Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to load all classes of a namespace?

Tags:

namespaces

php

I hate PHP namespaces. They don't work as normal ones, or at least as I expect. Anyway, since I'm trying to write a small library, I have to deal with them, and I was wondering if you can manage to treat them as you would for C# or Java, maybe using spl_autoload_* functions. Something like:

Library:

<?php
namespace A
{
    class MyAClass {...}
}

namespace A\B
{
    class MyBClass {...}
}
?>

and the app:

<?php
include("library\autoloader.php");

use A; //Loads every class in A namespace
use A\B; //Loads every class in A\B namespace

$obj = new MyAclass();
$obj2 = new MyBCLass();
?>

I tried simply:

<?php
function autoload($name)
{
    //echo "loading {$name}.php<br />";
    require_once($name.".php");
}
spl_autoload_register("autoload");
?>

but I'm forced to do this:

<?php
include("Library\autoload.php");

$obj = new MyNamespace\MyClass();
?>

I'd like to do something like this indeed:

<?php
include("Library\autoload.php");

use MyNamespace;    

$obj = new MyClass();
?>
like image 988
Phate01 Avatar asked Oct 21 '25 08:10

Phate01


2 Answers

  1. No you cannot load all classes in a namespace. A namespace is literally just an addition to the class/function naming system, it has no intrinsic connection to files or such. Since classes are "loaded" by including their file, and since namespaces are not linked to files, there could be any number of files in any number of places in your filesystem which contain classes of a namespace. There's no way for PHP to locate those automagically.
  2. You can simply load all files in a folder by looping over a glob result and include. If you organise your files according to namespaces, that'll "load all classes in a namespace."
  3. You shouldn't really do this and instead use autoloaders, which include files as needed when needed. That requires you to write a correct autoloader, its unclear what the issue is with yours. In order to use autoloaders effectively you should use one file per class named after the class. Your autoloader will also need to construct the correct relative path.
  4. use does not load a class. use only aliases a namespaced name into a shorter or alternative name within the current file. The class is only loaded the first time it's required; e.g. when you write new Foo or extends Foo.

If you want to be able to write something like use Foo\* and then refer to all classes within Foo by their bare name: that's not possible in PHP. The best you can do is to shorten the namespace prefix, e.g. use Foo\Bar as B, then use B\Baz everywhere.

like image 170
deceze Avatar answered Oct 23 '25 00:10

deceze


To extend from the comment by @halfer, your last codeblock is invalid PHP.

To illustate what you can do (as mentioned by @halfer again, you should use 1 class per file):

namespace Vendor\Package;
class AClass{}

To initialize this you can either do:

$a = new Vendor\Package\AClass();

or

use Vendor;
$a = new Vendor\Package\AClass();

or

use Vendor\Package;
$a = new Package\AClass();

or

use Vendor\Package\AClass;
$a = new AClass();

or

use Vendor\Package\AClass as B;
$a = new B();

or

use Vendor\Package as C;
$a = new C\AClass;

I hope you get the gist of it :)

Also, to fully utilize the power of namespacing, you should organize your files into folders according to their namespace and use an autoloader, e.g. the example above should give you the following folder structure:

Vendor
  Package
    AClass.php

Look into http://www.php-fig.org/psr/psr-4/ for a generally accepted convention for Autoloading

like image 38
Populus Avatar answered Oct 22 '25 22:10

Populus