I did brows through that question page but the answers given, I felt, didn\'t sufficiently answer the question I was struggling with.
I have a little php project. In this
Remove the line
include('./Class1.php');
Unless you've specified the full path to the include file, PHP will always try to resolve files according to the location of the entry script. In your case, your entry script seems to be app.php
at the root of the application.
So in your Class2.php
, instead of include('./Class1.php');
, you should write include('Models/Class1.php');
and things should work. But while it fix a short term problem, your code would be really non-portable. Besides, including the same file twice would result in another error (e.g. re-declaring class).
A slightly smarter would be to do this in Class2.php
instead.
<?php
// Class2.php
namespace Models\Class2;
use \Models\Class1\Class1;
include_once __DIR__ . '/Class2.php';
/**
* Class2 does other things
*/
class Class2 extends Class1 {
public function someMethod() {
// code
}
}
The variable __DIR__
will always be resolved to the directory of the script file, not the entry script.
But again, it is clumsy and error prone to do file includes by hand.
PHP supports file autoloading when a class is declare. That is to have a piece of code to do the file include when a class is called. If you want to have fun, you're welcome to write your own autoloader function and register to spl_autoload_register. With a combination of the __DIR__
technique we talked about, you can easily resolve the autoloading path from namespace.
A quick and ugly autoloading app.php
would probably look like this:
<?php
// app.php
use Models\Class1\Class1;
use Models\Class2\Class2;
spl_autoload_register(function ($class_name) {
$realClassName = basename(str_replace('\\', DIRECTORY_SEPARATOR, $class_name));
include_once __DIR__ . DIRECTORY_SEPARATOR . 'Models' . DIRECTORY_SEPARATOR . $realClassName . '.php';
});
$c1 = new Class1();
$c2 = new Class2();
If you're learning OOP PHP today, I'd highly recommend you to learn Composer and PSR-4. PSR-4 defines how you should structure a PHP application for class autoloading. Composer implements a PSR-4 autoloader by default.
First you should comply with the namespace standard. The least change to do is to loose the extra "Class1" and "Class2" in your namespace:
<?php
// Class1.php
namespace Models;
/**
* Class1 does things
*/
class Class1 {
public function someMethod() {
// code
}
}
<?php
// Class2.php
namespace Models;
use \Models\Class1;
/**
* Class2 does other things
*/
class Class2 extends Class1 {
public function someMethod() {
// code
}
}
With a nicely structured application folder, namespace structure and a correctly written autoload.psr-4 section in composer.json
, composer will help you to generate a class autoloader. Your composer.json would probably look like this:
{
"autoload": {
"psr-4": {
"Model\\": "Model/"
}
}
}
You may now run composer dump-autoload
to create the autoloader. Then you can simply add this to your entry script app.php
. When things are ready, you may simply add use
and new
statement anywhere in the application.:
<?php
// app.php
use Models\Class1;
use Models\Class2;
require_once './vendor/autoload.php';
$c1 = new Class1();
$c2 = new Class2();
All includes are handled by the autoloader. Hands free.