Patrick Manser
Patrick Manser

Reputation: 1183

Instantiate Class using namespaces

I have a function file, in which I put an __autodload() function. For my classes I want to use namespaces, since I'm learning about them. In the folder lib/ I have a DB class and a Test-User class. Code of those reads as follows:

DB.class.php

<?php
namespace App\Lib;

class DB
{
    public $db;

    function __construct($host, $username, $password, $database)
    {
        $this->db = new MySQLi($host, $username, $password, $database);
        if (mysqli_connect_error()) {
            die('Connect error');
        }
    }
}

User.class.php

<?php

namespace App\Lib;

class User
{
    private $_db;

    function __construct($db)
    {
        $this->_db = $db;
    }

    public function test()
    {
        echo '<pre>';
        print_r($this->_db);
        echo '</pre>';
    }
}

At this moment, my index file looks like this:

<?php

include 'functions.inc.php';

$db = new DB('localhost', 'root', '', 'test');
$user = new User($db);
$user->test();

And I'm getting the error Fatal error: Class 'DB' not found in C:\xampp\htdocs\tplsys\index.php on line 5

I've also tried $db = new \App\Lib\DB() and $db = new App\Lib\DB(), but it's always the same result... autoload function looks like this:

function __autoload($className)
{
    if (!file_exists('lib/' . $className . '.class.php')) {
        return FALSE;
    } else {
        require_once 'lib/' . $className . '.class.php';
    }
}

EDIT

I got it working with the help and links provided by sectus. The code now looks like this:

index.php

<?php
include 'functions.inc.php';

spl_autoload_register('autoload');

$db = new \Lib\DB('localhost', 'root', '', 'test');
$user = new \Lib\User($db);
$user->test();

autoload function:

function autoload($className)
{
    $className = ltrim($className, '\\');
    $fileName = '';
    $namespace = '';
    if ($lastNsPos = strrpos($className, '\\')) {
        $namespace = substr($className, 0, $lastNsPos);
        $className = substr($className, $lastNsPos + 1);
        $fileName = str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;
    }
    $fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.class.php';

    require $fileName;
}

Classes:

<?php

namespace Lib;

class DB
{
    public $db;

    function __construct($host, $username, $password, $database)
    {
        $this->db = new \MySQLi($host, $username, $password, $database);
        if (mysqli_connect_error()) {
            die('Connect Error (' . mysql_connect_errno() . ') ' . mysqli_connect_error());
        }
    }

}

I had to rename the namespace to Lib\ since it would look for app/lib/class.php otherwise... I'll just have to play with that a bit. Thanks for your help, guys!

Upvotes: 1

Views: 1119

Answers (1)

sectus
sectus

Reputation: 15464

You must use class with namespace with namespaces or aliases.

<?php

include 'functions.inc.php';

$db = new DB('localhost', 'root', '', 'test');// your DB class has no namespace
$user = new \App\Lib\User($db);               // <--- namespace added
$user->test();

And function __autoload($className) receive full class name (with namespace). So, when your __autoload function will execute it will recieve strings: 'DB', 'App\Lib\User'.

You should read about PSR-0 and use this implementation instead of yours.

Upvotes: 1

Related Questions