Search code examples
phpdrupal-7namespaces

Are namespaces in PHP "inherited"?


EDIT:

Yes the problem was using \ at the beginning of the use statement. As M1ke pointed out, use goes from the root element.

Original post

I think is a PHP question but it may be Drupal.

I'm working on a headless Drupal project where is using a class (which I call Entity Model) that uses a Drupal class called EntityFieldQuery.

Before a create or use this class I bootstrap Drupal using:

require_once DRUPAL_ROOT.'/includes/bootstrap.inc';

drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);

The entity model class is in the Models names space like so:

namespace Models;

use \EntityFieldQuery;

class EntityModel
{

    .....

     $query = new EntityFieldQuery();
     $query->doSomething();

    ......
}

The EntityFieldQuery is found perfectly as I use the "\" because this class is out of the Models namespace.

The problem is when this class is created is uses other classes that don't use any namespace, and I have the following error:

class Models\InsertQuery not found in ....

Here is the class used by EntityFieldQuery that uses InsertQuery

class InsertQuery_mysql extends InsertQuery ...

I don't understand why InsertQuery_mysql is found but InsertQuery

I ended up adding a "\" in InsertQuery to fix the problem like so:

class InsertQuery_mysql extends \InsertQuery ...

Actually this class in a php file called query.inc that contains two defitinion classes (in the same file, I don't know this is a a problem too)

class InsertQuery_mysql extends InsertQuery 
....
class TruncateQuery_mysql extends TruncateQuery

I thought that if I use "new \ClassName()" the "default namespace" inside this class would be "\" too and not the first called class's namespace.

I don't like to modify 3rd party libraries, is any way to avoid this? I guess is a architecture problem rather than a lack of definition if someone has a better idea, I appreciate.

Thanks!

EDIT2: Adding more info...

In order of execution.

index.php:

require_once 'vendor/autoload.php';
require_once DRUPAL_ROOT.'/includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
...

app/SiteController.php:

use Models\Campaign;
class SiteController {
   ...
   $campaing = new Campaign();
   ... 

app/Models/Campaing.php:

namespace Models;
class Campaign extends EntityModel {
...

app/Models/EntityModel.php:

namespace Models;

use \EntityFieldQuery; //<-- this should go without \ as I say in EDIT section
class EntityModel {
...
public function getAll() {
   $query = new EntityFieldQuery(); //<--throwed Models\InsertQuery not found. It must have \ at the beginning of the class name. 

Solution

  • To answer the base question (and pending further code) PHP namespaces are set by whichever namespace is declared in the file.

    // Bar.php
    
    namespace Foo;
    
    class Bar {}
    
    // some other file
    
    use Foo\Bar;
    
    $test = new Bar(); //works
    
    // different file
    
    namespace Foo;
    
    $test = new Bar(); // works
    
    // another file
    
    require 'Bar.php';
    
    // won't work because we are not in namespace "Foo"
    $test = new Bar(); 
    

    In your specific case it the use \EntityLoader should be use EntityLoader because you're exiting the namespace you want to be inside.