将 Composer 与现有项目自动加载器集成

Integrate Composer with existing project autoloader

我正在更新一个项目,我决定更新我的 Twig 版本。我过去故意没有更新它,因为你现在需要使用 Composer,但我最终屈服于此并决定安装更新的版本。

但是,它会影响我的自动加载功能,无法正确加载 Twig,我真的不想使用它。在一个只有自动加载 Composer 代码的空白文件中,它可以工作,所以我知道我的自动加载器发生冲突。我可以看出我将不得不在某种程度上使用它,因为 Twig 现在需要它。我只对将它用于第三方代码感兴趣,我不想将它用于任何其他用途。所以我正在寻找的是我自己的自动加载器首先尝试,然后如果我不能通过我自己的方式加载 class,尝试使用 Composer 自动加载器。第三方代码存在于“Lib”的子目录中。所以对于 Twig,它位于 Lib/vendor/twig/twig/src.

目前,我正在检查命名空间的第一部分,如果它与我自己的不匹配,我将尝试在 Lib/vendor/autoload 中加载 Composer autoload.php 文件。 php,然后从我的自动加载功能中返回。但这似乎没有找到 class.

我想做的事情真的可行吗?我将如何处理这样的事情?

** 编辑 - 当前自动加载器 **

public static function autoloader($classname)
{
    /* Separate by namespace */
    $bits = explode('\', ltrim($classname, '\'));
    $vendor = array_shift($bits);

    /* If this doesn't belong to us, ignore it */
    if ($vendor !== 'Site')
    {
        // We don't want to interfere here
        if ($vendor == 'Forum')
            return;

        // Try to see if we can autoload with Composer, if not abort
        include_once(SITE_ROOT.'include/Lib/vendor/autoload.php');
print_r(spl_autoload_functions ( ));
        return;
    }

    $class = array_pop($bits);
    $namespace = empty($bits) ? 'Site' : ('Site\'.implode('\', $bits));

    $sources_dir = false;
    $path = SITE_ROOT.'include/';
    foreach (array_merge($bits, array($class)) as $i => $bit)
    {
        if ($i === 0 && $bit == 'Lib')
        {
            $bit = mb_strtolower($bit);
            $sources_dir = true;
        }
        else if (preg_match("/^[a-z0-9]/", $bit)) // Applications only contain lowercase letters
        {
            if ($i === 0)
                $path .= 'apps/';
            else
                $sources_dir = true;
        }
        else if ($i === 1 && ($bit == 'Api' || $bit == 'Cli' || $bit == 'Ajax')) // The API/CLI/AJAX interfaces have slightly different rules ....
        {
            $bit = mb_strtolower($bit);
            $sources_dir = true;
        }
        else if ($sources_dir === false)
        {
            if ($i === 0)
            {
                $path .= 'components/';
            }
            else if ($i === 1 && $bit === 'Application')
            {
                // Do nothing
            }
            else
            {
                $path .= 'sources/';
            }

            $sources_dir = true;
        }

        $path .= $bit.'/';
    }

    /* Load it */
    $path = \substr($path, 0, -1).'.php';
    if (!file_exists($path))
    {
        $path = \substr($path, 0, -4).\substr($path, \strrpos($path, '/'));
        if (!file_exists($path))
        {
            return false;
        }
    }

    require_once($path);

    if (interface_exists("{$namespace}\{$class}", FALSE))
    {
        return;
    }

    /* Doesn't exist? */
    if (!class_exists("{$namespace}\{$class}", FALSE))
    {
        trigger_error("Class {$classname} could not be loaded. Ensure it has been properly prefixed and is in the correct namespace.", E_USER_ERROR);
    }
}

在自定义自动加载中加载 Composer 的 autoload.php 可能为时已晚。

您不必太担心性能问题,只需依次加载您的自定义自动加载器和 Composer 的自动加载器即可。您可以通过确定这些自动加载器的优先级来优化一些 类 您会更频繁地加载(您自己的或通过 Composer 安装的自动加载器)。

此外,您的 own/custom 自动加载器应该只关心加载是否成功,如果找不到则不会抛出错误。留给 PHP,这有助于与其他自动加载器兼容。