将 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,这有助于与其他自动加载器兼容。
我正在更新一个项目,我决定更新我的 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,这有助于与其他自动加载器兼容。