当我在index.php
中使用autoloader时,它可以正常工作,但是当我在index.php
中创建一个对象,并且这个对象必须创建其他对象(它们都在同一个名称空间中)时,它抛出错误Uncaught Error: Class 'xxx' not found in (...)
。
我的composer.json
如下所示:
{
"autoload": {
"psr-4": {
"pizzaCase\\": "src",
"Connection\\": "src/Connection/",
"Elements\\": "src/Elements/"
}
},
"require": {
"cboden/ratchet": "^0.4"
}
}
我的index.php
如下所示:
<?php
require_once __DIR__. '/vendor/autoload.php';
require_once __DIR__."/src/config.php";
use Connection\Database;
use Elements\Form;
use Elements\FormElement;
use Elements\FormElementRadio;
// Database::init();
$form = new Form();
$data["options"] = "soemthing, something else";
$form->addElement("", "pizza", "", "Choose pizza", "radio", $data);
?>
在addElement
方法中,我创建了一个对象,该对象也在src/Elements/
名称空间中,但是它抛出了上面提到的错误。addElement
方法的主体如下所示:
<?php
namespace Elements;
class Form
{
public static $leftSize = 3;
protected $elements = [];
public function addElement($table, $name, $value, $label=false, $type = false, $data = false)
{
$type = ucfirst($type);
$class = "FormElement{$type}";
//FAILS HERE
if(class_exists($class))
{
//CLASS EXISTS, CREATE OBJECT FROM RESPECTIVE CLASS
$form = new $class($table, $name, $value, $label, $type, $data);
$this->elements[$name] = $form;
}
}
}
我做错了什么(或者遗漏了什么)?为什么autoloader * 可以 * 从index.php自动加载它,但是我创建的对象不能在autoloader失败的情况下创建其他对象?
2条答案
按热度按时间e0bqpujr1#
区别不在于代码在哪里运行;不同之处在于,失败的代码试图选择要“动态”加载的类。
在PHP中,名称空间本质上是一个编译时功能:在运行任何代码之前,编译器会查看所有不以
\
开头的类名引用,并将当前命名空间作为前缀,或者根据您在use
语句中指定的规则。当代码运行时,当前命名空间和use语句根本不可见。当动态指定类名时,编译器只看到字符串,而不是类名,所以不去管它。然后当代码运行时,查找的类名被假定为完全指定的,而不是相对于当前命名空间或use语句。
因此解决方案很简单--在创建动态类名时指定完整的命名空间:
你也可以使用magic constant
__NAMESPACE__
让编译器替你替换 current 命名空间名称(显然,这仍然不能解释任何use
语句):或者,如果要在一组特定的类之间进行选择,则可以使用
::class
语法在编译时基于当前命名空间和任何有效的use
语句生成字符串:ffdz8vbo2#
这可能是因为src目录有多个名称空间。
通常您只需为src创建一个名称空间,如下所示
然后使用PizzaCase\Elements和PizzaCase\Connections作为名称空间