많은 친구들이 PHP를 배울 때 가장 먼저 직면하는 문제 중 하나는 require, include 및 require_once, include_once 사이의 사랑과 죽음입니다.
그들의 사랑과 죽음에 대한 이야기를 이해한 후에는 액자를 사용하기 시작하는 경우가 많습니다. 프레임워크는 확실히 작업에 좋은 도구이지만 일반적으로 새 클래스를 새로 만들면 어떤 일이 발생하는지 알고 계십니까? 사양을 따를 때 왜 모든 것이 자동으로 로드되는지 궁금한 적이 있습니까? 신비를 탐험하고 발견해 봅시다.
타임라인
Steam Age
PHP 코드 상단에서 이런 코드를 자주 보시나요?
require 'lionis.php'; require 'is.php'; require 'cool.php';
PHP 스크립트 몇 개만 소개한다면 괜찮습니다. 수천 개의 스크립트가 도입되면 폭발은 불가피합니다. 스크립트의 이름을 변경하면 변경된 스크립트를 소개하는 각 스크립트의 이름도 변경해야합니까? 이 문장을 타이핑하는 것조차 어떻게 할 수 있나요?
전기 시대
PHP 전기 시대에는 사용자 정의 자동 로딩 전략을 등록하기 위해 __autoload 및 spl_autoload_register 함수가 나타나기 시작했습니다.
일반인의 관점에서 보면 __autoload 및 spl_autoload_register는 킬러 조직이며 다양한 국가의 킬러(기능)를 고용합니다. 누군가(신규)를 제거하고 싶을 때 이름(클래스 이름)만 제공하면 나머지 "Killer"가 이를 완료하는 데 도움이 됩니다.
__autoload
PHP 5에서는 Portal 기능을 제공하기 시작합니다. 사용하는 클래스를 찾을 수 없으면 클래스 이름을 매개변수로 이 함수에 넣습니다.
<?php// Lionis.phpclass Lionis { public function __construct() { echo '欧耶耶, 我就是 Lionis'; } }
<?php // index.php function __autoload($classname) { $filename = './' . $classname . '.php'; require_once $filename; } $lionis = new Lionis();
출력
欧耶耶, 我就是 Lionis
spl_autoload_register
우리 프로젝트가 매우 크고 오래되었거나 던지기를 좋아하는 젊은 선구자라면 다음이 필요합니다. 소개하자면 사양이 다른 것들이 있는데 모두 __autoload 함수에 넣으면 이 함수는 곧 확장될 것입니다. 게다가 __autoload는 전역적으로 고유하며 다른 사람이 사용하는 경우 오류가 발생할 수 있습니다. (사람을 죽이려면 먼저 부풀려야 한다.)
PHP 5.1.2에서는 주어진 기능을 __autoload의 구현으로 등록하여 이 기능 포털을 제공하기 시작합니다. 따라서 일부 프레임워크나 플러그인을 사용할 때 호환성을 위해 function_exists(spl_autoload_register)가 나타날 수 있습니다.
<?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'));
아, 이제 다양한 자동 로딩 기능을 작성할 수 있습니다.
정보화 시대
스승님, 조심하세요. 앞에 악마가 있습니다! . 우리 각자가 자체 자동 로딩 방법 세트를 구현하는 경우 각 PHP 구성 요소와 프레임워크는 고유한 자동 로더를 사용하고 각 프레임워크는 서로 다른 논리를 사용하여 PHP 클래스, 인터페이스 및 특성을 로드합니다.
일부 타사 프레임워크를 사용하는 경우 부팅 파일에서 자동 로더를 파악해야 하는데 시간이 많이 걸립니다. PHP-FIG는 이 문제를 인식하고 자동 로더를 사용할 수 있도록 구성 요소 간의 상호 운용성을 촉진하기 위해 PSR-4 사양을 사용할 것을 권장합니다.
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"] }