wrjc1hod 发表于 2024-10-4 12:57:41

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;">&lt;?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;">"&lt;h1&gt;$className&lt;/h1&gt;"</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;">"&lt;h4&gt;$className&lt;/h4&gt;"</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;">?&gt;</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;">&lt;?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>-&gt;prefixes[$prefix]) === <span style="color: black;">false</span>) {
      <span style="color: black;">$this</span>-&gt;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>-&gt;prefixes[$prefix], $base_dir);
      } <span style="color: black;">else</span> {
      array_push(<span style="color: black;">$this</span>-&gt;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-&gt;prefixes中</span>
      <span style="color: black;">//<span style="color: black;">倘若</span>不存在则继续<span style="color: black;">查找</span>上一个\的位置,获取上一个\之前的字符串<span style="color: black;">是不是</span>在$this-&gt;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>-&gt;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-&gt;prefixes中存在,<span style="color: black;">那样</span>将循环$this-&gt;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>-&gt;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>-&gt;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>-&gt;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>




wrjc1hod 发表于 2024-10-29 03:00:17

你的见解独到,让我受益匪浅,非常感谢。

1fy07h 发表于 3 天前

seo常来的论坛,希望我的网站快点收录。
页: [1]
查看完整版本: PHP自动加载