php - 为什么 Codeigniter 在验证路由时不接受自动加载 Controller 类?

标签 php codeigniter autoload

为什么 Codeignitor 在验证路由时不接受 Composer 自动加载中的 Controller ?

它通过以下方式进行检查:class_exists($class, FALSE),其中第二个参数禁用自动加载检查。

https://github.com/bcit-ci/CodeIgniter

    $e404 = FALSE;
    $class = ucfirst($RTR->class);
    $method = $RTR->method;

    if (empty($class) OR ! file_exists(APPPATH.'controllers/'.$RTR->directory.$class.'.php'))
    {
        $e404 = TRUE;
    }
    else
    {
        require_once(APPPATH.'controllers/'.$RTR->directory.$class.'.php');

        if ( ! class_exists($class, FALSE) OR $method[0] === '_' OR method_exists('CI_Controller', $method))
        {
            $e404 = TRUE;
        }
        elseif (method_exists($class, '_remap'))
        {
            $params = array($method, array_slice($URI->rsegments, 2));
            $method = '_remap';
        }
        elseif ( ! method_exists($class, $method))
        {
            $e404 = TRUE;
        }
        /**
         * DO NOT CHANGE THIS, NOTHING ELSE WORKS!
         *
         * - method_exists() returns true for non-public methods, which passes the previous elseif
         * - is_callable() returns false for PHP 4-style constructors, even if there's a __construct()
         * - method_exists($class, '__construct') won't work because CI_Controller::__construct() is inherited
         * - People will only complain if this doesn't work, even though it is documented that it shouldn't.
         *
         * ReflectionMethod::isConstructor() is the ONLY reliable check,
         * knowing which method will be executed as a constructor.
         */
        elseif ( ! is_callable(array($class, $method)))
        {
            $reflection = new ReflectionMethod($class, $method);
            if ( ! $reflection->isPublic() OR $reflection->isConstructor())
            {
                $e404 = TRUE;
            }
        }
    }

最佳答案

查看 git 历史记录,更改是在 49e68de96b420a444c826995746a5f09470e76d9 中引入的,提交消息为:

Disable autoloader call from class_exists() occurences to improve performance

Note: The Driver libary tests seem to depend on that, so one occurence in CI_Loader is left until we resolve that.

所以名义上的原因是性能。

如果您想确保在每个请求上加载 Controller 类,您可以将文件显式添加到 Composer autoload.files属性,如下所示:

composer.json
{
    "autoload": {
        "files": [
            "src/Foo.php"
        ]
    },
    "name": "test/64166739"
}
src/Foo.php
<?php
class Foo {}
测试.php
<?php
$loader = require('./vendor/autoload.php');
var_dump(class_exists('Foo', false));

运行时(例如通过 php test.php),我们得到以下输出:

bool(true)

附加

查看对 class_exists 的调用周围的代码, Controller 文件似乎应该遵循约定,例如使用内置的 Welcome Controller 和默认设置,定义它的文件应该存在于:

application/controllers/Welcome.php

因此,在 require_once 该文件之后,对 class_exists 的调用是一个相当简单的健全性检查,以确保该文件确实定义了该类。因此,基于关于如何将 Controller 添加到 CodeIgniter 应用程序的假设(即所有 Controller 都在 application/controllers 目录中,并且命名与它们定义的类相同),在以下情况下绕过自动加载器是合理的:执行该检查。

如果您想确保 Controller 在需要时以 CodeIgniter 方式加载,则应将它们添加到上面列出的应用程序中。

关于php - 为什么 Codeigniter 在验证路由时不接受自动加载 Controller 类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64166739/

相关文章:

php - 无法将行复制到同一个表(php-mysql)

php - 更改模块的 uri,而不重命名 PyroCMS 中的类

php - Composer,我的包中的类没有在使用它的应用程序中自动加载

php - mysql - 一次更新两条记录

php - 按事件 PHP 显示画廊

php - 在带有自动加载器的错误处理程序中使用 MySQLi 扩展类

php - 在 php 中找不到类

php - 像在 php 中一样在 nodejs 中渲染 html

php - 我在 WAMP 安装的 httpd.conf 中输入了错误的信息...

php - Codeigniter 预订功能 - 每天限制预订 1 小时