<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                SPL,PHP標準庫(Standard PHP Library),從 PHP 5.0 開始內置的接口和類的集合,從 PHP5.3 開始逐漸成熟并成為內核組件的一部分。但是由于其文檔的稀少以及推行的力度不夠,導致較多的PHP開發人員對其不了解,甚至聞所未聞。 SPL是為了解決典型問題而存在,為了實現一些有效的數據訪問接口和類。現在它包括對常規數據結構的訪問,迭代器,異常處理,文件處理,數組處理和一些設計模式的實現。這些在程序設計的世界中都是一些典型的問題,以這樣一種標準庫的方式實現可以在很大程度上減少代碼的冗余和提高開發的效率。 SPL在PHP內核中以一個擴展的形式存在,在ext目錄下有一個spl目錄,這里存放了SPL的所有代碼實現。從文件名我們可以看出其基本的操作實體:異常、數組、文件……。與其它擴展相比,SPL擴展沒有太多不同的地方,它和json、date等擴展一起作為內置的模塊(php_builtin_extensions)加載。具體流程可以參考[<< 第一節 生命周期和Zend引擎 >>](#)。在ext/spl目錄中,有兩個有些奇怪的目錄:example和internal。這里都是一些.inc文件,它們是以PHP代碼的形式實現了SPL的一些類。通過TODO文件中的說明,example中的.inc文件是即將實現的SPL,而internal目錄中的.inc文件是已經實現了的SPL。也許這個擴展的開發人員的開發過程是先用PHP把相關代碼寫好,然后再依葫蘆畫瓢,換成C語言實現這些功能。 SPL的代碼結構和其它擴展一樣,一個主文件spl.c,它包括模塊初始化、請求初始化等擴展必須定義的方法,所有函數的定義以及所有函數和類的注冊。在函數中或類中需要調用的一些公用方法存儲在spl_function.c或spl_engine.c文件中。 ## 標準異常類[]() SPL提供了一系列的標準異常類,包括邏輯異常和運行時異常邏輯異常下又包括函數調用失敗異常、數據域異常、參數異常、長度異常等子類;運行時異常包括越界異常、溢出異常、范圍異常(通常這里是指一個算術錯誤)、下溢異常(如當從一個空集合中移除一個元素)和不確定值異常。以上的分類也在代碼層面體現,在spl_exceptions的模塊初始化函數中,這兩類被明顯分開。這是業務在代碼中的一種體現,我們在實現工作中的需求時,一個大的需求在分解后可能需要按函數或按類,甚至按文件進行物理上的分隔。SPL的異常類只是一個殼,他們都是從Exception繼承下來的,所有的方法完全繼承自Exception類。如果我們需要在項目中應用SPL的異常類,可以有選擇的繼承這些類,當有特定的需求需要實現時,可以覆蓋這些方法繼承自Exception類的方法。 [Exception](http://cn2.php.net/manual/zh/class.exception.php)是PHP中所有異常的基類,自從PHP5.1.0開始引入,自此,我們可以以面向對象的方式處理錯誤。Exception類的聲明如下: Exception { /* 屬性 */ protected string $message ; protected int $code ; protected string $file ; protected int $line ; ? /* 方法 */ public __construct ([ string $message = "" [, int $code = 0 [, Exception $previous = NULL ]]] ) final public string getMessage ( void ) final public Exception getPrevious ( void ) final public int getCode ( void ) final public string getFile ( void ) final public int getLine ( void ) final public [array](http://www.php.net/array) getTrace ( void ) final public string getTraceAsString ( void ) public string __toString ( void ) final private void __clone ( void ) } 其中message表示異常消息內容,code表示異常代碼,file表示拋出異常的文件名,line表示拋出異常在該文件中的行號。下面從 PHP內核的角度說明這些屬性及對應的方法。 message表示異常的消息內容,其對應getMessage方法。message是自定義的異常消息,默認為空字符串。對于PHP內核來說,創建Exception對象時,有無message參數會影響 getMessage方法的返回值,以及顯示異常時是否有with message %s等字樣。message成員變量的作用是為了讓用戶更好的定義說明異常類。 code表示異常代碼,其對應getCode方法。和meesage成員變量一樣,code也是用戶自定義的內容,默認為0。 file表示拋出異常的文件名,其對應getFile方法,返回值為執行文件的文件名,在PHP內核中存儲此文件名的字段為 EG(active_op_array)->filename 此字段的值在生成一個opcode列表時,PHP的內核會將此前正在編譯文件的文件名賦值給opcode的filename屬性,如生成一個函數的op_array,在初始化op_array時,會執行上面所說的賦值操作,這里的賦值是通過編譯的全局變量來傳遞的。當代碼執行時,EG(active_op_array)表示正在執行的opcode列表。 line表示拋出異常在該文件中的行號,其對應getLine方法,返回整數,即EG(opline_ptr)->lineno。對于每條PHP腳本生成的opcode,在編譯時都會執行一次初始化操作,在這次初始化操作中,PHP內核會將當前正在編譯的行號賦值給opcode的lineno屬性。EG(opline_ptr)是PHP內核執行的當前opcode,拋出異常時對應的行號即為此對象的lineno屬性。 除了上面四個屬性,異常類還包括一個非常重要的內容:異常的追蹤信息。在異常類中,通過getTrace方法可以獲取這些信息。此方法的作用相當于PHP的內置函數debug_backtrace。在代碼實現層面他們最終都是調用zend_fetch_debug_backtrace函數。在此函數中通過回溯PHP的調用棧,返回代碼追蹤信息。與getTrace方法對應還有一個返回被串化值的方法getTraceAsString,以字符串替代數組返回異常追蹤信息。 在構造函數中,從PHP5.3.0增加$previous參數,表示異常鏈中的前一個異常。在catch塊中可以拋出一個新的異常,并引用原始的異常,為調試提供更多的信息。 ## 數據結構[]() SPL提供了一套標準的數據結構,這些都是在應用開發過程中的常用數據結構,如雙向鏈表、堆、棧等。雙向鏈表的數據結構由一個雙向鏈表類(spl_dllist_object)、一個雙向鏈表(spl_ptr_llist)和一個標準的雙向鏈表元素結構體(spl_ptr_llist_element)組成這三者存在著包含關系,雙向鏈表是類的組成之一,雙向鏈表元素是雙向鏈表頭尾的結構。雙向鏈表類實現了迭代器接口,我們可以直接用foreach遍歷整個鏈表。其實現了 Countable 接口,即實現了count方法,我們可以直接對spl_dllist_object使用count函數獲取鏈表中的元素個數。關于 Countable 接口,關鍵實現在于count函數,當存在SPL時,如果count的是一個對象,則會判斷是否實現了Countable接口,如果實現了此接口,則會調用count方法并返回,否則返回對象的屬性個數。 隊列(SplQueue)和棧(SplStack)都是雙向鏈表的子類,棧操作的pop和push方法都是直接繼承自父類,隊列操作除了父類的操作外,增加了屬于自己的enqueue和dequeue操作,不過它們只不過是父類的push方法和shift方法的別名。 堆、大頭堆、小頭堆和優先隊列是同一類數據結構,都是基于堆的實現。堆是一顆完全二叉樹,常用于管理算法執行過程中的信息,應用場景包括堆排序,優先隊列等。堆分為大頭堆和小頭堆,在定義上的區別是父節點的值是大于還是小于子節點的值,在SPL中,它們的區別以比較函數的不同體現,而比較函數的不同僅僅體現在比較時交換了下位置和函數名的不同。 PHP的堆以數組的形式存儲數據,默認初始化分配64個元素的內存空間,新元素插入時,如果當前元素的個數總和超過分配的值,則會將其空間擴大一倍,即*2。SplMaxHeap和SplMinHeap都是SplHeap類的子類,直接繼承了SplHeap的所有方法和屬性,各自實現了自己的compare方法。 優先級隊列是不同于先進先出隊列的另一種隊列,它每次從隊列中取出的是具有最高優先權的元素,這里的優先是指元素的某一屬性優先,以比較為例,可能是較大的優先,也可能是較小的優先。PHP實現的優先級隊列默認是以大頭堆實現,即較大的優先,如果要較小的優先,則需要繼承SplPriorityQueue類,并重載compare方法。 SPL的堆實現了 Countable 接口和 Iterator 接口,我們可以通過count函數獲取堆的元素個數,以及直接foreach以訪問數組的方式遍歷堆中的元素,遍歷順序與比較函數相關。 SplFixedArray類提供了數組的主要功能。一個SplFixedArray和一個常規的PHP數組之間的主要區別是:SplFixedArray所代表的數組長度是固定的,并只允許為整數的下標。與普通的數組相比,它的優點是實現了更快的數組操作。但這里的操作并不包括創建, 與原生的 array 相比,在創建對象的性能上大概有 1/3 的損耗。之所有SplFixedArray類擁有更快的數組操作性能,是因為它舍棄了PHP自帶數組的HashTable數據結構,直接以C數組存儲數據。由于只允許整數作為下標,并且數組長度是固定的,當獲取一個元素時,只需要讀取下標索引,返回C數組對應的元素即可。這與HashTable的實現相比,少了hash key的計算,對于hash沖突的處理等。換一句話說:SplFixedArray類基本就是C數組,只是作為PHP語法展現。 和雙向鏈表一樣, SplFixedArray類實現了Iterator,ArrayAccess和Countable接口。從而可以直接用foreach遍歷整個鏈表,可以以數組的方式訪問對象,調用count方法獲取數組的長度。在獲取數組元素值時,如果所傳遞的不是整數的下標,則拋出RuntimeException: Index invalid or out of range異常。與獲取元素末端,在設置數組元素時,如果所傳遞的不是整數的下標,會拋出RuntimeExceptione異常。如果所設置的下標已經存在的值,則會先釋放舊值的空間,然后將新的值指向舊值的空間。當通過unset函數翻譯數組中的元素時,如果參數指定的下標存在值,則釋放值所占的空間,并設置為NULL。 SplObjectStorage類實現了對象存儲映射表,應用于需要唯一標識多個對象的存儲場景。在PHP5.3.0之前僅能存儲對象,之后可以針對每個對象添加一條對應的數據。SplObjectStorage類的數據存儲依賴于PHP的HashTable實現,與傳統的使用數組和spl_object_hash函數生成數組key相比,其直接使用HashTable的實現在性能上有較大的優勢。有一些奇怪的是,在PHP手冊中,SplObjectStorage類放在數據結構目錄下。但是他的實現和觀察者模式的接口放在同一個文件(ext/spl/spl_observer.c)。實際上他們并沒有直接的關系。 ## 觀察者模式[]() 觀察者模式定義對象間的一種一對多的依賴關系,當一個對象的狀態發生改變時,所有依賴于它的對象都得到通知并被自動更新觀察者模式又稱為發布-訂閱(Publish-Subscribe)模式、模型-視圖(Model-View)模式、源-監聽(Source-Listener)模式、或從屬者(Dependents)模式。一般來說,觀察者模式包括如下四個角色: - 抽象主題(Subject)角色:主題角色將所有對觀察者對象的引用保存在一個集合中,每個主題可以有任意多個觀察者。抽象主題提供了增加和刪除觀察者對象的接口。 - 抽象觀察者(Observer)角色:為所有的具體觀察者定義一個接口,在觀察的主題發生改變時更新自己。 - 具體主題(ConcreteSubject)角色:存儲相關狀態到具體觀察者對象,當具體主題的內部狀態改變時,給所有登記過的觀察者發出通知。具體主題角色通常用一個具體子類實現。 - 具體觀察者(ConcretedObserver)角色:存儲一個具體主題對象,存儲相關狀態,實現抽象觀察者角色所要求的更新接口,以使得其自身狀態和主題的狀態保持一致。 SPL實現了其中兩個抽象角色:SplObserver接口和SplSubject接口。如果我們需要實現觀察者模式,僅需要實現這兩個接口即可。并且這兩個接口定義在模塊初始化的方法中。除了聲明標準的接口函數,他們什么也沒有做。這只是觀察者模式的標準,具體的更新操作,添加操作等還是需要我們去實現。(有些不清楚作者為何在觀察者模式的文件中放入其它類的實現,并且貌似沒有什么直接的聯系。難道是因為是同一個作者的原因?) ## 迭代器[]() SPL提供了大量的迭代器,適用于各種應用場景,遍歷不同的對象。包括可以遍歷時刪除或修改元素的值或key(ArrayIterator)、空迭代器(EmptyIterator)、可以實現多迭代器遍歷的MultipleIterator、文件目錄迭代器等等。更多關于迭代器的類圖以及說明參照: [SPL-StandardPHPLibrary](http://www.php.net/~helly/php/ext/spl/annotated.html)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看