Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Composer autoloader duplicating class file path for child class

I am using the composer autoloader (psr-4) to load my classes when I need them. I am running into an issue when I call a class from inside another class such as a model for a controller.

It works fine when I need to call the classes on their own but when I try to call one from inside the other it doesn’t seem to work.

My composer.json has the following for the autoloading:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

"autoload": {
    "psr-4": {
        "WhizzKids\\Controller\\": "controllers/",
        "WhizzKids\\Model\\": "models/"
    }
},

My controller is is called like so $AccountsController = new WhizzKids\Controller\AccountsController(); and the code in this file is:

<?php
namespace WhizzKids\Controller;

class AccountsController {
    private $AccountsModel;

    public function __construct() {
        $this->AccountsModel = new WhizzKids\Model\AccountsModel();
    }

    public function getAccounts() {
        return $this->AccountsModel->getAccounts();
    }
}

Within this controller I am trying to call my model which includes the logic for fetching from the database. The code in the model is:

<?php
namespace WhizzKids\Model;

class AccountsModel {
    private $conn;
    
    public function __construct() {
        $this->conn = mysqli_connect($_ENV['DB_SERVER'], $_ENV['DB_USER'], $_ENV['DB_PASSWORD'], $_ENV['DB_DATABASE']);
        if (!$this->conn) {
            die("Connection failed: " . mysqli_connect_error());
        }
    }

    public function getAccounts() {
        $sql = 'SELECT * FROM accounts';
        $result = mysqli_query($this->conn, $sql);
        $accounts = [];
        if(mysqli_num_rows($result) > 0) {
            // output data of each row
            while($row = mysqli_fetch_assoc($result)) {
                $accounts[] = $row;
            }
        } 
        mysqli_close($this->conn);
        return $accounts;
    }
}

When I try to load the view that uses this on the front-end i get the following error:
error message

As you can see in the error message it seems to be prepending the previous namespace onto the child namespace, not sure where i’m going wrong? (also open to any improvements)

>Solution :

Your problem is related to how namespaces and classes are referred to in PHP. When you’re inside a namespace and you try to instantiate a class with a new keyword, PHP thinks you’re referring to a class that exists within the current namespace.

If you want to refer to a class in a different namespace, you have two options. You can either use the fully qualified class name (including the leading ), or you can include a use statement at the top of your file.

So, you could update your AccountsController class as follows:

<?php
namespace WhizzKids\Controller;

use WhizzKids\Model\AccountsModel;

class AccountsController {
    private $AccountsModel;

    public function __construct() {
        $this->AccountsModel = new AccountsModel();
    }

    public function getAccounts() {
        return $this->AccountsModel->getAccounts();
    }
}

Or you could use the fully qualified name in your __construct function:

public function __construct() {
    $this->AccountsModel = new \WhizzKids\Model\AccountsModel();
}

Remember, when you are using namespaces in PHP, if you want to refer to a global class (like those in the root namespace, including built-in PHP classes), you need to precede them with a . So if you want to use a global class in your namespace, for example, the Exception class, you would need to refer to it as \Exception.

The same principle applies here. By using \WhizzKids\Model\AccountsModel, you’re saying "look for this class in the root () namespace, then in the WhizzKids\Model namespace".

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading