




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
上一章提到過,為了真正地掌握一門語言,我們不僅要懂得這門語言的語法和符號,更重要的是,要知道它的主旨、背景和設計特性。為了能夠掌握PH,你必須知道它的所有特性。PHP語PHPC語言的影響(有一些人認為是受了Java語言的影響,但是Java語言也是從C語言發展而來。盡管PHP語法受C語言的影響非常大,但是它的符號與CPHP是解釋性語言,能夠識別各種變量類型。當你編程涉及到一個變量時,它的類型是不起作用的,只是被當作當前位置的一個命令。這個說明是稍微簡單了一點,但是你在開發程序時應該把這一點記在心里。PHP是一門解釋性的語言,它的源代碼都是一步一步被賦值和執行的。除了這一事實之外,PHP在處理變量時,你將知道有許多種編程方式去實現它,但是這樣同時也有許多容易出錯的地方。在這一章中我們將著重介紹一些典型的例子,以說明在使用高級的語法和算法的特征時什么是可以做的,什么是不可以做的。2.2定義常雖然在PHP中沒有為定義常量(其變量格式不可更改)特設表達式和結構。但你仍然可以通過賦值的方法達到這個目的。賦值的方法應該用來代替所有的明確值,例如錯誤代碼、文件格式的常量、特殊的字符串和其他任何對程序或者程序庫有特殊意義和在程序執行期間的固定值。賦值具有非常大的優點,它使得特殊值的意義非常明確,而且它同時也達到了另外一個目2.2定義常雖然在PHP中沒有為定義常量(其變量格式不可更改)特設表達式和結構。但你仍然可以通過賦值的方法達到這個目的。賦值的方法應該用來代替所有的明確值,例如錯誤代碼、文件格式的常量、特殊的字符串和其他任何對程序或者程序庫有特殊意義和在程序執行期間的固定值。賦值具有非常大的優點,它使得特殊值的意義非常明確,而且它同時也達到了另外一個目的:簡化程序。注意通過特殊值我們定義了“magicmembers”或者說是特殊字符串。舉一個例子:如果你想要從你的程序獲取一個GIF文件,你的程序內部能夠通過“magicr認識可以為這個值創建一個定義:define“IF_FILE,6);然后進一步通過關鍵值GIF_FILE你可以獲得“magicnumber。這一小段代碼從一個輸入文件讀取一個句柄,然后決定如何對這個句柄進行處理。這個句柄說明下面的數據是否為GIF圖像,還是一個PNG圖像,或者是一個ZIP壓縮文件。它可分為下列幾種情況,如表2-1表2-1圖像數圖這種建立方法的優點是:它可以把所有的句柄存放在一個集中的地方。如果其中的某個句柄需要更改,你只需要修改它的定義即可—如果不是這樣的話,你將不得不鉆到程序中一個一個尋找和替換這個字符串的當前值。使用賦值的方法,修改句柄的值這項工作就被簡化成為僅僅這些被賦值的句柄名字同樣地應該用大寫字母來表示,而且一般它們的名字前面應該有前綴,就像定義庫函數一樣。在前面的例子中,這些句柄都把FT_作為文件類型的前綴。你在編程時要盡可能定義變量。無論什么時候,在程序中當你碰到可能要給某個變量賦明確值的情況時,給其賦值并不是一個好主意。操作系統或者面向低端的程序通常有一大堆需要定義常量的清單。因為為了使他們的代碼段精煉,每一個小地方都得提煉。他們不能假設判斷代碼的字節大小、字的大小、寄存器的大小—一般你所見到的都以一定的方式進行過提煉。既然PHP本質上是輕便靈活的,這就意味著它不一定需要某些硬件或者其他的環境配置(不管它所在的操作系統是什么樣子,它的譯碼器不會改變其環境設置這些被賦值的句柄名字同樣地應該用大寫字母來表示,而且一般它們的名字前面應該有前綴,就像定義庫函數一樣。在前面的例子中,這些句柄都把FT_作為文件類型的前綴。你在編程時要盡可能定義變量。無論什么時候,在程序中當你碰到可能要給某個變量賦明確值的情況時,給其賦值并不是一個好主意。操作系統或者面向低端的程序通常有一大堆需要定義常量的清單。因為為了使他們的代碼段精煉,每一個小地方都得提煉。他們不能假設判斷代碼的字節大小、字的大小、寄存器的大小—一般你所見到的都以一定的方式進行過提煉。既然PHP本質上是輕便靈活的,這就意味著它不一定需要某些硬件或者其他的環境配置(不管它所在的操作系統是什么樣子,它的譯碼器不會改變其環境設置。當然在使用PHP語言時,非常極端的只使用賦值的方法也是沒有必要的。但是這種方法的確是一種好的程序設計風格。2.3數組函數組函數中最重要的幾個函數就是list()、each()和count()()是排序處理函數,組建一個來自于一組變量的lvalue值(的左邊,它把自己作為一個新的實體,就像多維數組的一個成員一樣;而作為一個參數時,它列出一組變量。當有東西分配給它時(一組變量或者一個數組成員,這些東西會作為參數賦給list()處理函數變量,從左至右地分列著。然后這些參數從rvalue值(這個值可以用在表達式的右邊)那里指定為一個相關的值。下面是一個例子,它是最好的解釋。注意你就不得不同時改變list()函數中定義的變量的順序。使用關聯數組和自定義的簡化值利用了程序的頭文件,其結果是獲得了更穩定的程序代碼。上面的代碼最好只用于來實L的查詢將從一個包含汽車信息的表單里面選擇e、r_or和d的值。查詢的結果將回過來使用yq_o(),這個函數將把這三個值放在同一個數組中返回。e將放在索引為0的位置,r在索引為1的位置,d在索引為22-2表2-分配變量SQLcar_type(arrayindexcar_color(arrayindexcar_speed(arrayindex當你想把一個值的集合整理到簡單的變量中去的時候,list()聲明是非常有用的。這也是編寫數據庫程序時經常發生的事情。然而要指出的是這個list()函數只能作為lvalue,而不能作為each()聲明經常和list()聲明結合起來一起使用。當你想把一個值的集合整理到簡單的變量中去的時候,list()聲明是非常有用的。這也是編寫數據庫程序時經常發生的事情。然而要指出的是這個list()函數只能作為lvalue,而不能作為each()聲明經常和list()聲明結合起來一起使用。each()遍歷一個數組之后把它的每一個成員作為一個鍵/值的結合體返回。這是通過它在輸入數組里的“漫游”來完成的。PHP指定了一個內部指針訪問每一個數組。這個指針最開始訪問這個數組的第一個成員,然后逐次指向后面的成員。這一對鍵/值的返回值格式是一個帶有鍵值“0”1“key和“value”四個成員的數組。“0和“1)包含有源成員在索引0處的鍵值,而此鍵值可以在索引1處找到。同樣的信息可以為索引數組僅僅只是關聯數組的一種特殊形式—理論上它們是不同的,但實際上在PHP卻是相同的。要獲得詳細信息,請參閱后面的論述。這些源成員的鍵值包含在“key”和“u如果你想更好地了解each()背后的原理,創建一個詳細的數組是非常有用的,如表2-3表2-each數013ElementElementElement這是包含在數組$my_array中所有鍵/值的清單。現在我們可以使用each()第一次調用each(,將返回包含第一對鍵/值的第一個四成員數組。這里要指出的是,既然我們只要賦給list()處理器兩個參數,那么只有來自于這個四成員數組中的值才能用作被賦的值,即:第一個鍵值“0”和$my_array中第一個有值的成員“Element1。2-1高級語 圖2-1使用高級語 圖2-1使用each()后的數組清其執行結果,如圖2-2圖2-2each()的返在輸出中你可以清楚地看到1、value、0和key,而且0和1應該正好是由“key”和“valu連在一個索引數組上使用each()在開始的時候沒有什么意義,因為一個索引數組的這些成員用for()聲明可以更容易被讀取—然而,使用for()有許多不足的地方。首先,因為在PHP中索引數組是關聯數組的一種特殊形式,PHP允許不連貫的數組索引。換句話說,你可以使用這樣的一個數組,如表2-4表2-關聯數組特殊形034這個數組只使用了索引0,3,4和1—其余的完全沒有指定。對這個數組使用這個數組只使用了索引0,3,4和1—其余的完全沒有指定。對這個數組使用count()函數(這個函數返回一個數組中被指定的成員的個數)將準確地返回四個指定過的成員。但是你不能對這個數組使用for()聲明,因為不知道這個數組的所有值的相關鍵值是哪一個:該段代碼的運行結果,如圖2-3使用一個簡單的for()循環對于這種數組來說并不足夠。它能讀取沒有指定值的索引。如果PHP提供一個更加嚴密的編譯環境,那么結果將出現意外而且程序馬上中斷。因此當你對它的內容和數組的一致性還不是很確定的話,你就必須使用each(。each()也是一個非常好的工具,它能夠保證你正在存取的數組不超出它的范圍——溢出是出現意外的另外一個原因。PHP以非常輕松的方式處理超出范圍的存取(它很可能只給你一個警示信息。然而如果我們使用不合理的數組存取,從而一而再,再而三地破壞了PHP完健性。這樣的話,最好的情況是PHPPHP模塊突然占100%的CPU時鐘,而且服務器的進程必須被中止—這在研制過程中應想盡一切辦法避免。即使這很可能是PHP多錯誤的內部數組句柄引發的,你也不能強行使用不合理的數組存取。這是非常不好的編程試驗,而且既然PHP提供了each()和list(,此外,還有輔助的函數和處理器保護你的程序安全,你就應該使用他們。eac()的最初目的是在實型數組中使用,這樣就可以使用不多的關鍵值去對數據進行索引。無論什么時候出現這種情況,如果沒有一個能夠列出所有可獲取的關鍵值(假設你并不知道哪一個關鍵值正在被使用)的話,你就不可能對存儲數據進行存取。這些數組可以被組合起來現在你有按名稱排序的數組(不是按數量排的,如果你不使用預先定義的關鍵值,你將打現在你有按名稱排序的數組(不是按數量排的,如果你不使用預先定義的關鍵值,你將打each()能夠讓你做到,如圖2-4所示。圖2-4使用each()關聯數組的清最后一個關于each()的重要注意事項是:為了使你每次重復操作時能夠重新獲取一對關鍵值/PHP必須記住上次存取的是哪一對關鍵值/數值。結果是當你對同一個數組進行另一次重復操作時,不會有兩個相同的鍵值/數值對會被返回。為了重新設置這個數組的內部順序,你不得不使用reset()這個函數使PHP的內部指針回移到這個數組的第一個成員,第一個成員也是reset()就如圖2-5所示的輸出那樣,第二個循環不會再從第一個成員處開始。相反的,它從第一次循環離開的地方繼續。這是由于PHP的內部數組指針還沒有被重置。對這個腳本語言進行一點小小的修改就可以獲得一個不同的結果(2-6。圖2-5不使用reset圖2-5不使用reset()而使用圖2-6結合reset()使用和current()。使用這些函數,你就可能人為地從兩個方向遍歷一個數組。next()返回當前成prepre()curren()僅僅返回當前指針訪問的數組成員。但是無論什么時候它們碰到一個空的沒有被賦值的數組時,這些函數將返回錯誤值,就像當它們碰到指針恰好訪問數組尾部一樣。還沒有區別這兩種情況的方法,所以當each()不是合適的選擇并且能夠保證不會碰到一個未被賦值的成員的時候,一般都應該使用這些函數。PHP函數也處理數組。如果你要完全的介紹,請查閱相關的手冊。在PHP4.0中數組函數的數量增長得十分驚人。如果在這里全面地介紹它們,我們將不能對更重要的問題加以重點敘述了。 PHP和90年代初期,最受歡迎的編輯器—例如Borland編輯器家族—逐漸形成了處理面向對象的程序設計(OOP)功能,面向對象的程序設計是一些基礎語言(Pascal和C)的拓展。忽然之間,類、對象、模板和繼承成了流行的詞匯,也是軟件開發中最熱門的主題。OOP主流,而且許多公司都極力把他們的軟件包從一般程序轉化為基于對象的應用程序。今天這種熱潮已經退卻,但是一門不能處理對象的語言仍然被看作是過時了的語言。PHP就支持對象。在這部分中我們將討論PHP語言中OOP的正反兩方。我們認為將所有的軟件都設計成OPP類型的這場“革命”是有絲微不當的。大規模的軟件包在經濟的影響下已經被轉化為一個個的對象——姑且不考慮開發者從頭思考程序、重新構建程序和重新實現千萬行程序代碼所花去的時間。這些用一般程序方法設計出來的軟件包以前運行得非常良好,它們中間的一些軟件根本就不需要對象的支持。我們以前經常看到一些軟件系統安全的廣告上說“現在已經完全用OOP重新設計。這些系統其實就像在檢查硬件鎖(一種插在PC機并行接口上的用來鎖硬件的一個小裝置,該系統可能需要密碼,有些情況下還可以把正在連接的執行程序加密等等。這些應用程序構建在那些通常根本不需調用初始化密碼檢查這樣的特殊環節的軟件包上。這些軟件包中有一些在應用程序運行時自動執行。在其他情況下,環境檢查減少到只調用一個非常簡單的函數—但是誰需要面向單個函數的對象?從本質上說,這些程序代碼的拓展是嚴格線性的,硬件的存取已經被過程程序抽象化了。(實際上,有些廣告根)我們碰到的最糟糕的情況是:有一個開發者在使用圖像函數庫繪制復雜的二維和三維對象,他決定這樣做是因為他在一次會議上碰到一個Borland公司的代表,那個代表建議他使用OOP。開發一個非常有價值的軟件時,難道就這樣輕易地基于一個建議?恐怕這不是一個好主意。那么OOP有什么好處?OOP與過程的程序設計有什么不一樣?我們又為什么要考慮這些現在來看一看上面的第一個問題。考慮在PHP開發中是否使用OOP是非常重要的,因為在開發中強行使用過高的技術是沒有意義的,這在低級結構中效果又不是很好,而且最后與你用一般程序方法開發的應用程序還沒有什么不同。過程程序的項目文件與面向對象的項目文件一樣2-5顯示了兩種方法之間的主要的不同點。表2-面向對象的程序設計與一般的程序設計對表2-面向對象的程序設計與一般的程序設計對對象過程完全數據封易于支持多重句使用繼承來保護程序接口的允許附加功沒有程序封裝;只有參數傳送才有作不支持多重句柄;處理不同的數據結構必須涉及到所有變無繼承性;附加功能只能依靠PI提供另外一個P層來實現,或者靠徹底改變這個AP來實現分離的名稱有效很難保證數據的完整性;初始化和消除必須做得非常清名稱必須在全局名稱域中聲該表只列出最顯著的差異;還有很多的差異,但是你已經可以看到過程程序并不是太好。但是過程程序真的像它表面看上去那么差嗎?這就意味著OOP是一種全新的技術,它將會取代舊的程序設計嗎?其實這將依賴于你所要達到的目標和你所在的工作平臺。對我們來說,這個平臺就是PHP。PHP當然支持對象,但是它是以一種非常特別的方式來支持的。這就與解釋程序的變量處理有關。無論什么時候PHP碰到需要對一個變量進行寫操作的聲明時,它就對將要賦給變量的數據進行計算和求值,然后拷貝它,最后把這個結果指定到內存中的目標空間。(這樣的描述是有一點簡單,但是你可以領會這個意思。在這個腳本程序中,PHP為$my_var開辟內存空間,讀取$some_var3,再把這個值賦給新分配的內存空間。為$new_var開辟內存空間,讀取$some_var和$my_var的值,然后對他們求和,再把他們賦給新分配的內存空間。好了,這聽起來好像很不錯也很有道理—但是這些都是非常簡單的類型,何況你已經在這上面花了很多時間了。但是當PHP處理類的時候就不一樣了(也是不合法的。你認為這作為輸出將會產生什么結果?這個腳本程序首先聲明了一個類,創建了它的一個句柄,然后給它的三個成員變量賦值。在完成這些以后,又創建了一個與該對象有關的變量,重新為這個新的對象賦值,然后就把兩個參考變量的成員變量的值都打印出來。記住,它們只有一個句柄。圖2-7給出了結果。你認為這作為輸出將會產生什么結果?這個腳本程序首先聲明了一個類,創建了它的一個句柄,然后給它的三個成員變量賦值。在完成這些以后,又創建了一個與該對象有關的變量,重新為這個新的對象賦值,然后就把兩個參考變量的成員變量的值都打印出來。記住,它們只有一個句柄。圖2-7給出了結果。如果你覺得這些都不足為奇的話,那么你要么就已經對PHP非常了解,要么你現在還沒有對對象思考得很多。PHP也創建了一個副本,這個副本是一個my_class句柄,它代替原來的僅僅是一個新的參考變量。既然希望新的處理器在內存里創建一個my_class句柄,那么返回一個參考變量將不是所希望的結果。因而,當把這個參考變量賦給另外一個變量的時候,只有這個參考變量應該被拷貝,而原來的數據不會改變—與一個文件系統的關聯相似,它允許在該文件系統PHP的表現—創建一個參考變量的數據副本,而不是這個參考變量本身。但是這看起來好像這并不值得花這么大的精力去敘述。然而你在這么短的時間里面你已經明白了它的確非常的不一般。寫到這里,PHP3.0和PHP4.0PHP的核心發展機構曾透漏他們的計劃將改變向來的慣例,而直接使用參考變量的語法。但是這樣做會失去兼容性。一個可能的改變就是計劃開發的版本—如果這變成事實,PHP3.0沒有能夠很好地實現垃圾清理功能。不論什么時候你對一個變量進行寫操作時,內存中一個新的空間被分配,而不是重新使用以前分配的空間。unset()可以做到這一點—就算是它沒有釋放內存,它也對后者做標志,以表明內存正在被重新使用當然僅僅只是一個樹節點,但是它有我們所需要的所有東西:一個左子目錄樹的鏈接和一當然僅僅只是一個樹節點,但是它有我們所需要的所有東西:一個左子目錄樹的鏈接和一個右子目錄樹,以及包含這個節點的內容變量。這個代碼僅僅只是建立了有一個節點和兩個子節點的目錄樹,給它們中每一個成員賦給不同的值。遍歷該目錄樹可用下面這個函數來實現:因為這個遞歸函數沒有中止程序的出口(這個函數實際上不知道哪一個節點有子節點,而哪一個沒有,如果忽略了這一點,這個函數將不會有返回值。讓我們來看一看它是怎么工作的,以及PHP是怎么處理的。這點瑕疵已經在程序的第一行顯示出來了,$node在這里已經被賦予了一個值。$start_node作為參數包含了程序開始處的節點句柄,然后給$node賦值的操作將創建它的一個副本。它創建了一個副本的事實對于一個函數來說并不是很重要,而僅僅是重現這個目錄樹,然后打印出這個節點的內容。但是只要你想在目錄樹的某個地方做一些改動,它將會是非常重要的。這些以后,只需要改變這個對象的子節點的鏈接,大功就告成了。等一下,你真的做到了嗎?仔細考慮一下你剛才所作的改變(2-8。你已經改變了最左端的節點的副本,并不是這個節點本身!只要你的函數返回,你所作的改變都會丟失,而且是永久地消失了。結點數這些以后,只需要改變這個對象的子節點的鏈接,大功就告成了。等一下,你真的做到了嗎?仔細考慮一下你剛才所作的改變(2-8。你已經改變了最左端的節點的副本,并不是這個節點本身!只要你的函數返回,你所作的改變都會丟失,而且是永久地消失了。結點數右子結點結點數右數左數右數你可以返回一個參考變量給這個句柄,然后用PHP“指針”機制去改變它。然后你就可以改變這個對象本身而不是它的副本。但是在你再次遍歷這個樹結構的同時,你將會看見一些奇怪的東西—看上去什么也沒有改變。而實際上確實什么也沒有改變。這是因為你想改變的該節點的父節點,已保留自己相同數據的備份。請記住,$node->left和該樹結構的節點備份沒有什么兩樣,同時也就是因為有了這個備份訪問這樹結構的句柄才能開始計算。你改變的這個備份將保留在樹結構之外,而且在垃圾處理程序中結束。如果你想改變這個節點,則需要按順序把參數傳遞給父節點,傳給父節點的父節點,直至三級父節點。你將結束另一個遞歸函數,這個函數對于代碼來說用處不是很大,它在99的情況下不會起作用。2.4.1類:PHP3.0和PHP4.0針對PHP3.0的不足,PHP4.0新添了一些功能:處理對象引用,而且現在可以支持實型對象引用。這里引用實型是因為它們并不是真的訪問其他變量正占用的內存;PHP將把這些變量看作這個源代碼為同一個對象創建了兩個參考變量。注意$another_object給$new_objectPHP不會拷貝這個變量,相反的,它將創建一個訪問該變量的副本。只有當你后來使用參考變量時(為了拷貝一個參考變量,你需要重新使用參考變量句柄,$new_object和$another_object才可以用于對于PHP的不同版本,下面我們給大家作一個簡單的介紹1.PHP3.0數據:不要使用需要實型指針的、具有復雜數據結構的類(比如樹結構。如果你不得不這樣做,那么盡力限制對數據集合使用類,而不是限制數據管理。編程:只對不會被副本語法影響的APIs結構使用類。仔細考慮一下你的項目是否要被過程編程兼容;如果是的話,一定要仔細考慮這一項。過程編程是很可靠的,是在實踐過程中被證實的,然而對象編程卻有許多缺陷。2.PHP編程:只對不會被副本語法影響的APIs結構使用類。仔細考慮一下你的項目是否要被過程編程兼容;如果是的話,一定要仔細考慮這一項。過程編程是很可靠的,是在實踐過程中被證實的,然而對象編程卻有許多缺陷。2.PHP4.0PHP將創建對象的一個副本,同時也很可能破壞你的數據的共存性&PHP4.0中類的性能得到了很大的改善,但是我們仍然不是很放心。我們聽到了兩方面的意見。一方堅持說對象是垃圾,像PHP這樣的語言中根本不應該使用類。然而另一方人則支持在任何過程程序編程中使用對象,在PHP3.0中也應該這樣。對那些只用過程編程的人們來說,面向OOP這幫人來說,這些“PP(過程程序編程者)是白癡。這簡直就像一場宗教戰爭。無論那里我們提及這個話題的時候,馬上就會導致永無休止的爭論。平心而論,兩種極端的想法都是錯的。忽略特點不是一個好想法,而不管它是否倒退就使用它也不好。我們不喜歡說這是個人偏好的一種方式,因為技術永遠不應該這樣。我們的建議是:不要被你的任何偏見所左右—特別是別人的偏見—然后有目的地決定什么對于你的項目是有用的。2.4.2PHP中好像在PHP中,類能非常簡單地被執行。你可以從其他語言中知道許多的關鍵字這段代碼定義了shopping_cart類,這個類使用了成員變量$item_list、pick()和drop()注意現在沒有方法區分公用和私有變量的差異。在PHP中,所有的變量缺省為公用型—這意味注意現在沒有方法區分公用和私有變量的差異。在PHP中,所有的變量缺省為公用型—這意味這個簡單的類執行了某種類型的購物手推車(名字的直譯,該類使用了一個包含存儲在關聯數組($item_list)中的手推車內容,以及用來加減內容的兩個函數(pick)和drop()的變量。成員函數作為一個普通的函數聲明,只不過它們只有在類的定義域內才能夠執行。類的成員變量(在類中的變量)用關鍵字va定義。注意在PHP中區分類的聲明和執行是不可能的。你常常必須在類的聲明域中直接執行所2.4.3成員函數可以使用以前的語法instance->member()調用,也可以使用新的語法instance::membe()調用。相似的成員變量也可以使用instance->property或者是instance::property新版本中的存取形式對調用父類的構造函數或者其他的不在當前對象中的成員函數是特別有用的(在后一部分用得最多的是繼承:extended_object對象的擴展版本中有一個構造函數可以用來調用父類的構造函數,它能正確地初始化該對象樹的剩余部分。注意如果沒有明確的用這個構造函數調用父類的構造函數,父類將永遠不會被初始化(它的上一級父類以及更高的父類也不會被初始化。PHP能夠使用一個像關鍵字一樣的特定名稱訪問當前對象的句柄。這個特定名稱命名為this,它能夠給當前實例句柄的所有成員給予存取權限。這對于所有的自變量來說是非常有用的。PHP并注意既然PHP沒有在類的定義域內引進一個新的局部變量,你要確信你在每個地方都包含了this關鍵字,那樣你是在你的對象里操作參考變量。如果你忘了使用this關鍵字指示2.4.4構造函數除了自身的名字必須與類的名字一樣之外,也可以像普通函數一樣被定義。PHP2.4.4構造函數除了自身的名字必須與類的名字一樣之外,也可以像普通函數一樣被定義。PHP沒有析構函數也可以像其他函數一樣可以使用參數—即使是可選的參數(如果想獲得可選參數的詳細信息,請參閱后面關于變量參數的清單部分。注意和對象,這在PHP3.0中是允許的。這個包含在shopping_cart::shopping_carttakes具有兩個選項——如果沒有參數被指定,本實例中的這個購物車將給自己添加一件恤,否則它將取用期望的物件:2.4.5給對象添加函數,不是重新修改原來的代碼,而是重載現有的結構體。新的對象可以從以前的對象那里繼承關鍵字的擴展特性。就像名字的意思所顯示的那樣,這將需要定義一個新的類來擴展已建立的類:擴展的手推車extend_cart除了包含shopping_cart中的所有成員變量和成員函數之外,還附加了另外一個函數query(,這個函數允許我們檢查在手推車中任何項目的數量。注擴展的手推車extend_cart除了包含shopping_cart中的所有成員變量和成員函數之外,還附加了另外一個函數query(,這個函數允許我們檢查在手推車中任何項目的數量。注 2.4.6特殊的OOPPHP定義了許多非常簡單的函數,它們可以使處理對象變得更加簡單。表2-6描述了這些函表2-PHP的函函數功能決定對象是否是類名的一個子stringget_class(objectobjectstringget_parent_class(objectboolmethod_exists(objectobject,stringmethod)boolclass_exists(stringclassname)boolis_subclass_of(objectobject,string注意PHP3.0沒有這些功能。這個部分顯示的是用OOP實現購物手推車的整個程序(2-1清單2-1手推車的源2.5鏈接清2.5鏈接清鏈接清單是樹的一種特殊形式,它是組織數據系統的最典型的數據結構之一。我們現在假設你已經明白了結構、概念和鏈接清單的使用,我們就不必深究它們這里是如何實現的。下面將重點放在能做和不能做的要點上。PHP3.0創建了一個對象的副本,而不是用一個指針訪問它們。這只是使用了鏈接清單的一些非常有限的小功能:只寫一次而要讀很多次。鏈接清單可以被創建,但是不能被修改。當你想要去修改這個清單中的一個元素的時候,你將丟失清單中的接下來的所有參考變量。由于同樣的原因,重新組織這些成員是不可能的。類似地,雙鏈接的清單在PHP3.0中是不能實現的(至少我們沒有全力去試。在我們徹底放棄之前,我們也只是在調試程序上花了非常少的時間。因為每一個節點都需要鏈接清單尾部的一個新的副本。為了使它具有回讀元素的功能,你將不得不創建一大堆相同內容的冗長的清單。PHP4.0支持實型參考變量,沒有上面的這些限制。清單可以被隨機地創建和重組—即使注意不定指針—傳統的程序員是這樣提醒的。我們在PHP中要這樣修改:注意冗長的副當使用表單工作時,可以用最一般的方式創建一個能夠滿足你所有需要的功能強大的庫。高強度地測試它,確信它能正確的工作。這可以防止你不得不去尋找而且還是錯鏈接清單和樹—一個工作像前面提到的一樣,根據你的需要去創建一個功能強大的庫是一個不錯的做法—很容易擴展而且具有與有關的重要任務所應具有的特征。我們在這里提供一個實際的例子:我們已經開發的處理樹結構的庫,它在PHP3.0中也能運行。你可以在CD-ROM中找到完整的源程序。這個庫還能夠用兩個子集在每個葉節點處處理雙鏈接樹結構,每個節點處有一個混合變量的內容容器。每一個能夠在樹上使用的操作都被合并到了應用程序接口,這樣就把樹的結構圖和存取樹的代碼分離開了。這就是為什么這個樹能夠在PHP3.0下使用的原因(表面上看起來與我們前面所說的相矛盾。這個樹是基于數組的,而不是基于指針的。因為PHP具有動態數組的特征,只需要花一點這個思想并不新鮮。很多年以前就有它的雛形,這也并不難理解。它沒有使用指針在一個節點到下一個節點間移動,這樣需要在內存中專門為指針分配一個空間。每一個節點包含有與它有鏈接的每個節點組成的數組的索引。這也有好處,PHP可以提醒你不合法的索引,你只需要把包含樹結構數組的變量賦給另外一個變量,就可以拷貝整個樹了。緊接下來你可以把整個樹連接起來,然后將其存到任何你想存的地方。下面是另外一個更加理論化的解釋:把為你的程序分配的內存空間看作是一個大的數組。是指針只是索引這些元素的一個數值,因而它只訪問放置在內存中的每個結構體的開始位置。現在,所有的事情抽象成了一個語言結構(一個實型數組,你對這個情形會有更深的了解:現在PHP使用數組可以讓你創建很多這樣的“內存,你可以任意增加或者減少它的容量,把它整個清理掉或者只刪掉其中的一個成員。總的來講,這是一種非常不錯的管理內存的方法。把所有的這些集成為一個可靠的庫將使你擁有一個非常有用的工具。圖2-9一個包是指針只是索引這些元素的一個數值,因而它只訪問放置在內存中的每個結構體的開始位置。現在,所有的事情抽象成了一個語言結構(一個實型數組,你對這個情形會有更深的了解:現在PHP使用數組可以讓你創建很多這樣的“內存,你可以任意增加或者減少它的容量,把它整個清理掉或者只刪掉其中的一個成員。總的來講,這是一種非常不錯的管理內存的方法。把所有的這些集成為一個可靠的庫將使你擁有一個非常有用的工具。圖2-9一個包含在數組中的這個庫包含下列函數,如表2-7表2-樹的結構庫函函數描述創建一把一個節點作為左子目錄樹連接到另一個節arrayinttree_allocate_node(arraytreeinttree_free_node(arraytree,inthandle)inttree_link_left(arraytree,intlink_to,intchild)inttree_link_right(arraytree,intlink_to,intchildinttree_get_parent(arraytree,inthandle)inttree_get_left(arraytree,inthandle)inttree_get_right(arraytree,inthandle)inttree_assign_node_contents(arraytree,inthandle,mixedcontents)mixedtree_retrieve_node_contents(arraytree,inthandle返回所給節點的右子給一個節點的內容容器指定數從一個節點的內容容器中取出數你會感覺到在這里添加更多的函數非常簡單。例如:庫沒有合并樹、刪除沒有用的葉(存在于數組中但是已經與主目錄樹脫離的葉,因此它們不能再被存取)等等的功能。對這個代碼你會感覺到在這里添加更多的函數非常簡單。例如:庫沒有合并樹、刪除沒有用的葉(存在于數組中但是已經與主目錄樹脫離的葉,因此它們不能再被存取)等等的功能。對這個代碼進行研究是一種非常好的實踐和學習方法。該庫是非常直截了當的。tree_create()為一個樹創建了一個新的數組,它同時初始化了一個成員,并把這個成員作為根目錄成員。所有的其他節點參考變量在數組之內是整數索引值(參看源程序$idx_left和$idx_right。一個參考變量被標上-1,以示它正在被使用。例如:如果$idx_left將含有-1。為了標記一個成員自身是否正在被使用(意思是是否有數據賦給它$free。這個變量只包含1(正在使用)或者0兩個布爾值(沒有被使用。tree_creat()創建了一個虛擬的節點,把它標記為對所有沒有使用的參考變量都是開放的,0位置。然后把這個數組返回給調用者。注意:調用者并不需要知道這個數組的任何情況—即使它并非一個實際的數組。這個程序應該僅僅將數組假定為某種樹的處理方法。因為PHP并不具有明確類型的特點,但是PHP運行起來通過檢查$free標志上已經存在的每個節點,tree_allocate_node()將在樹的數組內尋找一個空的節點。如果沒有節點被標記是空的,它將分配一個新的節點,然后把它加到樹的數組中去。這就是PHP的派得上用場的動態結構功能—如果我們不得不使用大小固定的數組,那么這些節點遲早會被用完。它找到的節點將被標記為正在使用的節點,然后作為一個句柄返回給調用者。tree_free_node()的功能基本上完全相反:它使用$free標志給特定的現在沒有被使用的節點作標記。這強調了三方面的問題:首先,空的節點并不是真的是空的,它們只是被標記為空的。試想你想建立一個有許多節點的復雜的樹結構,然后對它使用優化程序,這個優化程序把節點的總數減少到一半。優化程序運行之后只在數組中留下了許多“神奇的節點。假設你最開始分配了1000個節點,在優化程序運行過程中釋放了其中的500個節點,這樣做的結果是在一個數組中有1000500個被標志為正在被使用。這是非常浪費內存的。于是自動的垃圾處理器對這些特殊情況是就顯得非常有用。垃圾處理器導致出現了一個新的問題:也就是“怪節點(zombienode“怪節點”就是那些被標志為正在使用的、但是沒有和樹鏈接,再不能被訪問的節點(參見圖2-10。圖2-10樹中的怪節當庫知道了樹中所有的節點以及節點內部之間的鏈接關系之后,怪節點就能夠很容易的識別—然而,這在源代碼中還是行不通。第三個問題和怪節點的問題非常相似:斷開鏈接(broken當庫知道了樹中所有的節點以及節點內部之間的鏈接關系之后,怪節點就能夠很容易的識別—然而,這在源代碼中還是行不通。第三個問題和怪節點的問題非常相似:斷開鏈接(brokenlinks。斷開鏈接就是從一個節點開始鏈接,并指向一個沒有被使用(或者并不存在)節點的鏈接(參看圖2-1。無論什么時候你把一個節點從一個樹分開時,這個鏈接隨即也斷開了,該節點被標記為空的,并且所有訪問該節點的其他節點都被修改。斷開鏈自由節圖2-11一個樹中的斷開鏈tree_link_left()和tree_link_right()分別連接一個左節點和一個右節點。它們是通過給節點結構體中的$idx_left和idx_righttree_get_left()和tree_get_right()中找到與它們相對應的部分,它們分別讀取這個左和右連接的句柄。另外,為了在樹結構中存儲一些內容和從樹結構中讀取數據,你可以使用tree_assign_node()和tree_retrieve_node_contents(。同樣地,當我們不需要把節點固定為一定的類型時,PHP的動態特性在這種情況下就顯得非常有用了。在C++中使用類模板例示一個樹就成了一個非常普遍的實踐經驗。舉個例子:它可以產生一個整數(僅僅是整數)的樹類。只要你喜歡,你想要建立多少數據類型就可以建立多少數據類型。但是用這種方法要存儲動態類型的內容并不是一件容易的事。PHP僅僅存取混合類型的數據。例如:它允許你突然改變所有節點的數據類型等。千萬不要低估了練習的作用。知道怎么做一件事與能夠去做一件事是截然不同的。我們希望你至少做一下改進庫的工作。明確的說,即使你并沒有成功,這也不算是浪費e“只有一個方法可以增強能力:那就是親自去做!”清單2-樹結構庫的實2.6關聯數在編程語言中,數組(a2.6關聯數在編程語言中,數組(arrays)是另外一種基本的結構體。數組以一種非常簡單的方式提供了一個存儲同樣數據類型的固定裝置(或者是集合,它使用獨一無二的鍵使你設置的每一個元上述C代碼的一個小片段聲明了一個數組,叫做my_integer_array,包含256個整數。你可以通過使用一個有序值索引該數組來給這些整數的每一個分配地址。這個數組的范圍從0到255(C從0以上是從數組中取出的五個元素(記住:C是從0開始計數的)由于匯編語言的特性,你經常被你先前定義的變量所束縛。在上述數組中,如果你忽然需要大于256的整數時,那么,這幾乎是不可能的。當然,你可能已經把這個變量定義成一個訪問這個整數數組的指針,也給它分配了257個元素—但是如果你需要另外一個元素時,該怎么辦?你將不得不再分配一個空間,拷貝舊數組的內容,釋放舊的、未被使用的空間。PHP使用了一個不同的方法。因為PHP沒有典型變量的聲明(僅僅只是類型定義,新的變量被分配,但是它不工作。無論什么時候你想通過把它的名字引進到名字域,以創建一個新的變量,你只需根據它的名稱創建一個存儲空間即可—其他什么工作都不需要做了。駐留在這個空間中的數據類型并不局限于某一種變量類型。無論怎么樣,在它不工作時,可以對它重新解釋,重新指定大小,重新分配。第一行創建了一個新的變量$my_var。PHP$my_var的最初類型設置為整型。然而第二行用一個字符串覆蓋的$my_var的內容。如果是使用一$my_var然后第三行通過創建一個數組又一次改變$my_var的類型。PHP(我們知道與這相似的其他語言沒有嚴格的變量類型,但是我們在這里沒有把它們歸結為傳統語PHP然后第三行通過創建一個數組又一次改變$my_var的類型。PHP(我們知道與這相似的其他語言沒有嚴格的變量類型,但是我們在這里沒有把它們歸結為傳統語PHP3.0會再被使用。在長期腳本語言中(或者在大型過程中使用的腳本語言,其結果是一大堆的“死內存。當使用很耗內存的且運行了很長一段時間的腳本語言時,將測試環境中的內存釋放到產品環境中之前監視這些內存,你要確信你的服務器不會崩潰。在這個問題上,PHP4.因為正式的變量聲明在PHP中是不需要的,所以變量的使用就是徹底動態的了。PHP量處理中的一個特殊情況就是數組。你可能知道這個普通的數組類型:變址數組。變址數組是0到n,n是可能的最大索引值。像Pascal這樣3到18。然而這些范圍在運行時被轉化回以0開始的索引。這些有序索引數組的關鍵特征是你可以從任何給定基準的索引那里計算另一個索引的值。例如:假設你想讀出三個連續的數組成員,從索引值2開始:在對for()語句的每次重復操作中,這一小段程序通過使用增量$i來計算訪問數組的下一關聯數組沒有這個特征。關聯數組的特殊之處在于它們可以用無序的鍵編排索引,例如字符串。每一個用作索引的字符串都有一個與之相關聯的值,因此被叫做關聯數組。可以想像,把一個字符串作為基準索引給出,那么,該字符串是不允許猜測數組中下一個有效索引值的。因而關聯數組不能以一種有序的方式為數據元素排序。所以,你必須知道這些數組的操作鍵,以取出它們的相關值。除此以外,前面討論過的函數list()和each(),在PHP中索引數組只是關聯數組的一種特殊形式。對一個索引數組成員當中的某一個使unset()時,除了產生一個不連續的數組之外,還使所有的其他成員(還有它們的順序)分離。欲知詳細信息,請參閱前面有關list()和eac()函數的描述。2.6.1顧名思義,多維數組的維數要多于一維。一維(或者單維)數組是通常所見數組的形式之一:為了索引這種類型的數組,你只需要一個索引值就夠了,它限制了這個索引范圍內的可能值的數量。但是當處理復雜數據結構時,通常創建一個多維數組是非常有用的。典型的例子包括位圖和圖像緩沖器。當你看著你的顯示器時,你可以看見(至少現在是這樣)桌面是一個二維的項目。窗口、位圖命令行、光標和指針—所有的東西都是二維的。為了用一種簡便的方式說明這個數據,你當然可以只用一維把所有的東西連續的存放在數組中—但更合適的方法是使用與那些輸入數據維數相等的數組。例如:為了存儲一個鼠標指針的位圖(一套像素值括位圖和圖像緩沖器。當你看著你的顯示器時,你可以看見(至少現在是這樣)桌面是一個二維的項目。窗口、位圖命令行、光標和指針—所有的東西都是二維的。為了用一種簡便的方式說明這個數據,你當然可以只用一維把所有的東西連續的存放在數組中—但更合適的方法是使用與那些輸入數據維數相等的數組。例如:為了存儲一個鼠標指針的位圖(一套像素值,你只需要給你的數組添加另一個索引:0—使用兩個循環,每維一個循環。圖2-12顯示的是一個二維數據的圖表,這個二維數據的數據元素放在一個坐標系統中。在內存里,這些數據元素當然會被連續地存儲(內存的索引只有一維);但是坐標系統是一個更合適的可視化分析工具。(元素位于數組[4][3]中(元素位于數組[2][5]中圖2-12兩維數組的結數組沒有限制維數的最大數目(坦白的說,我們現在還沒有試過—但是使用一個16維的或者更高維數的數組幾乎是沒有用處的。維數也可以有不同的類型(第一維是相關型的,第二維是用整數索引的,第三維又是相關型的等等。因此,它們對于顯示靜態數據也是非常有用的。2.6.2使用函數時,通常需要返回多個參數值或者改變給定參數。例如:fsockopen()把一個接口如果不能與所需的主機建立連接的話,這個代碼將打印錯誤的代碼及錯誤的原因。這些變量最初作為參數已傳遞給了fsockopen(如果不能與所需的主機建立連接的話,這個代碼將打印錯誤的代碼及錯誤的原因。這些變量最初作為參數已傳遞給了fsockopen(。然而,這些參數在fsockopen()的聲明中被聲明為“通過參考變量傳遞的,fsockopen()就能夠修改它們,并且能夠使它們返回之后在全局范圍通常函數并不通過參考變量來存取自身的參數。當它們在調試中修改其值的時候,它則是用初始值的本地副本工作的:兩個打印都輸出相同的內容。當calculate()在調試期間修改$a$i的內容將不被修改,盡管它已經作為參數$a的一個自變量傳遞。這是因為calculate()是用初始變量的副本工作的,而不是變量本身。因而,這個函數一返回,它使用的變量副本將被丟棄,其內容也將丟失。既然它是fsockopen()的情況之一,那么有時候也有必要使用一個參數來保留這些改變量,并使它們在全局范圍內可見。為了達到這個目的,變量是不能作為副本來傳遞的,但是可以通過參考變量來實現。通過參考變量傳遞參數的結果是在函數中只得到了訪問一個初始變量駐留的內存塊的指針。使用這些指針,函數能夠存取這些變量的全局句柄并直接改變它:$符號在上面的一小段程序中沒有了。當該字符放在一個 你不需要改變調用函數的那一行,使它包含$符號。當PHP找到一個需要把你的參于是,當calculate()修改$a時,并沒有修改$i的本地副本,但是存取$icalculate()會直接修改它。此外,因為calculate()沒有利用本地內存,當函數返回時,對calculate()會直接修改它。此外,因為calculate()沒有利用本地內存,當函數返回時,對當運用復合函數調用這一方法在某一程序行中作復雜計算時,對返回多個函數值,或巧妙地修改變量來說,通過訪問參數來傳遞參數通常是非常有用的方法。然而,你也可以直接把參數放在一個結構體中返回,但你應該避免分離結構體和將參數擠壓到參數清單。盡量不要過度使用這種參數。更不要把它作為你的日常工具—它實際上是一個非常不好的習慣(函數并不希望在全局范圍內修改它們的參數—有時候就是因為這樣才出現討厭的BUG。但是它常常會幫助你使事情變得簡單并且允許你使用很巧妙的竅門。一個可能的例子就是所謂“運行變量(runvariables”的自動更新。運行變量就是在一次規則循環中改變它自身值的變量(for()聲明中的計數變量就是這種特殊情況。由此受益的一個具體的例子就是運行長度編碼(RLE)規則,這個規則很多人都知道,因為它一直用在(現在仍然在使用)如Zsof’sPX圖像格式一樣的格式中。聯想稍微豐富的人都可以看出,這個方陣是由許多0組成的立方體和許多1組成的邊框集合而成。如果按照它原來的形式把它寫到一個文件中,你將需要20×10=2002010。我們這里且假定一個元素占用至少一個字節的空間,壓縮文件則可以把這些信息壓縮成一丁點大。然而,你可以看到把這些數據按照它本來的形式存儲是沒有意義的。如果你向其他人說明這些數據,你不會按照“一、一、一??零、零、零”這樣的方式去讀,而是告訴他“二十個一,然后有一個一,然后18。然后使用“個數/數值”這樣的一對數據來存儲他們。壓縮之后,以上的數據就會變成這樣:通常第一個元素是計數元素,第二個元素是是數據元素。為了解壓這些數據,你只需要讀取這些計數元素,然后輸出相鄰的、出現頻率等同于計數元素的數據元素。你可以看到,就這么一個小小的“詭計”把必要元素的個數從兩百個減少到34個。這個壓縮規則的缺點就是當它在一行中碰到許多不同的元素時,它將創建一個比原來輸入數據還要大的輸出數據。因為存儲一大堆數據只有一次的元素馬上使得這個規則變得無效了。為了解決這個問題,我們可以添加一個小的原則,這個原則也就是“個數極限”每一種類21值是18和2。因而,重新把個數的范圍限定在1—3121值是18和2。因而,重新把個數的范圍限定在1—31的范圍內,我們就可以把那些并不需要壓縮的“千奇百怪”的數據放到輸出流中—壓縮僅僅只是把個數多于31的數據元素清理出來,在31100%的優化。所有個數小于或者等于31的數據將不被優化而直接放到壓縮數據中去,這些數據解壓這些數據的時候,區別沒有被壓縮的數據和壓縮過的數據是至關緊要的,就像程序清單2-3、2-4和2-5中所顯示的那樣。在這些清單中,變量參數是非常簡單的。清單2-3RLE壓高級語 高級語 清單2-4RLE解壓清單2- RLE引擎使用舉清單2- RLE引擎使用舉這個例子非常好地顯示了解碼和讀取的邏輯過程可以被抽象成更小的單獨的函數。實際的解碼過程現在只有幾行了。提供輸入數據的函數可以從代碼的剩余部分分離出來。區別壓縮的和沒有被壓縮的數據的“決定者”又是一個單獨的很小的易被理解的函數。1返回。這樣解壓縮程序就不必要擔心這些了—這個例子非常好地顯示了解碼和讀取的邏輯過程可以被抽象成更小的單獨的函數。實際的解碼過程現在只有幾行了。提供輸入數據的函數可以從代碼的剩余部分分離出來。區別壓縮的和沒有被壓縮的數據的“決定者”又是一個單獨的很小的易被理解的函數。1返回。這樣解壓縮程序就不必要擔心這些了—它只需要把提供給它的數據寫到輸出數組中就可以了。1.變量參數列表(Variableargumentlists,通常也叫做可選參數(optionalparameters,允許你預先定義一個有缺省值的函數參數。如果調用者不指定參數值,那么就假定為缺省值。這使得函數能夠提供給調用著一列可以使用但不是必須使用的可選參數。函數open_函數open_http_connection()存取$hostname規則參數,這個參數指定了該函數希望連接的主機名字。另外,它有兩個可選參數$port和$timeout,這兩個參數分別包含了連接的端口號和以秒計算的連接時間限制。這兩個參數有預先定義的缺省值,用“=”號指出,等號后面就是所希望的缺省值。因而,不管什么時候,只要調用者沒有給出這些參數,PH就用這個函數中所設的缺省值代替。從這個調用的例子中可以看到,第一次調用只用到了$hostname。$port和$timeout沒有用,于$regular_socket=open_http_connection("",80,第二次調用,你仍然可以依次地指定可選參數,然后覆蓋它們的缺省值。$port的值仍然是第三個例子中,你需要提供缺省參數的值,這個值可以隨意改動。這里只有$port被指定為了8080。$timeout沒有指定值,所以它仍然保持為缺省值10秒。由于PHP不能猜測哪一個值屬于哪一個參數,這就需要把所有可選參數都放在參數列表的尾部。如果你已經把$hostname作為唯一需要的參數放在了列表的尾部($port和$timeout,只指定$hostnamePHP認為這個主機的字符串實際上是$port的值,這樣就制造了許多混亂。你也不能隨便挑選一套你想要賦值的可選參數—如果你有一個函數存取這三個可選參數,但是你只想改變參數列表中的最后一個值,那么,你還需要提供其他兩個參數的缺省值(也像上面第二次調用中顯示的那樣,只有$timeou。在PHP4.0中,實型變量參數是可以的。一個函數可以使用比這個函數定義列表多的參數。你可以使用func_get_arg、func_num_args和func_get_ag()來存取任何數量的參數。函數func_get_args()的返回值是一個索引數組,它由傳遞給這個函數的所有參數從左至右填充。2.不定變量名,對于那些不知道的人來說(我們第一次聽到它的時候也是一樣)真是莫名其PHP的$my_var被預先確定為$$。這基本上就是不定變量名的工作機制。當然,你可以用不定變量名先進后出的方法來獲取不同的不定變量名(或用其他的方法,但是單是用不定變量名你就已經做得很好了。一個實際的例子是phpPolls,在第一章中描述的選舉室用的程序,其“開發概念”就使用了cookie的。使用者什么時候投票,一個名為cookie的配置就什么時候安裝,其名字有一個可配置前綴和一個獨一無二的ID標志來識別投票。當cookie被重新引進到全局名稱域時,一個使用者什么時候想要phpPolls就什么時候檢查和以前建立的cookie一樣的全局變量名是否存在。如果存在phpPolls就拒絕這張選票。不定變量名對于執行這項任務是非常便利的。下面就是從phpPolls這段代碼首先取出cookie獨一無二的ID,這個IDcookie前綴$poll_cookiePrefix裝在這個ID前面,組成所希望的變量名$poll_cookieName。使用isset(,這個變量(也就是cookie)的存在性就被決定了,因而也就可以起作用了。3.當然,我們在前面提到的關于不定變量名的內容對函數名來說也是有效的。函數名可以使用變量名建立,提供一個處理數據、安裝可修改的回收功能等的動態方法。你可以使用一個字符串變量來指定你想要調用的函數,而不是明確指定函數名:聲明$my_func后,變量聲明$my_func后,變量$function被指定為一個字符串“my_func。由于該字符串名與你想調用的函數名相同,所以,調用該字符串時,你可以使用該名字。當然,這是變量函數名的一個非常簡單的例子。當你需要在不同函數之間切換,而只使用許多變量標志時,變量函數名就非常有用了。假設你想要對電子郵件的附件進行解碼。這些附件可能有不同的格式——這里只用兩個名字,base64和uuencoded。創建一個封閉的只能夠識別一個或者兩個編碼格式而且還不能被擴展的語法分析程序并不是一個好方法。一旦要求用新格式解碼,你就會被困住。這種情況就是變量函數名的最好用武之地。determine_encoding()符串,該字符串指示要被解碼數據類型,每個字符串都要有一個相關的函數存在。這個要被調用的函數名通常被寫到$decode中,然后馬上被調用。這種方法的缺點是不夠簡潔。在這個方法里面,你幾乎看不到一個缺省的行為—解碼裝置完全是動態的,而且如果determine_encoding()產生了一個沒有意義的結果,它很可能會崩潰。然而它對于處理輸入數據是非常方便的。只要新的編碼類型一出現,你就能創建一個有貼切名稱的函數,然后調整determine_encoding,返回一個相關的字符串。只要你使得determine_encoding()穩定,意思是說它將返回一個有意義的字符串(即使它是虛擬的,我們就可以說這個技術的使用是完全合法的。只要你確信腳本程序在整個運行期間phpIRC(phpIRC(在下一章中我們要討論的軟件。phpIRC是一個PHP的一個IR(InternetRelayChat)層,它通過一個非常方便的API提供IRC網絡的存取。因為輸入數據的句柄是非線性的,完全是依賴于用戶的,所以phpIRC擁有一套把引入的數據包分類的事件。使用者可以為每一個事件給phpIRC設置句柄,它能夠對引入通信量的每一種類型起作用。phpIRC能夠把回調函數的名字存儲在一個內部數組中。只要數據到達,它就掃描其函數的回調數組,看它能否與偵測到的數據類型匹配,連續的調用所有匹配的函數。與前面提到的關于電子郵件的例子相似,它允許動態數據處理。當你可以(或者想要)在運行過程中決定如何處理即將發生的事件的時候,它是非常簡便的。考慮得更深遠一點,你可以使用變量函數名去改變腳本程序運行時的狀態,你也可以安裝一個用戶定義的在運行時能夠自己連接代碼的“插件,在一行代碼也不用改變的情況下,獲得附加的功能。2.7多態和自變代變量函數名的缺點(也有一部分不定變量名)是通常必須要有固定的程序部分(在變量函數名的情況中,有一系列你可以使用的前面已經聲明的的函數)和一個變化的程序部分(用一個變量構造函數名然后調用那些已經有構造名稱的函數部分。這意味著你必須為每一個可能已構造的名稱預先創建一個函數,這樣才能使你的程序正確地進行操作—這似乎有些嚴格。可以通過使用完全的動態程序來克服這個缺點—這個程序憑空自行產生。最開始這是早期程序設計的一個思想,一部分是游戲程序員和編寫病毒的人發明的。這完全是從自變代碼開始的。在游戲的內部循環中—舉個例子,負責把緩沖區輸出到熒幕的過程——速度是(現在仍然是)至關重要的。然而,因為過程的時間并非用不完,所以人們不得不想出新的方法以盡可能發揮其最高性能。通常的情況就是在最內層的循環中,必須要有非常多的判定程序。例如:如果某種情況下if()/then結構嵌入到最不需要它們的部分程序代碼中。這些結構耗費寶貴的程序執行時間。既然最內層的例程占用了全部程序總運行時間的80%左右,那么通過刪除這些結構使它的速度提高50%的結果是能夠節省40%的計算機資源。然而創建一套例程去處理每一種情況不會有太大的用處。如果你這樣做了,就會浪費代碼的空間,而僅僅只是把判定程序移到其他地方去了。當然,最后你可以獲得更好的全面的性能,但不是最理想的性能。/then結構的一個條件,它不是去調整相關的負責這部分功能的標志,而是把內層循環按我們所需要的那樣重新編程。這就是說如果需要,它就計算標志值。必要的修改通常只是改變一兩個字節的事情,決不會比設置一套標志工作量更大。但是這只能在機器代碼中起作用,當然它是絕對依賴于系統的—但又極其有用。因為他們可以自己改變自己的代碼但是
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 高校微課程設計與應用學習心得體會
- 以天津音樂學院為例探索音樂藝術院校大學生心理健康教育路徑
- 以境啟思:高中思想政治課貫穿式情境教學的深度探究與實踐
- 以圖啟智:初中地理教學中地圖對學生智能培養的深度探究
- 工業自動化設備維護專業實習總結范文
- 重慶市西北狼教育聯盟2024-2025學年高一上學期入學考試物理試題
- 道路環保工程施工合同書范文
- 政務服務審批辦理流程
- 港口建設危大工程清單及安全管理措施
- 東華大學自主招生健康體魄自薦信范文
- 糧食的形態與化學組成第二節糧食的主要化學成分下64課件
- 中國凈菜行業市場深度研究及發展趨勢預測報告
- 糖尿病飲食治療講課件
- 輸液反應急救護理流程講課件
- 鋼結構倉庫施工組織設計
- 變電站電氣設備管理制度
- 中國農田水利行業發展前景及發展策略與投資風險研究報告2025-2028版
- 50篇短文搞定高考英語3500單詞
- 物業消防檢查培訓課件
- 專題 完形填空 七年級英語下冊期末復習考點培優專項北師大版(2024版)(含答案解析)
- 余料使用管理制度
評論
0/150
提交評論