PHP自动加载
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">自定义的自动加载函数:</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">系统的自动加载函数<span style="color: black;">仅有</span>一个__autoload(), 有时候略显<span style="color: black;">不方便</span>, <span style="color: black;">咱们</span>有时候还需要分别定义<span style="color: black;">区别</span>的函数, 去<span style="color: black;">做为</span>自动加载函数,</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">以应对<span style="color: black;">区别</span>的情形, 此时就<span style="color: black;">能够</span><span style="color: black;">运用</span>自定义加载函数。</p><span style="color: black;"><span style="color: black;">bool</span> <span style="color: black;">spl_autoload_register</span> <span style="color: black;">([ callable $autoload_function [,<span style="color: black;">bool</span> $<span style="color: black;">throw</span> = <span style="color: black;">true</span> [, <span style="color: black;">bool</span> $prepend = <span style="color: black;">false</span> ]]] )</span></span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">autoload_function 欲注册的自动装载函数。<span style="color: black;">倘若</span><span style="color: black;">无</span><span style="color: black;">供给</span>任何参数, 则自动注册 autoload 的默认实现函数spl_autoload()。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">throw 此参数设置了 autoload_function <span style="color: black;">没法</span>成功注册时, spl_autoload_register()<span style="color: black;">是不是</span>抛出<span style="color: black;">反常</span>。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">prepend <span style="color: black;">倘若</span>是 true, spl_autoload_register() 会添加函数到队列之首, 而不是队列尾部。</p><span style="color: black;"><span style="color: black;"><?php</span>
<span style="color: black;">//1,先声明要<span style="color: black;">做为</span>自定义加载函数的函数名,<span style="color: black;">能够</span>多个:</span>spl_autoload_register(<span style="color: black;">auto1</span>);
spl_autoload_register(<span style="color: black;">auto2</span>);
<span style="color: black;">//2,分别定义这几个函数,其中写<span style="color: black;">规律</span>去加载需要的类文件。</span>
<span style="color: black;"><span style="color: black;">function</span> <span style="color: black;">auto1</span><span style="color: black;">($className)</span></span>{
<span style="color: black;">echo</span> <span style="color: black;">"<h1>$className</h1>"</span>;
$file =<span style="color: black;">./class/</span> . $className . <span style="color: black;">.class.php</span>;
<span style="color: black;">if</span>(file_exists($file)){ <span style="color: black;">//file_exists()判断文件<span style="color: black;">是不是</span>存在</span>
<span style="color: black;">require_once</span> $file;
}
}
<span style="color: black;"><span style="color: black;">function</span> <span style="color: black;">auto2</span><span style="color: black;">($className)</span></span>{
<span style="color: black;">echo</span> <span style="color: black;">"<h4>$className</h4>"</span>;
$file = <span style="color: black;">./library/</span> . $className . <span style="color: black;">.class.php</span>;
<span style="color: black;">if</span>(file_exists($file)){ <span style="color: black;">//file_exists()判断文件<span style="color: black;">是不是</span>存在</span>
<span style="color: black;">require_once</span>$file;
}
}<span style="color: black;">//3,<span style="color: black;">运用</span>类,需要的时候就会自动依次调用这几个函数去完成加载工作。</span>
$obj1 = <span style="color: black;">new</span> A();
$obj2 = <span style="color: black;">new</span> B();
var_dump($obj1,$obj2);
<span style="color: black;">?></span></span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">PHP自动加载——PSR4规范</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">1.先来介绍一下PSR规范</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">PHP-FIG, 它的网站是:www.php-fig.org。<span style="color: black;">便是</span>这个联盟组织发明和创造了PSR规范, 其中自动加载<span style="color: black;">触及</span>其中两个规范, 一个是PSR0, 一个是PSR4, PSR0规范<span style="color: black;">已然</span>过时了,</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">官方有提示, <span style="color: black;">此刻</span><span style="color: black;">重点</span>是用PSR4规范定义自动加载标准。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">PSR-4风格</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">类名:ZendAbc</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">命名空间前缀:Zend</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">文件基目录:/usr/includes/Zend/</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">文件路径:</p>/usr/includes/Zend/Abc.php
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">类名:SymfonyCoreRequest</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">命名空间前缀:SymfonyCore</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">文件基目录:./vendor/Symfony/Core/</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">文件路径:</p>./vendor/Symfony/Core/Request.php
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">3. 自动加载<span style="color: black;">办法</span></p>spl_autoload_register(<span style="color: black;"><span style="color: black;">function</span> <span style="color: black;">($class)</span> </span>{
<span style="color: black;">// 命名空间前缀</span>
$prefix = <span style="color: black;">Foo\\Bar\\</span>;
<span style="color: black;">// 命名空间前缀对应的<span style="color: black;">基本</span>目录</span>
$base_dir = <span style="color: black;">__DIR__</span> . <span style="color: black;">/src/</span>;
<span style="color: black;">// <span style="color: black;">检测</span>new的类<span style="color: black;">是不是</span>有命名空间前缀</span>$len = strlen($prefix);<span style="color: black;">if</span> (strncmp($prefix, $class, $len) !== <span style="color: black;">0</span>) {
<span style="color: black;">return</span>;
}
<span style="color: black;">// 获取去掉命名空间前缀后的类名</span>
$relative_class = substr($class, $len);
<span style="color: black;">// 将命名空间的中的分隔符替换为目录分隔符,再加上<span style="color: black;">基本</span>目录和.php后缀,<span style="color: black;">最后</span>拼接成</span>
<span style="color: black;">// 文件路径</span>
$file = $base_dir . str_replace(<span style="color: black;">\\</span>, <span style="color: black;">/</span>, $relative_class) . <span style="color: black;">.php</span>;
<span style="color: black;">// <span style="color: black;">倘若</span>文件存在则require</span>
<span style="color: black;">if</span> (file_exists($file)) {
<span style="color: black;">require</span>$file;
}
});<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">然则</span>上面的<span style="color: black;">办法</span>只能适用固定的命名空间前缀, <span style="color: black;">不可</span>通用。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">4、再次优化通用自动加载<span style="color: black;">办法</span></p><span style="color: black;"><span style="color: black;"><?php</span>
<span style="color: black;">namespace</span> <span style="color: black;">Example</span>;
<span style="color: black;">/**
* 下面这个例子实现了一个命名空间前缀对应多个<span style="color: black;">基本</span>目录
*
* <span style="color: black;">此刻</span><span style="color: black;">咱们</span>的目录结构是下面<span style="color: black;">这般</span>:
*
* /demo/autoload/
* controller/
* DemoController.php # Foo\Bar\DemoController
* Admin/
* AdminController.php # Foo\Bar\Admin\AdminController
* model/
* DemoModel.php # Foo\Bar\DemoModel
* Admin/
* AdminModel.php # Foo\Bar\Admin\AdminModel
*
* Foo\Bar分别对应<span style="color: black;">基本</span>路径 /demo/autoload/controller 和 /demo/autoload/model
*/</span>
<span style="color: black;"><span style="color: black;">class</span> <span style="color: black;">Psr4AutoloaderClass</span>
</span>{
<span style="color: black;">/**
* 一个数组,key为命名空间前缀,值为<span style="color: black;">基本</span>路径
*
* <span style="color: black;">@var</span> array
*/</span>
<span style="color: black;">protected</span> $prefixes = <span style="color: black;">array</span>();
<span style="color: black;">/**
* 封装自动加载函数
*
* <span style="color: black;">@return</span> void
*/</span>
<span style="color: black;">public</span> <span style="color: black;"><span style="color: black;">function</span> <span style="color: black;">register</span><span style="color: black;">()</span>
</span>{
spl_autoload_register(<span style="color: black;">array</span>(<span style="color: black;">$this</span>, <span style="color: black;">loadClass</span>));
}
<span style="color: black;">/**
*
* 添加一个<span style="color: black;">基本</span>路径对应一个命名空间前缀
*
* <span style="color: black;">@param</span>string $prefix 命名空间前缀.
*<span style="color: black;">@param</span> string $base_dir 命名空间类文件的<span style="color: black;">基本</span>路径
* <span style="color: black;">@param</span> bool true为往数组头部添加元素,false为往数组尾部添加元素
* <span style="color: black;">@return</span> void
*/</span>
<span style="color: black;">public</span> <span style="color: black;"><span style="color: black;">function</span> <span style="color: black;">addNamespace</span><span style="color: black;">($prefix, $base_dir, $prepend = false)</span>
</span>{
<span style="color: black;">// 去掉左边的\</span>
$prefix = trim($prefix, <span style="color: black;">\\</span>) . <span style="color: black;">\\</span>;
<span style="color: black;">// 规范<span style="color: black;">基本</span>路径</span>$base_dir = rtrim($base_dir, DIRECTORY_SEPARATOR) .<span style="color: black;">/</span>;
<span style="color: black;">// 初始化数组</span>
<span style="color: black;">if</span> (<span style="color: black;">isset</span>(<span style="color: black;">$this</span>->prefixes[$prefix]) === <span style="color: black;">false</span>) {
<span style="color: black;">$this</span>->prefixes[$prefix] = <span style="color: black;">array</span>();
}
<span style="color: black;">// 将命名空间前缀和<span style="color: black;">基本</span>路径存入数组</span>
<span style="color: black;">if</span>($prepend) {
array_unshift(<span style="color: black;">$this</span>->prefixes[$prefix], $base_dir);
} <span style="color: black;">else</span> {
array_push(<span style="color: black;">$this</span>->prefixes[$prefix], $base_dir);
}
}
<span style="color: black;">/**
* 真正<span style="color: black;">包括</span>文件<span style="color: black;">办法</span>,将给到类名文件<span style="color: black;">包括</span>进来
*
*<span style="color: black;">@param</span> string $class 全限定类名(<span style="color: black;">包括</span>命名空间).
* <span style="color: black;">@return</span> 成功将返回文件路径,失败则返回false
*/</span>
<span style="color: black;">public</span> <span style="color: black;"><span style="color: black;">function</span> <span style="color: black;">loadClass</span><span style="color: black;">($class)</span>
</span>{
$prefix = $class;
<span style="color: black;">//<span style="color: black;">查询</span>$prefix最后一个\的位置,<span style="color: black;">瞧瞧</span>最后一个\之前的字符串<span style="color: black;">是不是</span>在$this->prefixes中</span>
<span style="color: black;">//<span style="color: black;">倘若</span>不存在则继续<span style="color: black;">查找</span>上一个\的位置,获取上一个\之前的字符串<span style="color: black;">是不是</span>在$this->prefixes中</span>
<span style="color: black;">//<span style="color: black;">倘若</span>循环结束还是<span style="color: black;">无</span>找到则返回false</span>
<span style="color: black;">while</span> (<span style="color: black;">false</span> !== $pos = strrpos($prefix, <span style="color: black;">\\</span>)) {
$prefix = substr($class, <span style="color: black;">0</span>, $pos + <span style="color: black;">1</span>);
$relative_class = substr($class, $pos +<span style="color: black;">1</span>);
$mapped_file = <span style="color: black;">$this</span>->loadMappedFile($prefix, $relative_class);
<span style="color: black;">if</span> ($mapped_file) {
<span style="color: black;">return</span> $mapped_file;
}
<span style="color: black;">//去掉右边的\</span>$prefix = rtrim($prefix,<span style="color: black;">\\</span>);
}
<span style="color: black;">return</span> <span style="color: black;">false</span>;
}
<span style="color: black;">/**
* <span style="color: black;">倘若</span>参数中的$prefix在$this->prefixes中存在,<span style="color: black;">那样</span>将循环$this->prefixes[$prefix]里的value(<span style="color: black;">基本</span>路径)
* 之后拼接文件路径,<span style="color: black;">倘若</span>文件存在将文件<span style="color: black;">包括</span>进来
*
*<span style="color: black;">@param</span> string $prefix 命名空间前缀.
* <span style="color: black;">@param</span>string $relative_class 真正的类名(不<span style="color: black;">包括</span>命名空间路径的类名).
*<span style="color: black;">@return</span> mixed <span style="color: black;">包括</span>成功返回文件路径,否则返回false
*/</span>
<span style="color: black;">protected</span> <span style="color: black;"><span style="color: black;">function</span> <span style="color: black;">loadMappedFile</span><span style="color: black;">($prefix, $relative_class)</span>
</span>{
<span style="color: black;">// <span style="color: black;">检测</span>数组中<span style="color: black;">是不是</span>有$prefix这个key</span>
<span style="color: black;">if</span>(<span style="color: black;">isset</span>(<span style="color: black;">$this</span>->prefixes[$prefix]) === <span style="color: black;">false</span>) {
<span style="color: black;">return</span> <span style="color: black;">false</span>;
}
<span style="color: black;">// 将数组中所有的<span style="color: black;">基本</span>路径中的文件<span style="color: black;">包括</span>进来</span>
<span style="color: black;">foreach</span> (<span style="color: black;">$this</span>->prefixes[$prefix] <span style="color: black;">as</span> $base_dir) {
<span style="color: black;">// 拼接文件绝对路径</span>$file = $base_dir
. str_replace(<span style="color: black;">\\</span>, <span style="color: black;">/</span>, $relative_class)
. <span style="color: black;">.php</span>;
<span style="color: black;">// <span style="color: black;">倘若</span>文件存在则<span style="color: black;">包括</span>进来</span>
<span style="color: black;">if</span> (<span style="color: black;">$this</span>->requireFile($file)) {
<span style="color: black;">// 返回文件路径</span>
<span style="color: black;">return</span>$file;
}
}<span style="color: black;">// <span style="color: black;">无</span>找到文件</span>
<span style="color: black;">return</span> <span style="color: black;">false</span>;
}
<span style="color: black;">/**
*<span style="color: black;">倘若</span>文件存在则<span style="color: black;">包括</span>进来.
*
* <span style="color: black;">@param</span> string $file 文件路径.
* <span style="color: black;">@return</span>bool
*/</span>
<span style="color: black;">protected</span> <span style="color: black;"><span style="color: black;">function</span> <span style="color: black;">requireFile</span><span style="color: black;">($file)</span>
</span>{
<span style="color: black;">if</span> (file_exists($file)) {
<span style="color: black;">require</span> $file;
<span style="color: black;">return</span> <span style="color: black;">true</span>;
}
<span style="color: black;">return</span> <span style="color: black;">false</span>;
}
}
</span>
你的见解独到,让我受益匪浅,非常感谢。 seo常来的论坛,希望我的网站快点收录。
页:
[1]