如何加载命名空间的所有类?

时间:2015-04-24 15:09:51

标签: php namespaces

我讨厌PHP命名空间。它们不像普通的那样工作,或者至少像我期望的那样。无论如何,因为我正在尝试编写一个小型库,我必须处理它们,我想知道你是否可以设法像对待C#或Java那样对待它们,可能使用spl_autoload_*函数。类似的东西:

库:

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

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

和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();
?>

我试过简单:

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

但我不得不这样做:

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

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

我想做这样的事情:

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

use MyNamespace;    

$obj = new MyClass();
?>

2 个答案:

答案 0 :(得分:6)

  1. 不,您无法加载命名空间中的所有类。命名空间实际上只是对类/函数命名系统的补充,它与文件等没有内在联系。由于类通过包含它们的文件而“加载”,并且由于名称空间没有链接到文件,因此文件系统中任何数量的位置都可以包含任意数量的文件,这些文件包含命名空间的类。 PHP无法自动找到它们。
  2. 可以通过循环glob结果和include来加载文件夹中的所有文件。如果根据命名空间组织文件,那么“将”加载命名空间中的所有类。“
  3. 你不应该真的这样做,而是使用自动加载器,在需要时根据需要包含文件。这需要你写一个正确的自动加载器,它不清楚你的问题是什么。为了有效地使用自动加载器,您应该为每个以类命名的类使用一个文件。您的自动加载器还需要构建正确的相对路径。
  4. use未加载课程。 use仅将命名空间名称别名为当前文件中的较短或替代名称。该类仅在第一次需要时加载;例如当您撰写new Fooextends Foo
  5. 如果您希望能够编写类似use Foo\*的内容,然后用它们的名字引用Foo中的所有类:这在PHP中是不可能的。您可以做的最好是缩短命名空间前缀,例如use Foo\Bar as B,然后到处使用B\Baz

答案 1 :(得分:3)

要从@halfer的注释扩展,您的最后一个代码块是无效的PHP。

为了说明你可以做什么<(再次提到@halfer,你应该为每个文件使用1个类):

namespace Vendor\Package;
class AClass{}

要初始化此功能,您可以执行以下操作:

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

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

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

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

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

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

我希望你得到它的要点:)

此外,为了充分利用命名空间的强大功能,您应该根据命名空间将文件整理到文件夹中,并使用自动加载器,例如:上面的例子应该给你以下文件夹结构:

Vendor
  Package
    AClass.php

查看http://www.php-fig.org/psr/psr-4/,了解一个普遍接受的自动加载惯例