2

I have installed Propel ORM with Composer but I cannot create a new model as the PHP script is not in the same directory as the PHP class.

I have class Test inside Test.php and I want to use it from subfolder/index.php. Note that class Test then uses Base/Test from Base/Test.php, so using require() is not an option here as Base/Test just goes on to use even more classes generated by composer.

Traditionally, I'm supposed to do the following:

<?php
   use Test;
?>

but since I have Test in the parent folder, I cannot do that, and obviously

<?php
   use ../Test;
?>

doesn't work.

My folder structure:

My Project
|-- Base
|   `-- Test.php <-- File referenced by `Test` class
|-- subfolder
|   `-- index.php <-- File I want to use `Test` from
`-- Test.php <-- File containing `Test` class

The Actual Code: subfolder/index.php:

<?php 
use \Test;
    require __DIR__ . '/../vendor/autoload.php';
    $test = new Test();
?>

Test.php:

<?php
use Base\Test as BaseTest;

class Test extends BaseTest
{

}
Sunny Patel
  • 7,830
  • 2
  • 31
  • 46
Kevin Pei
  • 5,800
  • 7
  • 38
  • 55

2 Answers2

3

Test is a namespace and has literally nothing to do with folder structure. Namespaces have a folder-like structure, but you cannot use relative paths.

PSR-4 autoloaders, such as what most Composer packages use these days, map their namespaces in a way that very closely matches the folder structure, but they are still entirely separate concepts.

If you have declared a namespace in a file all subsequent names are considered to be relative to that path. eg:

namespace Foo;

class Bar {}; // \Foo\Bar

If you want to use something outside of the current namespace you need to declare the full path, beginning with \ which signifies the root namespace. eg:

namespace Foo;
use \Test

class Bar { // \Foo\Bar
  public function test() {
    $test = new Test();
    $dbh = new \PDO();
  }
}
Sammitch
  • 30,782
  • 7
  • 50
  • 77
  • I'm still a little confused as to how the "root" namespace is defined. So for example, I put `namespace Foo;` in both `Test.php` and `index.php`, but `use \Test` from `index.php` still doesn't work. I have updated my question with the actual code of `Test.php` and `index.php` prior to the namespace modification – Kevin Pei Sep 25 '15 at 20:41
  • adding `Test.php` and `Base/` to the composer autoload classmaps made everything work - thank you for informing me that these aren't based off of folder structure! – Kevin Pei Sep 25 '15 at 20:54
  • 1
    @KevinPei Bah, I was just about finished typing that out in long-form. Glad you got it working. – Sammitch Sep 25 '15 at 20:55
  • 1
    You wouldn't normally start the `use` clause with a backslash because the argument always has to be a fully qualified namespace identifier - you cannot `use` something with a relative path. – Sven Sep 26 '15 at 11:03
1

Just set all the folder that you want in the composer.json file. Like this:

"autoload": {
    "psr-4": {
        "App\\": "app/",
        "Config\\": "config/"
    },
    "files": [
        "config/config.php"
    ]
},

Search about the composer.json tho learn more about it. For the example above i chose the namespaces "App" and "Config" for the directories "app/" and "config/" in the root directory of my project AND chose the file "config/config.php" to be running BEFORE any action in my project.