现在 PHP 开发基本上都用上 composer,大部分我们都只是下面一句话引入 composer
require_once __DIR__.'/vendor/autoload.php';
这里面其实有很多东西,很多组件的助手会人手一个助手函数,每次请求会载入很多用不到的助手函数和一些类映射,例如 laravel 框架。
[0] => /data/codes/blog/public/index.php
[1] => /data/codes/blog/vendor/autoload.php
[2] => /data/codes/blog/vendor/composer/autoload_real.php
[3] => /data/codes/blog/vendor/composer/ClassLoader.php
[4] => /data/codes/blog/vendor/composer/autoload_static.php
[5] => /data/codes/blog/vendor/symfony/polyfill-mbstring/bootstrap.php
[6] => /data/codes/blog/vendor/symfony/polyfill-php72/bootstrap.php
[7] => /data/codes/blog/vendor/symfony/polyfill-php72/Php72.php
[8] => /data/codes/blog/vendor/symfony/var-dumper/Resources/functions/dump.php
[9] => /data/codes/blog/vendor/swiftmailer/swiftmailer/lib/swift_required.php
[10] => /data/codes/blog/vendor/swiftmailer/swiftmailer/lib/classes/Swift.php
[11] => /data/codes/blog/vendor/paragonie/random_compat/lib/random.php
[12] => /data/codes/blog/vendor/laravel/framework/src/Illuminate/Foundation/helpers.php
[13] => /data/codes/blog/vendor/laravel/framework/src/Illuminate/Support/helpers.php
[14] => /data/codes/blog/vendor/myclabs/deep-copy/src/DeepCopy/deep_copy.php
[15] => /data/codes/blog/vendor/psy/psysh/src/Psy/functions.php
Tp5,yii2,phalcon 好像可以有自己的去实现类加载器,我想为啥子我要载入多么多东西,所以我改进了一个 composer 的载入
/**
* ---------------------------------------------------------------
* Composer
* ---------------------------------------------------------------.
*
* 用于管理 PHP 依赖包
* 优化 composer 性能,优先载入 composer 注册的 Psr4
* 如果 Psr4 不存在,才会去初始化 composer 加载,使得大部分请求不走 composer 的自动载入
* 如果你使用的包是比较新的,基本都遵循 Psr4 规则,这个时候会提升一部分性能
* 对于助手函数需要自己引入
*/
$psr4s = include_once __DIR__.'/../vendor/composer/autoload_psr4.php';
require_once __DIR__.'/../vendor/hunzhiwange/framework/src/Queryyetsimple/Bootstrap/function.php';
spl_autoload_register(function ($className) use ($psr4s) {
static $loadedComposer;
$name = explode('\\', $className);
$topLevel = '';
for($i = 0; $i <= 2; $i++) {
$topLevel .= $name[$i].'\\';
if (isset($psr4s[$topLevel])) {
foreach ($psr4s[$topLevel] as $dir) {
$file = $dir.'/'.str_replace('\\', '/', substr($className, strlen($topLevel))).'.php';
if (is_file($file)) {
return require_once $file;
}
}
//return;
}
}
if (null === $loadedComposer) {
$composer = require_once __DIR__.'/../vendor/autoload.php';
$composer->loadClass($className);
$loadedComposer = true;
}
});
这使得每次载入
/data/codes/queryphp/www/index.php
/data/codes/queryphp/vendor/composer/autoload_psr4.php
/data/codes/queryphp/vendor/hunzhiwange/framework/src/Queryyetsimple/Bootstrap/function.php
/data/codes/queryphp/vendor/hunzhiwange/framework/src/Queryyetsimple/Bootstrap/Project.php
/data/codes/queryphp/vendor/hunzhiwange/framework/src/Queryyetsimple/Di/Container.php
/data/codes/queryphp/vendor/hunzhiwange/framework/src/Queryyetsimple/Di/IContainer.php
/data/codes/queryphp/vendor/hunzhiwange/framework/src/Queryyetsimple/Kernel/IProject.php
只载入 composer/autoload_psr4.php ,如果遇到不是 psr4 这种类才去载入完整的 composer,助手函数需要自己引入,需要的地方手动载入,比如 swagger 那个做当。
/**
* 生成 swagger.
*
* @return \Swagger\Annotations\Swagger
*/
protected function makeSwagger()
{
require_once \Leevel::path().'/vendor/zircote/swagger-php/src/functions.php';
return \Swagger\scan($this->swaggerScan);
}
这样子可以两全其美,实现代价很小,干净。
基本上 3 层 psr4 基本可以完整覆盖所有组件,下面是 lavavel prs4 注册的。只有 Symfony 的组件有 3 层目录。
<?php
// autoload_psr4.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
'phpDocumentor\\Reflection\\' => array($vendorDir . '/phpdocumentor/reflection-common/src', $vendorDir . '/phpdocumentor/reflection-docblock/src', $vendorDir . '/phpdocumentor/type-resolver/src'),
'XdgBaseDir\\' => array($vendorDir . '/dnoegel/php-xdg-base-dir/src'),
'Whoops\\' => array($vendorDir . '/filp/whoops/src/Whoops'),
'Webmozart\\Assert\\' => array($vendorDir . '/webmozart/assert/src'),
'TijsVerkoyen\\CssToInlineStyles\\' => array($vendorDir . '/tijsverkoyen/css-to-inline-styles/src'),
'Tests\\' => array($baseDir . '/tests'),
'Symfony\\Polyfill\\Php72\\' => array($vendorDir . '/symfony/polyfill-php72'),
'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
'Symfony\\Component\\VarDumper\\' => array($vendorDir . '/symfony/var-dumper'),
'Symfony\\Component\\Translation\\' => array($vendorDir . '/symfony/translation'),
'Symfony\\Component\\Routing\\' => array($vendorDir . '/symfony/routing'),
'Symfony\\Component\\Process\\' => array($vendorDir . '/symfony/process'),
'Symfony\\Component\\HttpKernel\\' => array($vendorDir . '/symfony/http-kernel'),
'Symfony\\Component\\HttpFoundation\\' => array($vendorDir . '/symfony/http-foundation'),
'Symfony\\Component\\Finder\\' => array($vendorDir . '/symfony/finder'),
'Symfony\\Component\\EventDispatcher\\' => array($vendorDir . '/symfony/event-dispatcher'),
'Symfony\\Component\\Debug\\' => array($vendorDir . '/symfony/debug'),
'Symfony\\Component\\CssSelector\\' => array($vendorDir . '/symfony/css-selector'),
'Symfony\\Component\\Console\\' => array($vendorDir . '/symfony/console'),
'Ramsey\\Uuid\\' => array($vendorDir . '/ramsey/uuid/src'),
'Psy\\' => array($vendorDir . '/psy/psysh/src/Psy'),
'Psr\\SimpleCache\\' => array($vendorDir . '/psr/simple-cache/src'),
'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
'Psr\\Container\\' => array($vendorDir . '/psr/container/src'),
'PhpParser\\' => array($vendorDir . '/nikic/php-parser/lib/PhpParser'),
'NunoMaduro\\Collision\\' => array($vendorDir . '/nunomaduro/collision/src'),
'Monolog\\' => array($vendorDir . '/monolog/monolog/src/Monolog'),
'League\\Flysystem\\' => array($vendorDir . '/league/flysystem/src'),
'Laravel\\Tinker\\' => array($vendorDir . '/laravel/tinker/src'),
'Illuminate\\' => array($vendorDir . '/laravel/framework/src/Illuminate'),
'Fideloper\\Proxy\\' => array($vendorDir . '/fideloper/proxy/src'),
'Faker\\' => array($vendorDir . '/fzaninotto/faker/src/Faker'),
'Egulias\\EmailValidator\\' => array($vendorDir . '/egulias/email-validator/EmailValidator'),
'Dotenv\\' => array($vendorDir . '/vlucas/phpdotenv/src'),
'Doctrine\\Instantiator\\' => array($vendorDir . '/doctrine/instantiator/src/Doctrine/Instantiator'),
'Doctrine\\Common\\Inflector\\' => array($vendorDir . '/doctrine/inflector/lib/Doctrine/Common/Inflector'),
'DeepCopy\\' => array($vendorDir . '/myclabs/deep-copy/src/DeepCopy'),
'Cron\\' => array($vendorDir . '/dragonmantank/cron-expression/src/Cron'),
'Carbon\\' => array($vendorDir . '/nesbot/carbon/src/Carbon'),
'App\\' => array($baseDir . '/app'),
);
我觉得可以。
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.