Eines der frühesten Probleme, mit denen viele Freunde beim Erlernen von PHP konfrontiert sind, ist die Liebe und der Tod zwischen require, include und require_once, include_once.
Nachdem sie die Geschichte ihrer Liebe und ihres Todes verstanden haben, beginnen sie oft, den Rahmen zu verwenden. Das Framework ist sicherlich ein gutes Werkzeug für die Arbeit, aber wissen Sie, was passiert, wenn Sie normalerweise eine neue Klasse eröffnen? Haben Sie sich jemals gefragt, warum alles automatisch für uns geladen wird, wenn wir uns an die Vorgaben halten? Lassen Sie uns die Geheimnisse erforschen und entdecken.
Zeitleiste
Steam Age
Sehen Sie häufig Code wie diesen oben im PHP-Code?
require 'lionis.php'; require 'is.php'; require 'cool.php';
Wenn Sie nur ein paar PHP-Skripte einführen, ist das akzeptabel. Wenn Tausende von Skripten eingeführt werden, sind Explosionen unvermeidlich. Wenn Sie den Namen eines Skripts ändern, müssen Sie auch den Namen jedes Skripts ändern, das das geänderte Skript einführt. Kann es nicht explodieren? Wie kann ich es umgehen, diesen Satz überhaupt zu tippen?
Elektrisches Zeitalter
Im PHP-Elektrozeitalter tauchten die Funktionen __autoload und spl_autoload_register auf, um benutzerdefinierte automatische Ladestrategien zu registrieren.
Laienhaft ausgedrückt sind __autoload und spl_autoload_register eine Killerorganisation, und sie werden Killer (Funktionen) aus verschiedenen Ländern einstellen. Wenn wir jemanden (neu) loswerden möchten, müssen wir nur den Namen (Klassennamen) angeben, und der Rest „Killer“ hilft uns dabei.
__autoload
PHP 5 beginnt, dieses Funktionsportal bereitzustellen. Wenn die von Ihnen verwendete Klasse nicht gefunden werden kann, wird der Klassenname als Parameter in diese Funktion übergeben.
<?php// Lionis.phpclass Lionis { public function __construct() { echo '欧耶耶, 我就是 Lionis'; } }
<?php // index.php function __autoload($classname) { $filename = './' . $classname . '.php'; require_once $filename; } $lionis = new Lionis();
Ausgabe
欧耶耶, 我就是 Lionis
spl_autoload_register
Wenn unser Projekt sehr groß oder alt ist oder Sie ein junger Pionier sind, der gerne wirft, brauchen Sie Um es vorzustellen: Die Dinge haben unterschiedliche Spezifikationen. Wenn Sie sie alle in die Funktion __autoload einfügen, wird diese Funktion bald erweitert. Darüber hinaus ist __autoload global eindeutig und kann Fehler verursachen, wenn es von anderen belegt wird. (Um eine Person sterben zu lassen, muss sie es zuerst anschwellen lassen.)
PHP 5.1.2 beginnt mit der Bereitstellung dieses Funktionsportals und registriert die gegebene Funktion als Implementierung von __autoload. Wenn wir daher einige Frameworks oder Plug-Ins verwenden, wird aus Kompatibilitätsgründen möglicherweise function_exists(spl_autoload_register) angezeigt.
<?php function lionisIsCoolFind($classname) { require './' . $classname . '.php'; } // 函数 spl_autoload_register('lionisIsCoolFind'); // 匿名函数 spl_autoload_register(function($require) { require './' . $classname . '.php'; }); // 类中的函数 spl_autoload_register(array('Lionis', 'loadClass'));
Oye, jetzt können wir viele verschiedene Autoloading-Funktionen schreiben.
Informationszeitalter
Meister, seien Sie vorsichtig, vor Ihnen steht ein Dämon! . Wenn jeder von uns seinen eigenen Satz an Autoloading-Methoden implementiert, verwendet jede PHP-Komponente und jedes PHP-Framework einen einzigartigen Autoloader, und jedes Framework verwendet eine andere Logik, um PHP-Klassen, -Schnittstellen und -Eigenschaften zu laden.
Wenn wir einige Frameworks von Drittanbietern verwenden, müssen wir auch den Autoloader in der Boot-Datei herausfinden. Das wird viel Zeit in Anspruch nehmen. PHP-FIG erkennt dieses Problem und empfiehlt die Verwendung der PSR-4-Spezifikation, um die Interoperabilität zwischen Komponenten zu fördern, sodass wir einen Autoloader verwenden können.
PSR-4 规范
利用命名空间的前缀和文件系统中的目录对应起来。
映射关系为
namespace => filePath \Lionis\Cool => cool
带有命名空间的类
<?php // 该文件为 cool/Real.phpnamespace \ Lionis\Cool;class Real { }
创建一个对象
<?php// 该文件为 index.php$lionis = new \ Lionis\Cool\Real;
这个时候,按照 PSR-4 的规范,自动加载器应该去加载 cool/ 目录下的 Real.php。
不对!那这样不是还要自己去实现 自动加载器 嘛,不然怎么 无中生有 出现 自动加载器 呢?难道官方 内置 了?
你 out 了吧,我们可以使用依赖管理器 composer 来生成 PSR-4 自动加载器。你可能会疑问,那我的旧项目没有遵循 PSR-4 规范怎么办?嘿嘿,让我们来探索发现一下 composer 是怎么解决这个问题的吧。
Composer
哦吼吼,我们这次的重点在与探究自动加载,所以 composer 的安装和使用等,就不去讨论了。
composer 自动加载设置了 4种 加载方式:
PSR-0
PSR-4
classmap
files
PSR-0
要求命名空间和目录层层对应,且可以使用 _ 作为路径分隔符,但是这会导致目录结果变得过深。
在 composer 执行 install 等操作时,composer 会把文件中的配置存储在 vendor/composer/autoload_psr0.php文件中的返回数组中。
例如:定义了Very\Good=>vendor\Lionis\IsReal\Cool,在调用 use Very\Good\Love\SomeClass,PSR-0 加载的实际目录为 vendor/Lionis/IsReal/Cool/Very/Good/Love/SomeClass.php。
对吧,这简直深得吓人,所以 PSR-0 被官方废除了。但是一些主流的框架已经实现了 PSR-0,为了向下兼容还是要实现 PSR-0。
composer.json配置:
"autoload": { "psr-0": { "Very\\Good": "vendor\Lionis\IsReal\Cool" } }
PSR-4
PSR-4 是现在比较推荐的方法,用于替代 PSR-0。
与 PSR-0 不同的是,取消掉了 _ 作为分隔符和目录结构。
在 composer 执行 install 等操作时,composer 会把文件中的配置存储在 vendor/composer/autoload_psr4.php文件中的返回数组中。
例如:定义了Very\Good=>vendor\Lionis\IsReal\Cool,在调用 use Very\Good\
Love\SomeClass,PSR-4 加载的实际目录为 vendor/Lionis/IsReal/Cool/Love/SomeClass.php。
composer.json配置:
"autoload": { "psr-4": { "Very\\Good": "vendor\Lionis\IsReal\Cool" } }
classmap
classmap 通过配置指定的目录和文件,在 composer 执行 install 等操作时,composer 会去扫描对应的目录下以.php结尾的文件中的 class,并存储在 vendor/composer/autoload_classmap.php文件中的返回数组中。
composer.json配置:
"autoload": { "classmap": [ "Lionis/", "Xiaoer/" ] }
如果 Lionis 下有一个叫 VeryCool的文件,那么在vendor/composer/autoload_classmap.php 中会生成。
<?php // autoload_classmap.php @generated by Composer $vendorDir = dirname(dirname(__FILE__)); $baseDir = dirname($vendorDir); return array( 'VeryCool' => $baseDir . '/Lionis/VeryCool.php', // 其他的映射 );
files
files 就是直接简单粗暴的加载文件。在 composer 执行 install 等操作时,composer 会把文件中的配置存储在vendor/composer/autoload_static.php文件中的生成一个 $files 数组。
composer.json 配置:
"autoload": { "files": ["Lionis/Very/Cool.php"] }