基本類型 PHP是一種弱類型語言。
PHP類型檢查函數 is_bool() is_integer() is_double() is_string() is_object() is_array() is_resource() is_null()
繼承 繼承是從一個基類獲得一個或多個派生系類的機制。 繼承自另外一個類的類被稱爲該類的子類。 子類能夠增長父類(也稱超類,superclass)以外新的功能,所以子類也被稱爲擴展。
構造方法和繼承 句柄(handle) php爲此提供了parent關鍵字 parent ::__construct() 意爲「調用父類的__construct()方法」
public private protected 管理類的訪問 若使用舊的var關鍵字,方法和屬性默認設置爲public.
在任何地方均可以訪問public屬性和方法。
只能在當前類忠才能訪問private方法或屬性,及時在子類中葉不能訪問。
能夠在當前類或者子類中訪問protected方法或屬性,其餘外部代碼無權訪問。
訪問方法 比較好的作法是不要允許直接訪問屬性,而是提供方法來取得須要的值,這樣的方法被稱爲訪問方法,也可稱爲getter和setter.
靜態方法和屬性 把類當作生成對象的模板,吧對象做爲活動組件,對象的方法能夠被調用,對象的屬性能夠被訪問。 面向對象編程中的實際操做都是經過類的實例(而不是類自己)完成的。類僅僅是對象的模板。
靜態方法是以類做爲做用域的函數。靜態方法不能訪問這個類忠的普通屬性,由於那些屬性屬於一個對象,但能夠訪問靜態屬性。 static 關鍵字
常量屬性 能夠在類中定義常量屬性。和全局常量同樣,類常量一旦設置後就不能改變。常量屬性用const關鍵字來聲明,常量不像常規屬性那樣以美圓符號開頭,按照慣例,只能用大寫字母來命名常量。常量屬性只包含基本數據類型的值,不能將一個對象指派給常量。像靜態屬性同樣,只能經過類而不能經過類的實例訪問常量屬性。引用常量時不須要用美圓符號做爲前導符,如print ShopProduct :: AVAILABLE; 給已經聲明過的常量賦值會引發解析錯誤。當須要在類的全部實例中都能訪問某個屬性,而且屬性值無需改變時,應該使用常量。
抽象類(abstract class) 抽象類不能被直接實例化。抽象類中只定義(或部分實現)子類須要的方法。子類能夠繼承它而且經過實現其中的抽象方法,使抽象類具體化。 可使用abstract關鍵字定義一個抽象類。和普通的類同樣,能夠建立抽象類的方法和屬性,可是實例化一個抽象類會產生錯誤,如一個抽象類, abstract class ShopProductWriter 如今去實例化它 $writer = new ShopProductWriter() 會提示輸出嚴重錯誤:不能實例化抽象類。 建立抽象方法後,要確保全部子類中都實現了該方法, 但實現的細節能夠先不肯定。抽象類的每一個子類都必須實現抽象類中全部的抽象方法,或者把它們自身也聲明爲抽象方法。 擴展類不只僅負責簡單實現抽象類中的方法,還必須從新聲明方法。新的實現方法的訪問控制不能比抽象方法的訪問控制更嚴格,新的實現方法的參數個數應該和抽象方法的參數個數同樣,從新生成對應的類型提示。
接口(interface) 抽象類提供了具體實現標準,而接口(interface)則是純粹的模板。接口只能定義功能,而不包含實現的內容。接口可用關鍵字interface來聲明。接口能夠包含屬性和方法聲明,可是方法體爲空。 例如定義一個接口
interface Chargeable{
public function getPrice();
}
接口和類很是類似。任何實現接口的類要實現接口中所定義的全部方法,不然該類必須聲明爲abstract。
一個類能夠在聲明中使用implements關鍵字來實現某個接口。這麼作以後,實現接口的具體過程和擴展一個僅包含抽象方法的抽象類是同樣的。 好比讓ShopProduct類實現Chargeable接口,class ShopProduct implements Chargeable 實現多個接口能夠用逗號隔開,例如Bookable是接口名 class Consultancy extends TimedService implentes Bookable, Cargeable 這樣Consultancy類就實現了不止一個接口,php只支持繼承自一個父類,所以extends關鍵字只能在一個類名以前。
延遲靜態綁定: static關鍵字
錯誤處理 能夠中止執行代碼,簡單激烈,雖然__construct 和 write() 這樣的方法能夠檢測到錯誤,可是它們並不知道該如何處理錯誤。 不在類中直接處理錯誤,而只返回某種錯誤標誌。錯誤標誌能夠是布爾值或整數值。一些類也能夠設置錯誤字符串或標誌,讓客戶端代碼在失敗以後能夠得到更多信息。
異常(exception) 異常是從php內置的Exception類(或其子類)實例化獲得的特殊對象。Exception類型的對象用於存放和報告錯誤信息。exception類的構造方法接受兩個可選參數:消息字符串和錯誤代碼。拋出異常,能夠聯合使用throw關鍵字和Exception對象拋出異常。這會中止執行當前方法,並負責將錯誤返回給調用代碼。 異常子類化,若是要建立用戶自定義的異常類,能夠從exceotion類繼承,能夠擴展異常類的功能,子類定義了新的異常類型,能夠進行本身特有的錯誤處理。實際上,定義多個catch子句時,也只需一個try語句。
Final類和方法 繼承爲類層次(class hierarchy)內毒帶來了巨大的靈活性。經過覆寫類或方法,根據調用的是哪一個類的實例,調用一樣的類方法能夠獲得徹底不一樣的結果。但有時候可能須要類或方法保持不變。若是但願類或方法完成肯定不變的功能,擔憂覆寫它會破壞這個功能,那麼須要使用final關鍵字。 final關鍵字能夠終止類的繼承。 final類不能有子類,final方法不能被覆寫。
使用攔截器interceptor
析構方法 __destruct() 它只在對象在被垃圾收集器收集前(即對象從內存中刪除以前)自動調用。能夠利用這個方法進行最後的清理工做,例若有一個類須要把其自身的信息寫入數據庫,這時可使用__destruct方法在對象實例被刪除時確保實例把本身保存到了數據庫中
例如function __destruct() {
if(!empty($this->id)){
//保存數據
printf "saving person\n";
}
}
使用__clone()複製對象 clone使用「值複製」方式(by-value copy)新生成一個對象
class = CopyMe{}
$first = new CopyMe();
$second = clone $first;
//php5及之後的版本:$second和$first如今是兩個不一樣的對象
在對象上調用clone時,能夠控制複製什麼。能夠經過實現一個特殊的方法__clone()來達到這個目的(__兩個下劃線開頭的方法都是PHP內置的方法)。當在一個對象上調用clone關鍵字時,其__clone()方法就會被自動調用。
實現__clone()方法時,要注意當前方法執行的環境。__clone()是複製獲得的對象上運行的,而不是在原始對象上運行的。給Person類添加上__clone()方法:
class Person{
private $name;
private $age;
private $id;
function __construct ($name, $age) {
$this->name = $name;
$this->age = $age;
}
function __construct ($name, $age) {
$this->id = $id;
}
function __clone() {
$this->id = 0;
}
}
當在一個Person對象上調用clone時,產生了一個新的副本,而且新副本的__clone()方法會被調用。這意味着咱們在__clone()中從新賦值會生效。
定義對象的字符串值 經過實現本身的 __toString()方法,能夠控制輸出字符串的格式。 __toString()方法應當返回一個字符串值。當把對象傳遞給print或echo時,會自動調用這個方法,並用方法的返回值來替代默認的輸出內容。如在Person類中添加__toString()方法:
class Person{
function getName() {return "Bob";}
function getAge() {return 44;}
function __toString() {
$desc = $this->getName();
$desc = "(age".$this->getAge().")";
return $desc;
}
}
如今把Person對象打印 出來,該對象會被解析爲:
$Person = new Person();
print $person;
-----------------------
Bob(age 44)
-----------------------
回調,匿名函數和閉包
PHP包和命名空間 命名空間就是一個容器,能夠將類,函數和變量放在其中,在命名空間中,能夠無條件地訪問這些項,在命名空間以外,必須導入或引用命名空間,才能訪問它所包含的項。namespace.
使用use關鍵字,利用該關鍵字,能夠爲當前命名空間中的其餘命名空間起別名 例:
namespace main;
use com\getinstance\util;
util\Debug::helloWorld();
導入com\getinstance\util命名空間,並隱式地爲其使用了別名until。沒有使用前導反斜線字符做爲開始。這裏是從全局命名空間而不是從當前命名空間搜索要使用的參數。若是不想引用命名空間,能夠導入Debug類自己:
namespace main;
use com\getinstance\util\Debug;
util\Debug::helloWorld();
以後吐過main命名空間中已經包含了Debug類,會形成命名衝突,解決方案是顯式使用別名。
namespace main;
use com\getinstance\util\Debug as uDebug;
.......
......
.....
uDebug::helloWorld();
在use關鍵字後使用as子句,能夠將別名Debug修改成uDebug。
若是打開命名空間塊的時候不指定名稱,那就能夠進入全局空間。
使用文件系統模擬包
PEAR風格的命名方式
包含路徑
自動加載
類函數和對象函數
查找類 class_exists()函數接受表示類的字符串,檢查並返回布爾值。若是類存在,則返回true,不然返回false。
對象或類 有不少用於檢測對象類型的基本工具。首先可使用get_class()函數檢查對象的類。它接受任何對象做爲參數,並以字符串的形式返回類名。 instanceof()操做符有兩個操做數,要檢測的對象在關鍵字左邊,類或藉口名在右邊。若是是給定類型的實例,則返回true。
類中的方法 可使用get_class_methods()函數來獲得一個類中全部的方法列表。該函數須要一個類名做爲參數,返回包含類中全部方法名的數組。 print_r( get_class_methods( 'CdProduct' ) ); //CdProduct是參數類。在調用某個方法以前,先檢測該方法是否存在於get_class_methods()返回的數組中,可使用函數is_callable()和method_exists()來檢查。兩個函數中is_callable()更高級些,它接受字符串變量形式的方法名做爲第一個參數,若是類方法存在且可被調用,則返回true。若是要檢測類中的方法能否被調用,能夠給函數傳遞一個數組而不是類方法名做爲參數。數組必須包含對象或類名,以將其做爲它的第一個元素,要檢查的方法名做爲第二個元素。若是該方法在類中存在,函數會返回true。
類屬性 get_class_vars()函數接受類名做爲參數,返回關聯數組。在返回的數組中,屬性名做爲鍵名,屬性值做爲鍵值。
繼承 get_parent_class()來找到一個類的父類。這個函數須要一個對象或類名做爲參數,而且若是父類存在的話,就返回父類的名字。若是不存在這樣的類,即咱們檢測到的類沒有父類,就返回false。 也可可使用is_subclass_of()函數檢測類是不是另外一個類的派生系。它須要接受一個子類對象和父類的名字。若是第二個參數是第一個參數的父類的話,該函數就返回true。 is_subclass_of() 只會告訴你類的繼承關係,而不會告訴你類是否實現了一個接口。所以若是須要檢測一個類是否實現了某個接口,應當使用instanceof操做符,或者可使用一個函數,該函數式SPL(Standard PHP Library, 標準PHP類庫)的一部分。class_implements()使用一個類名或一個對象引用做爲參數,而且返回一個由接口名構成的數組。
方法調用
使用字符串來動態調用方法的例子
$product = getProduct(); //得到對象
$method = "getTitle"; //定義方法名
print $product->$method; //調用方法
PHP還提供call_user_func()方法來達到相同的目的。
反射API 不可缺乏的類測試工具 ReflectionFuction
var_dump()和姊妹函數print_r()是檢測PHP代碼中數據的利器,但對於類和函數,反射API提供了更高層次的功能。
檢查類 ReflectionClass::getName()返回要檢查的類名。若是類已經在PHP代碼中定義,ReflectionClass::isUSerDefined()方法返回true;若是是內置類,則ReflectionClass::isInsternal()返回true。 能夠用ReflectionClass::isAbstract()來測試一個類是不是抽象的,用ReflectionClass::isInterface()來測試類是不是接口。若是想獲得類的實例,能夠用RefectionClass::isInstantiable()測試是否可行。
檢查方法 就像ReflectionClass能夠用於檢查類同樣,ReflectionMethod對象能夠用於檢查類中的方法。 得到ReflectionMethod對象的方法有兩種:從ReflectionClass::getMethod()可接受一個方法名做爲參數並返回相應的ReflectionMethod對象。
檢查方法參數 反射API提供了ReflectionParameter類。要得到ReflectionParameter對象,須要Reflection Method對象的幫助。 ReflectionMethod::getParameters()方法可返回ReflectionParameter對象數組。 ReflectionParameter能夠告訴你參數的名稱,變量是否能夠按引用傳遞(即方法聲明前有一個&符號),還能夠告訴你參數類型提示和方法是夠接受空值做爲參數。
面向對象設計和過程式編程
內聚(cohesion)是一個模塊內部各成分之間的關聯程度的度量。理想狀況下,應該使各組件職責清晰,分工明確。若是代碼間的關聯範圍太廣,維護就會困難,由於你須要在修改某部分代碼的同時修改相關的代碼。
耦合 當系統各部分代碼緊密綁在一塊兒時,就會產生緊密耦合,這時在一個組件中的變化會迫使其餘部件隨之改變。緊密耦合並非過程式代碼特有的,可是過程式比較容易產生耦合問題。
正交(orthogonality)指將職責相關的組件牢牢組合在一塊兒,而與外部系統環境隔開,保持獨立。正交主張重用組件,指望不須要任何特殊配置就能把一個組件插入到新系統中。這樣的組件有明確的與環境無關輸入和輸出。正交代碼使修改變地更簡單,由於修改一個實現只會影響到被改動的組件自己。更安全,bug的影響做用域只侷限於它的做用域之中。
----------------------------php學習筆記2016.1