日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > php >内容正文

php

PHP自动加载机制

發布時間:2023/12/15 php 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 PHP自动加载机制 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

概述

首先,為什么PHP需要自動加載呢?

在PHP面向對象(OO)編程中,為了方便管理,我們都會把一個類寫在一個單獨的文件中,那么如果想在A類中使用B類的功能,就需要把B類加載到A類。對于這樣的需求在最原始的時候,我們是通過require 和 include 語法實現將文件加載到另一個文件中,include 和 require 是PHP中引入文件的兩個基本方法。

在小規模開發中直接使用 include 和 require 不會有什么不妥,但在大型項目中會造成大量的 include 和 require 堆積。這樣的代碼既不優雅,執行效率也很低,而且維護起來也相當困難。

PHP的自動加載功能,框架實現自動加載的包括PHP規范中的PSR0和PSR4原則,Composer的自動加載功能等等。

php加載文件方式

  • 常規加載:include,include_once,requice,requice_one
  • 魔法方法:__autoload()
  • SPL 自動加載:spl_autoload_register()
  • include()與require()

    簡單的文件加載方法:

  • require()

    包含的意思,找不到文件時,會報warning的錯誤,然后程序繼續往下執行。include語句只有在被執行時才會讀入要包含的文件。在錯誤處理方便,使用include語句,如果發生包含錯誤,程序將跳過include語句,雖然會顯示錯誤信息但是程序還是會繼續執行!php處理器會在每次遇到include()語句時,對它進行重新處理,所以可以根據不同情況的,在條件控制語句和循環語句中使用include()來包含不同的文件。

  • include()

    必須的意思,找不到文件時,會報fatal error(致命錯誤),程序停止往下執行。在php文件被執行之前,php解析器會用被引用的文件的全部內容替換require語句,然后與require語句之外的其他語句組成個新的php文件,最好后按新的php文件執行程序代碼。

  • require_once()

    類似于include(),系統會進行判斷,如果已經包含,則不會再包含第二次。

  • include_once()

    類似于require(),系統會進行判斷,如果已經包含,則不會再包含第二次。

  • 共同點:能包含位于獨立文件中的代碼,可以減少代碼的重復,實現代碼結構的模塊化,方便調用。

    • 注意事項

      • 加載文件格式

        include/require 包含進來的文件必須要加<?php ?>因為在包含時,首先理解文件內容是普通字符串,碰到<?php ?>標簽時,才去解釋。

      • 路徑要求

        可以用絕對路徑,也可以用相對路徑;windows下正反斜線都可以,linux下只認正斜線,所以最好用正斜線。

      • 如何選擇

        比如是系統配置,缺少了,網站不讓運行,自然用require,如果是某一段統計程序,少了,對網站只是少統計人數罷了,不是必須要的,可以用include而加不加once是效率上的區別,加上once,雖然系統幫你考慮了只加載一次,但系統的判斷會是效率降低,因此,更應該在開發之初,就把目錄結構調整好,盡量不要用_once的情況。

      • 特殊用法

        利用include/require返回被包含頁面的返回值

        1
        2
        a.php頁面中: ..... return $value;
        b.php頁面中:$v = include("a.php");

    __autoload()自動加載

    • PHP5及之后的版本,使用尚未定義的類時會自動調用__autoload函數,所以我們可以通過編寫__autoload函數來讓php自動加載類,而不必寫一個長長的包含文件列表。

      需明確的是對于__autoload()函數,PHP在找不到類的時候會自動執行,但是PHP內部并沒有定義這個函數。

      這個函數需要開發者自定義,并且編寫內部邏輯,PHP只負責在需要的時候自動調用執行。而且在調用的時候會自動傳人要加載的類名作為參數。

    • 用法:首先需要在需要加載文件的代碼中,定義__autoload()函數,并且編寫內部邏輯。PHP在找不到類的時候會自動執行__autoload()函數。下面是A.php需要加載B.php的例子:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      //文件 B.php 不做修改
      //文件 A.php
      <?php
      class A{
      public function test(){
      $b_object = new B();
      $b_object->echo_info();
      }
      }
      function __autoload($classname){
      require $classname.'.php';//include 'b.php';
      }
      $a_object = new A();
      $a_oject->test();
      ?>
      命令行輸入:#php a.php
      輸出: “我是class B中的方法執行結果“
    • 缺陷:一個項目中僅能有一個這樣的 __autoload() 函數,因為 PHP 不允許函數重名,也就是說你不能聲明2個__autoload()函數文件,否則會報致命錯誤。

      如果項目比較大,加載每個文件都使用同樣的規則顯然是不現實的,那么我們可能就需要在__autoload()中編寫復雜的規則邏輯來滿足加載不同文件的需求。

      這同樣會使得__autoload()函數變得復雜臃腫,難以維護管理

    SPL 自動加載

    PHP在實例化一個對象時(實際上在實現接口,使用類常數或類中的靜態變量,調用類中的靜態方法時都會如此),首先會在系統中查找該類(或接口)是否存在,如果不存在的話就嘗試使用autoload機制來加載該類。而autoload機制的主要執行過程為:

    • 檢查執行器全局變量函數指針autoload_func是否是NULL;
    • 如果 autoload_func==NULL ,則查找系統是否定義 __autoload() 函數,如果定義了,則執行并返回加載結果。如果沒有定義,則報錯并退出;
    • 如果 autoload_func 不等于NULL,則直接執行 autoload_func 指向的函數加載類,此時并不檢查 __autoload() 函數是否定義。

    通過上述PHP自動加載流程,可知PHP實際上提供了兩種方法來實現自動裝載機制:(1)使用用戶定義的__autoload()函數,這通常在PHP源程序中來實現;(2)設計一個函數,將autoload_func指針指向它,這通常使用C語言在PHP擴展中實現,即 SPL autoload機制,即本節中的SPL自動加載。如果兩種方式都實現了,也就是 autoload_func 不等于NULL,程序只會執行第二種方式,__autoload() 函數是不會被執行的。

    • 用法

      通過spl_autoload_register('my_autoload'),實現了 當程序執行找不到類B時,會執行 自定義的 my_autoload()函數,加載B類。實際上 spl_autoload_register('my_autoload') 的作用就是 把autoload_func 指針指向 my_autoload()。

      示例:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      B.php文件不變
      A.php
      <?php
      class A{
      public function test(){
      $b_object = new B();
      $b_object->echo_info();
      }
      }

      function __autoload($classname){
      require $classname.'.php';//include 'b.php';
      }

      function my_autoload($classname){
      require $classname.'.php';//include 'b.php';
      echo 'my_autoload ';
      }

      spl_autoload_register('my_autoload');
      $a_object = new A();
      $a_object->test();

      結果:my_autoload 我是class B中的方法執行結果
      ?>
    • SPL 自動加載整個過程

      針對上述的示例,假如把spl_autoload_register('my_autoload')改成 spl_autoload_register()不添加任何參數,B類也能被加載。

      為什么呢?

      因為SPL擴展內部自己定義了一個自動加載函數 spl_autoload(),實現了自動加載的功能,如果我們不定義自己的自動加載函數,并且程序里寫了spl_autoload_register()(如果不傳參數,必須是第一次執行才會有效)或者 spl_autoload_register('spl_autoload'),那么autoload_func 指針就會指向內部函數 spl_autoload()。程序執行的時候如果找不到相應類就會執行該自動加載函數。

      SPL 是怎么實現autoload_func 指針指向不同的函數呢?

      在SPL內部定義了 一個函數 spl_autoload_call() 和 一個全局變量autoload_functions。autoload_functions本質上是一個HashTable,不過我們可以將其簡單的看作一個鏈表,鏈表中的每一個元素都是一個函數指針,指向一個具有自動加載類功能的函數。

      spl_autoload_call()的作用就是按順序遍歷 autoload_functions,使得autoload_func指向每個自動加載函數,如果加載成功就停止,如果不成功就繼續遍歷下個自動加載函數,直到加載成功或者遍歷完所有的函數。

      autoload_functions 這個列表是誰來維護的呢?

      由spl_autoload_register() 這個函數維護。我們說的自動加載函數的注冊,其實就是通過·spl_autoload_register()·把自動加載函數加入到autoload_functions 列表。

      相關SPL自動加載函數

      1
      2
      spl_autoload_functions() //打印autoload_functions列表
      spl_autoload_unregister() //注銷自動加載函數

    參考:

  • PHP-自動加載原理分析
  • php自動加載方式集合
  • 總結

    以上是生活随笔為你收集整理的PHP自动加载机制的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。