PSR4自动加载器不会从类中自动加载

发布于 2025-01-24 02:06:44 字数 1829 浏览 2 评论 0原文

当我在index.php中使用它时,自动加载器起作用,但是当我在index.php中创建一个对象时,此对象必须创建其他对象(这些对象都在相同的名称空间),它抛出了错误未被发现的错误:(...)中找不到类'xxx'。

我的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;
            }
        }
    }

我在做什么错(或丢失)?如何从index.php启用自动加载器可以自动加载它,但是我创建的对象不能在没有自动加载器失败的情况下创建其他对象?

The autoloader works when I use it in index.php, but when I create an object within index.php and this object has to create other objects (which are all in the same namespace), it throws the error Uncaught Error: Class 'xxx' not found in (...).

My composer.json looks like this:

{
    "autoload": {
        "psr-4": {
            "pizzaCase\\": "src",
            "Connection\\": "src/Connection/",
            "Elements\\": "src/Elements/"
        }
    },
    "require": {
        "cboden/ratchet": "^0.4"
    }
}

My index.php looks like this:

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

In the addElement method I then create an object which is also within the src/Elements/ namespace, but it throws the error mentioned above.

The body of my addElement method looks like this:

<?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;
            }
        }
    }

What am I doing wrong (or missing)? How come the autoloader can autoload it from index.php, but the object I create cannot create other objects without autoloader failing?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

夜光 2025-01-31 02:06:44

区别不与代码运行的位置有关。不同之处在于,失败的代码正在尝试选择要动态加载的类。

在PHP中,命名空间本质上是一个编译时间功能:在运行任何代码之前,编译器将查看所有不以\开头的类名的引用命名空间,或根据您指定的规则使用语句。当代码运行时,当前名称空间和使用语句根本看不到。

当您动态地指定类名时,编译器只是看到一个字符串,而不是类名称,因此单独将其留下。然后,当代码运行时,假定的类名称已完全指定,而不是相对于当前名称空间或使用语句。

因此,解决方案很简单 - 创建动态类名称时指定全名空间:

$class = "Elements\FormElement{$type}";

您还可以使用魔术常数__命名空间__ 让编译器替换为您的 current 代码>使用语句):

$class = __NAMESPACE__ . "\FormElement{$type}";

或者,如果您在之间选择了一组特定的类,则可以使用:: class语法在编译时生成字符串,以基于当前命名空间和任何使用语句有效:

$mapTypeToClassName = [
   'Radio' => FormElementRadio::class, // expands to 'Elements\FormElementRadio'
   'Select' => FormElementSelect::class,
   // etc
];
$class = $mapTypeToClassName[$type];

The difference is not to do with where the code is being run; the difference is that the failing code is trying to choose which class to load dynamically.

In PHP, namespaces are essentially a compile-time feature: before any of your code is run, the compiler looks at all references to class names which don't start with \, and prefixes them with the current namespace, or according to rules you've specified with use statements. When the code runs, the current namespace, and use statements, aren't visible at all.

When you specify a class name dynamically, the compiler just sees a string, not a class name, so leaves it alone. Then when the code runs, the class name looked up is assumed to be fully specified, not relative to the current namespace or use statements.

So the solution is simple - specify the full namespace when creating the dynamic class name:

$class = "Elements\FormElement{$type}";

You can also use the magic constant __NAMESPACE__ to have the compiler substitute the current namespace name for you (obviously, this still won't account for any use statements):

$class = __NAMESPACE__ . "\FormElement{$type}";

Alternatively, if you have a specific set of classes you are choosing between, you can use the ::class syntax to generate a string at compile time, based on the current namespace and any use statements in effect:

$mapTypeToClassName = [
   'Radio' => FormElementRadio::class, // expands to 'Elements\FormElementRadio'
   'Select' => FormElementSelect::class,
   // etc
];
$class = $mapTypeToClassName[$type];
荭秂 2025-01-31 02:06:44

可能是因为您为SRC目录有多个名称空间。

您只会为SRC创建一个命名空间

“psr-4": {
    "PizzaCase\\": "src"
}

通常,

It could be because you’re having multiple namespaces for the src directory.

Usually you would just create a namespace for src like this

“psr-4": {
    "PizzaCase\\": "src"
}

And then just use PizzaCase\Elements and PizzaCase\Connections as namespaces

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文