亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

Home php教程 php手冊(cè) php5學(xué)習(xí)筆記(轉(zhuǎn))

php5學(xué)習(xí)筆記(轉(zhuǎn))

Jun 21, 2016 am 09:15 AM
function gt php quot this

php5|筆記

作者: whhwq
在phpv.net看到的感覺(jué)不錯(cuò)
/*
+-------------------------------------------------------------------------------+
| = 本文為Haohappy讀>
| = 中Classes and Objects一章的筆記
| = 翻譯為主+個(gè)人心得
| = 為避免可能發(fā)生的不必要的麻煩請(qǐng)勿轉(zhuǎn)載,謝謝
| = 歡迎批評(píng)指正,希望和所有PHP愛(ài)好者共同進(jìn)步!
+-------------------------------------------------------------------------------+
*/

PHP5學(xué)習(xí)筆記
第一節(jié)--面向?qū)ο缶幊?br>面向?qū)ο缶幊瘫辉O(shè)計(jì)來(lái)為大型軟件項(xiàng)目提供解決方案,尤其是多人合作的項(xiàng)目. 當(dāng)源代碼增長(zhǎng)到一萬(wàn)行甚至更多的時(shí)候,每一個(gè)更動(dòng)都可能導(dǎo)致不希望的副作用. 這種情況發(fā)生于模塊間結(jié)成秘密聯(lián)盟的時(shí)候,就像第一次世界大戰(zhàn)前的歐洲.
//haohappy注:喻指模塊間的關(guān)聯(lián)度過(guò)高,相互依賴性太強(qiáng).更動(dòng)一個(gè)模塊導(dǎo)致其它模塊也必須跟著更動(dòng).
想像一下,如果有一個(gè)用來(lái)處理登錄的模塊允許一個(gè)信用卡處理模塊來(lái)分享它的數(shù)據(jù)庫(kù)連接. 當(dāng)然出發(fā)點(diǎn)是好的,節(jié)省了進(jìn)行另一個(gè)數(shù)據(jù)庫(kù)連接的支出.然而有時(shí),登錄處理模塊改變了其中一個(gè)變量的名字,就可能割斷了兩者間的協(xié)議.導(dǎo)致信用卡模塊的處理出錯(cuò),進(jìn)而導(dǎo)致處理發(fā)票的模塊出錯(cuò). 很快地,體系中所有無(wú)關(guān)的模塊都可能由此出錯(cuò).
因此,我覺(jué)得有點(diǎn)戲劇性地,絕大多數(shù)程序員都對(duì)耦合和封裝心存感激. 耦合是兩個(gè)模塊間依賴程度的量度. 耦合越少越好.我們希望能夠從已有的項(xiàng)目中抽走一個(gè)模塊并在另一個(gè)新項(xiàng)目中使用.
我們也希望在某個(gè)模塊內(nèi)部大規(guī)模的更動(dòng)而不用擔(dān)心對(duì)其他模塊的影響. 封裝的原則可以提供這個(gè)解決方案.模塊被看待成相對(duì)獨(dú)立,并且模塊間的數(shù)據(jù)通信通過(guò)接口來(lái)進(jìn)行. 模塊不通過(guò)彼此的變量名來(lái)窺探另一個(gè)模塊,它們通過(guò)函數(shù)來(lái)禮貌地發(fā)送請(qǐng)求.
封裝是你可以在任何編程語(yǔ)言中使用的一個(gè)原則. 在PHP和許多面向過(guò)程的語(yǔ)言中,可以偷懶是很有誘惑的.沒(méi)有什么可以阻止你通過(guò)模塊來(lái)構(gòu)建一個(gè)假想的WEB. 面向?qū)ο缶幊淌鞘钩绦騿T不會(huì)違背封裝原則的一種方法.
在面向?qū)ο缶幊讨?模塊被組織成一個(gè)個(gè)對(duì)象. 這些對(duì)象擁有方法和屬性. 從抽象的角度來(lái)看,方法是一個(gè)對(duì)象的所做的動(dòng)作,而屬性是對(duì)象的特性.從編程角度來(lái)看,方法就是函數(shù)而屬性是變量. 在一個(gè)理想化的面向?qū)ο篌w系中,每個(gè)部份都是一個(gè)對(duì)象. 體系由對(duì)象及對(duì)象間通過(guò)方法來(lái)形成的聯(lián)系構(gòu)成.
一個(gè)類定義了對(duì)象的屬性. 如果你在烘烤一組甜餅對(duì)象,那么類將會(huì)是甜餅機(jī). 類的屬性和方法是被調(diào)用的成員. 人們可以通過(guò)說(shuō)出數(shù)據(jù)成員或者方法成員來(lái)表達(dá).
每種語(yǔ)言提供了不同的途徑來(lái)訪問(wèn)對(duì)象. PHP從C++中借用概念,提供一個(gè)數(shù)據(jù)類型用來(lái)在一個(gè)標(biāo)識(shí)符下包含函數(shù)和變量。最初設(shè)計(jì)PHP的時(shí)候,甚至PHP3被開(kāi)發(fā)出時(shí),PHP并不打算提供開(kāi)發(fā)超過(guò)10萬(wàn)行代碼的大型項(xiàng)目的能力。隨著PHP和Zend引擎的發(fā)展,開(kāi)發(fā)大型項(xiàng)目變得有可能,但無(wú)論你的項(xiàng)目規(guī)模多大,用類來(lái)書寫你的腳本將可以讓代碼實(shí)現(xiàn)重用。這是一個(gè)好主意,特別當(dāng)你愿意與別人分享你的代碼的時(shí)候。
有關(guān)對(duì)象的想法是計(jì)算機(jī)科學(xué)上最令人興奮的概念之一。開(kāi)始很難掌握它,但我可以保證,一旦你掌握了它,用它的思維來(lái)思考將會(huì)非常自然。
第二節(jié)--PHP5 的對(duì)象模型
PHP5有一個(gè)單重繼承的,限制訪問(wèn)的,可以重載的對(duì)象模型. 本章稍后會(huì)詳細(xì)討論的”繼承”,包含類間的父-子關(guān)系. 另外,PHP支持對(duì)屬性和方法的限制性訪問(wèn). 你可以聲明成員為private,不允許外部類訪問(wèn). 最后,PHP允許一個(gè)子類從它的父類中重載成員.
//haohappy注:PHP4中沒(méi)有private,只有public.private對(duì)于更好地實(shí)現(xiàn)封裝很有好處.
PHP5的對(duì)象模型把對(duì)象看成與任何其它數(shù)據(jù)類型不同,通過(guò)引用來(lái)傳遞. PHP不要求你通過(guò)引用(reference)顯性傳遞和返回對(duì)象. 在本章的最后將會(huì)詳細(xì)闡述基于句柄的對(duì)象模型. 它是PHP5中最重要的新特性.
有了更直接的對(duì)象模型,基于句柄的體系有附加的優(yōu)勢(shì): 效率提高, 占用內(nèi)存少,并且具有更大的靈活性.
在PHP的前幾個(gè)版本中,腳本默認(rèn)復(fù)制對(duì)象.現(xiàn)在PHP5只移動(dòng)句柄,需要更少的時(shí)間. 腳本執(zhí)行效率的提升是由于避免了不必要的復(fù)制. 在對(duì)象體系帶來(lái)復(fù)雜性的同時(shí),也帶來(lái)了執(zhí)行效率上的收益. 同時(shí),減少?gòu)?fù)制意味著占用更少的內(nèi)存,可以留出更多內(nèi)存給其它操作,這也使效率提高.
//haohappy注:基于句柄,就是說(shuō)兩個(gè)對(duì)象可以指向同一塊內(nèi)存,既減少了復(fù)制動(dòng)作,又減少對(duì)內(nèi)存的占用.
Zand引擎2具有更大的靈活性. 一個(gè)令人高興的發(fā)展是允許析構(gòu)--在對(duì)象銷毀之前執(zhí)行一個(gè)類方法. 這對(duì)于利用內(nèi)存也很有好處,讓PHP清楚地知道什么時(shí)候沒(méi)有對(duì)象的引用,把空出的內(nèi)存分配到其它用途.
第三節(jié)--定義一個(gè)類
當(dāng)你聲明一個(gè)類,你需要列出對(duì)象應(yīng)有的所有變量和所有函數(shù)—被稱為屬性和方法. 3.1.1中顯示了一個(gè)類的構(gòu)成. 注意在大括號(hào)({})內(nèi)你只能聲明變量或者函數(shù). 3.1.2中顯示了如何在一個(gè)類中定義三個(gè)屬性和兩個(gè)方法.
3.1.1
class Name extends Another Class
{
Access Variable Declaration
Access Function Declaration
}
//定義一個(gè)跟蹤用戶的類
class User
{
//屬性
public $name;
private $password, $lastLogin;

//方法
public function __construct($name, $password)
{
$this->name = $name;
$this->password = $password;
$this->lastLogin = time();
$this->accesses++;
}

// 獲取最后訪問(wèn)的時(shí)間
function getLastLogin()
{
return(date("M d Y", $this->lastLogin));
}
}

//創(chuàng)建一個(gè)對(duì)象的實(shí)例
$user = new User("Leon", "sdf123");

//獲取最后訪問(wèn)的時(shí)間
print($user->getLastLogin() ."
\n");

//打印用戶名
print("$user->name
\n");
?>
當(dāng)你聲明屬性,你不需要指明數(shù)據(jù)類型. 變量可能是整型,字符串或者是另一個(gè)對(duì)象,這取決于實(shí)際情況.在聲明屬性時(shí)增加注釋是一個(gè)好主意,標(biāo)記上屬性的含義和數(shù)據(jù)類型.

當(dāng)你聲明一個(gè)方法,你所做的和在類外部定義一個(gè)函數(shù)是一樣的. 方法和屬性都有各自的命名空間. 這意味著你可以安全地建立一個(gè)與類外部函數(shù)同名的方法,兩者不會(huì)沖突. 例如,一個(gè)類中可以定義一個(gè)名為date()的方法. 但是你不能將一個(gè)方法命名為PHP的關(guān)鍵字,如for或者while.

類方法可能包含PHP中所謂的type hint. Type hint 是另一個(gè)傳遞參數(shù)給方法的類的名字. 如果你的腳本調(diào)用方法并傳遞一個(gè)不是類的實(shí)例的變量,PHP將產(chǎn)生一個(gè)”致命(fatal)錯(cuò)誤” . 你可能沒(méi)有給其它類型給出type hint,就像整型,字符串,或者布爾值. 在書寫的時(shí)候, type hint是否應(yīng)當(dāng)包含數(shù)組類型仍存在爭(zhēng)議.

Type hint是測(cè)試函數(shù)參數(shù)或者運(yùn)算符的實(shí)例的數(shù)據(jù)類型的捷徑. 你可能總是返回這個(gè)方法. 確認(rèn)你強(qiáng)制讓一個(gè)參數(shù)必須是哪種數(shù)據(jù)類型,如整型. 3.2.1 確保編譯類只產(chǎn)生Widget的實(shí)例.

3.2.1
PHP代碼:

//組件
class Widget
{
public $name='none';
public $created=FALSE;
}

//裝配器
class Assembler
{
public function make(Widget $w)
{
print("Making $w->name
\n");
$w->created=TRUE;
}
}

//建立一個(gè)組件對(duì)象
$thing = new Widget;
$thing->name = 'Gadget';

//裝配組件
Assembler::make($thing);
?>
除了傳遞參數(shù)的變量外,方法含有一個(gè)特殊的變量. 它代表類的個(gè)別實(shí)例. 你應(yīng)當(dāng)用這個(gè)來(lái)指向?qū)ο蟮膶傩院推渌椒?一些面向?qū)ο蟮恼Z(yǔ)言假設(shè)一個(gè)不合格的變量提交給本地屬性,但在PHP中方法的任何變量只是在方法的一定范圍內(nèi). 注意在User類的構(gòu)造函數(shù)中這個(gè)變量的使用(3.1.2).

PHP在屬性和方法聲明前定義一個(gè)訪問(wèn)限定語(yǔ),如public,private和protected. 另外,你可以用”static”來(lái)標(biāo)記一個(gè)成員. 你也可以在類中聲明常量. 本章稍后會(huì)有不同訪問(wèn)方式的相關(guān)討論.

你可以在一行中列出相同訪問(wèn)方式的幾個(gè)屬性,用逗號(hào)來(lái)分隔它們. 在3.1.2中,User類有兩個(gè)private屬性--$password和$lastLogin.

第四節(jié)--構(gòu)造函數(shù)和析構(gòu)函數(shù)

如果你在一個(gè)類中聲明一個(gè)函數(shù),命名為_(kāi)_construct,這個(gè)函數(shù)將被當(dāng)成是一個(gè)構(gòu)造函數(shù)并在建立一個(gè)對(duì)象實(shí)例時(shí)被執(zhí)行. 清楚地說(shuō),__是兩個(gè)下劃線. 就像其它任何函數(shù)一樣,構(gòu)造函數(shù)可能有參數(shù)或者默認(rèn)值. 你可以定義一個(gè)類來(lái)建立一個(gè)對(duì)象并將其屬性全放在一個(gè)語(yǔ)句(statement)中.

你也可以定義一個(gè)名為_(kāi)_destruct的函數(shù),PHP將在對(duì)象被銷毀前調(diào)用這個(gè)函數(shù). 它稱為析構(gòu)函數(shù).

繼承是類的一個(gè)強(qiáng)大功能. 一個(gè)類(子類/派生類)可以繼承另一類(父類/基類)的功能. 派生類將包含有基類的所有屬性和方法,并可以在派生類中加上其他屬性和方法. 你也可以覆寫基類的方法和屬性. 就像3.1.2中顯示的,你可以用extends關(guān)鍵字來(lái)繼承一個(gè)類.

你可能想知道構(gòu)造函數(shù)是如何被繼承的. 當(dāng)它們和其它方法一起被繼承時(shí),他們不會(huì)在創(chuàng)建對(duì)象時(shí)被執(zhí)行.
如果你需要這個(gè)功能,你需要用第二章提到的::運(yùn)算符. 它允許你指向一塊命名空間. parent指向父類命名空間,你可以用parent::__construct來(lái)調(diào)用父類的構(gòu)造函數(shù).

一些面向?qū)ο笳Z(yǔ)言在類之后命名構(gòu)造函數(shù). PHP的前幾個(gè)版本也是如此,到現(xiàn)在這種方法仍然有效.也就是:如果你把一個(gè)類命名為Animal并且在其中建立一個(gè)命名也是Animal的方法,則這個(gè)方法就是構(gòu)造函數(shù).如果一個(gè)類的同時(shí)擁有__construt構(gòu)造函數(shù)和與類名相同的函數(shù),PHP將把__construct看作構(gòu)造函數(shù).這使得用以前的PHP版本所寫的類仍然可以使用. 但新的腳本(PHP5)應(yīng)當(dāng)使用__construct.

PHP的這種新的聲明構(gòu)造函數(shù)的方法可以使構(gòu)造函數(shù)有一個(gè)獨(dú)一無(wú)二的名稱,無(wú)論它所在的類的名稱是什么. 這樣你在改變類的名稱時(shí),就不需要改變構(gòu)造函數(shù)的名稱.

你可能在PHP中給構(gòu)造函數(shù)一個(gè)像其它類方法一樣的訪問(wèn)方式. 訪問(wèn)方式將會(huì)影響從一定范圍內(nèi)實(shí)例化對(duì)象的能力. 這允許實(shí)現(xiàn)一些固定的設(shè)計(jì)模式,如Singleton模式.

析構(gòu)函數(shù),相反于構(gòu)造函數(shù). PHP調(diào)用它們來(lái)將一個(gè)對(duì)象從內(nèi)存中銷毀. 默認(rèn)地,PHP僅僅釋放對(duì)象屬性所占用的內(nèi)存并銷毀對(duì)象相關(guān)的資源. 析構(gòu)函數(shù)允許你在使用一個(gè)對(duì)象之后執(zhí)行任意代碼來(lái)清除內(nèi)存.

當(dāng)PHP決定你的腳本不再與對(duì)象相關(guān)時(shí),析構(gòu)函數(shù)將被調(diào)用. 在一個(gè)函數(shù)的命名空間內(nèi),這會(huì)發(fā)生在函數(shù)return的時(shí)候. 對(duì)于全局變量,這發(fā)生于腳本結(jié)束的時(shí)候. 如果你想明確地銷毀一個(gè)對(duì)象,你可以給指向該對(duì)象的變量分配任何其它值. 通常將變量賦值勤為NULL或者調(diào)用unset .

下面的例子中,計(jì)算從類中實(shí)例化的對(duì)象的個(gè)數(shù). Counter類從構(gòu)造函數(shù)開(kāi)始增值,在析構(gòu)函數(shù)減值.

一旦你定義了一個(gè)類,你可以用new來(lái)建立一個(gè)這個(gè)類的實(shí)例. 類的定義是設(shè)計(jì)圖,實(shí)例則是放在裝配線上的元件. New需要類的名稱,并返回該類的一個(gè)實(shí)例. 如果構(gòu)造函數(shù)需要參數(shù),你應(yīng)當(dāng)在new后輸入?yún)?shù).
PHP代碼:
class Counter
{
private static $count = 0;

function __construct()
{
self::$count++;
}

function __destruct()
{
self::$count--;
}

function getCount()
{
return self::$count;
}
}

//建立第一個(gè)實(shí)例
$c = new Counter();

//輸出1
print($c->getCount() . "
\n");

//建立第二個(gè)實(shí)例
$c2 = new Counter();

//輸出2
print($c->getCount() . "
\n");

//銷毀實(shí)例
$c2 = NULL;

//輸出1
print($c->getCount() . "
\n");
?>
當(dāng)你新建了一個(gè)實(shí)例,內(nèi)存會(huì)被準(zhǔn)備來(lái)存儲(chǔ)所有屬性. 每個(gè)實(shí)例有自己獨(dú)有的一組屬性. 但方法是由該類的所有實(shí)例共享的.

第五節(jié)--克隆

PHP5中的對(duì)象模型通過(guò)引用來(lái)調(diào)用對(duì)象, 但有時(shí)你可能想建立一個(gè)對(duì)象的副本,并希望原來(lái)的對(duì)象的改變不影響到副本 . 為了這樣的目的,PHP定義了一個(gè)特殊的方法,稱為_(kāi)_clone. 像__construct和__destruct一樣,前面有兩個(gè)下劃線.

默認(rèn)地,用__clone方法將建立一個(gè)與原對(duì)象擁有相同屬性和方法的對(duì)象. 如果你想在克隆時(shí)改變默認(rèn)的內(nèi)容,你要在__clone中覆寫(屬性或方法).

克隆的方法可以沒(méi)有參數(shù),但它同時(shí)包含this和that指針(that指向被復(fù)制的對(duì)象). 如果你選擇克隆自己,你要小心復(fù)制任何你要你的對(duì)象包含的信息,從that到this. 如果你用__clone來(lái)復(fù)制. PHP不會(huì)執(zhí)行任何隱性的復(fù)制,

下面顯示了一個(gè)用系列序數(shù)來(lái)自動(dòng)化對(duì)象的例子:
PHP代碼:
class ObjectTracker //對(duì)象跟蹤器
{
private static $nextSerial = 0;
private $id;
private $name;

function __construct($name) //構(gòu)造函數(shù)
{
$this->name = $name;
$this->id = ++self::$nextSerial;
}

function __clone() //克隆
{
$this->name = "Clone of $that->name";
$this->id = ++self::$nextSerial;
}

function getId() //獲取id屬性的值
{
return($this->id);
}

function getName() //獲取name屬性的值
{
return($this->name);
}
}

$ot = new ObjectTracker("Zeev's Object");
$ot2 = $ot->__clone();

//輸出: 1 Zeev's Object
print($ot->getId() . " " . $ot->getName() . "
");

//輸出: 2 Clone of Zeev's Object
print($ot2->getId() . " " . $ot2->getName() . "
");
?>
第六節(jié)--訪問(wèn)屬性和方法

一個(gè)對(duì)象實(shí)例的屬性是變量,就像PHP的其他變量一樣. 但是你必須使用->運(yùn)算符來(lái)引用它們. 不需要在屬性前使用美元符$. 例如, 6.1中打印User對(duì)象的name屬性那一行.

可以聯(lián)用->,如果一個(gè)對(duì)象的屬性包含了一個(gè)對(duì)象,你可以使用兩個(gè)->運(yùn)算符來(lái)得到內(nèi)部對(duì)象的屬性. 你甚至可以用雙重引用的字符串來(lái)放置這些表達(dá)式. 看6.5中的例子,對(duì)象House中的屬性room包含了一組Room對(duì)象.

訪問(wèn)方法和訪問(wèn)屬性類似. ->運(yùn)算符用來(lái)指向?qū)嵗姆椒? 在例子6.1中調(diào)用getLastLogin就是. 方法執(zhí)行起來(lái)和類外的函數(shù)幾乎相同.

如果一個(gè)類從另一類中繼承而來(lái),父類中的屬性和方法將在子類中都有效,即使在子類中沒(méi)有聲明. 像以前提到過(guò)的,繼承是非常強(qiáng)大的. 如果你想訪問(wèn)一個(gè)繼承的屬性,你只需要像訪問(wèn)基類自己的屬性那樣引用即可,使用::運(yùn)算符.
PHP代碼:
class Room
{
public $name;

function __construct($name="unnamed")
{
$this->name = $name;
}
}

class House
{
//array of rooms
public $room;
}

//create empty house
$home = new house;

//add some rooms
$home->room[] = new Room("bedroom");
$home->room[] = new Room("kitchen");
$home->room[] = new Room("bathroom");

//show the first room of the house
print($home->room[0]->name);
?>
PHP有兩個(gè)特殊的命名空間arent命名空間指向父類,self命名空間指向當(dāng)前的類. 例子6.6中顯示了如何用parent命名空間來(lái)調(diào)用父類中的構(gòu)造函數(shù). 同時(shí)也用self來(lái)在構(gòu)造函數(shù)中調(diào)用另一個(gè)類方法.
class Animal //動(dòng)物
{
public $blood; //熱血or冷血屬性
public $name;
public function __construct($blood, $name=NULL)
{
$this->blood = $blood;
if($name)
{
$this->name = $name;
}
}
}

class Mammal extends Animal //哺乳動(dòng)物
{
public $furColor; //皮毛顏色
public $legs;

function __construct($furColor, $legs, $name=NULL)
{
parent::__construct("warm", $name);
$this->furColor = $furColor;
$this->legs = $legs;
}
}

class Dog extends Mammal
{
function __construct($furColor, $name)
{
parent::__construct($furColor, 4, $name);

self::bark();
}

function bark()
{
print("$this->name says 'woof!'");
}
}

$d = new Dog("Black and Tan", "Angus");
?>
第四章中介紹了如何調(diào)用函數(shù). 對(duì)于對(duì)象的成員來(lái)是這樣調(diào)用的:如果你需要在運(yùn)行時(shí)確定變量的名稱,你可以用$this->$Property這樣的表達(dá)式. 如果你想調(diào)用方法,可以用$obj->$method().

你也可以用->運(yùn)算符來(lái)返回一個(gè)函數(shù)的值,這在PHP以前的版本中是不允許的. 例如,你可以寫一個(gè)像這樣的表達(dá)式: $obj->getObject()->callMethod(). 這樣避免了使用一個(gè)中間變量,也有助于實(shí)現(xiàn)某些設(shè)計(jì)模式,如Factory模式.
第七節(jié)--類的靜態(tài)成員

類的靜態(tài)成員與一般的類成員不同: 靜態(tài)成員與對(duì)象的實(shí)例無(wú)關(guān),只與類本身有關(guān). 他們用來(lái)實(shí)現(xiàn)類要封裝的功能和數(shù)據(jù),但不包括特定對(duì)象的功能和數(shù)據(jù). 靜態(tài)成員包括靜態(tài)方法和靜態(tài)屬性.

靜態(tài)屬性包含在類中要封裝的數(shù)據(jù),可以由所有類的實(shí)例共享. 實(shí)際上,除了屬于一個(gè)固定的類并限制訪問(wèn)方式外,類的靜態(tài)屬性非常類似于函數(shù)的全局變量

我們?cè)谙吕惺褂昧艘粋€(gè)靜態(tài)屬性Counter::$count. 它屬于Counter類,而不屬于任何Counter的實(shí)例.你不能用this來(lái)引用它,但可以用self或其它有效的命名表達(dá). 在例子中,getCount方法返回self::$count,而不是Counter::$count.

靜態(tài)方法則實(shí)現(xiàn)類需要封裝的功能,與特定的對(duì)象無(wú)關(guān). 靜態(tài)方法非常類似于全局函數(shù). 靜態(tài)方法可以完全訪問(wèn)類的屬性,也可以由對(duì)象的實(shí)例來(lái)訪問(wèn),不論訪問(wèn)的限定語(yǔ)是否是什么.

在6.3例中,getCount是一個(gè)普通的方法,用->來(lái)調(diào)用. PHP建立一個(gè)this變量,盡管方法沒(méi)有使用到.但是,getCount不屬于任何對(duì)象.在有些情況下,我們甚至希望在不存在有效的對(duì)象時(shí)調(diào)用它,那么就應(yīng)該使用靜態(tài)方法. PHP將不在靜態(tài)方法內(nèi)部建立this變量,即使你從一個(gè)對(duì)象中調(diào)用它們.

例子6.7由6.3改變getCount為靜態(tài)方法而來(lái). Static關(guān)鍵字不能阻止一個(gè)實(shí)例用->運(yùn)算符來(lái)調(diào)用getCount,但PHP將不在方法內(nèi)部建立this變量.如果你使用this->來(lái)調(diào)用,將會(huì)出錯(cuò).

//6.3例指第四節(jié)--構(gòu)造函數(shù)和析構(gòu)函數(shù)中的例子(參看前文),通過(guò)兩個(gè)例子的比較,你可以很好掌握
//static方法與普通方法之間的區(qū)別.

你可以寫一個(gè)方法通過(guò)判斷this是否建立來(lái)顯示是否它被靜態(tài)地或者非靜態(tài)地調(diào)用. 當(dāng)然,如果你用了static 關(guān)鍵字,不管它怎樣被調(diào)用,這個(gè)方法總是靜態(tài)的.

你的類也可以定義常量屬性,不需要使用public static,只需要用const關(guān)鍵字即可. 常量屬性總是靜態(tài)的.它們是類的屬性,而不是實(shí)例化該類的對(duì)象的屬性.

Listing 6.7 Static members
PHP代碼:
class Counter
{
private static $count = 0;
const VERSION = 2.0;

function __construct()
{
self::$count++;
}

function __destruct()
{
self::$count--;
}

static function getCount()
{
return self::$count;
}
};

//創(chuàng)建一個(gè)實(shí)例,則__construct()將執(zhí)行
$c = new Counter();

//輸出 1
print(Counter::getCount() . "
\n");

//輸出類的版本屬性
print("Version used: " . Counter::VERSION . "
\n");
?>
第八節(jié)--訪問(wèn)方式

PHP5的訪問(wèn)方式允許限制對(duì)類成員的訪問(wèn). 這是在PHP5中新增的功能,但在許多面向?qū)ο笳Z(yǔ)言中都早已存在. 有了訪問(wèn)方式,才能開(kāi)發(fā)一個(gè)可靠的面向?qū)ο髴?yīng)用程序,并且構(gòu)建可重用的面向?qū)ο箢悗?kù).

像C++和Java一樣,PHP有三種訪問(wèn)方式ublic,private和protected. 對(duì)于一個(gè)類成員的訪問(wèn)方式,可以是其中之一. 如果你沒(méi)有指明訪問(wèn)方式,默認(rèn)地訪問(wèn)方式為public. 你也可以為靜態(tài)成員指明一種訪問(wèn)方式,將訪問(wèn)方式放在static關(guān)鍵字之前(如public static).

Public成員可以被毫無(wú)限制地訪問(wèn).類外部的任何代碼都可以讀寫public屬性. 你可以從腳本的任何地方調(diào)用一個(gè)public方法. 在PHP的前幾個(gè)版本中,所有方法和屬性都是public, 這讓人覺(jué)得對(duì)象就像是結(jié)構(gòu)精巧的數(shù)組.

Private(私有)成員只在類的內(nèi)部可見(jiàn). 你不能在一個(gè)private屬性所在的類方法之外改變或讀取它的值. 同樣地,只有在同一個(gè)類中的方法可以調(diào)用一個(gè)private方法. 繼承的子類也不能訪問(wèn)父類中的private 成員.

要注意,類中的任何成員和類的實(shí)例都可以訪問(wèn)private成員. 看例子6.8,equals方法將兩個(gè)widget進(jìn)行比較.==運(yùn)算符比較同一個(gè)類的兩個(gè)對(duì)象,但這個(gè)例子中每個(gè)對(duì)象實(shí)例都有唯一的ID.equals方法只比較name和price. 注意equals方法如何訪問(wèn)另一個(gè)Widget實(shí)例的private屬性. Java和C都允許這樣的操作.

Listing 6.8 Private members
PHP代碼:
class Widget
{
private $name;
private $price;
private $id;

public function __construct($name, $price)
{
$this->name = $name;
$this->price = floatval($price);
$this->id = uniqid();
}
//checks if two widgets are the same 檢查兩個(gè)widget是否相同
public function equals($widget)
{
return(($this->name == $widget->name)AND
($this->price == $widget->price));
}
}
$w1 = new Widget('Cog', 5.00);
$w2 = new Widget('Cog', 5.00);
$w3 = new Widget('Gear', 7.00);

//TRUE
if($w1->equals($w2))
{
print("w1 and w2 are the same
\n");
}

//FALSE
if($w1->equals($w3))
{
print("w1 and w3 are the same
\n");
}

//FALSE, == includes id in comparison
if($w1 == $w2) //不等,因?yàn)镮D不同
{
print("w1 and w2 are the same
\n");
}
?>
如果你對(duì)面向?qū)ο缶幊滩皇煜?你可能想知道用private成員的目的是什么. 你可以回憶一下封裝和耦合的想法,這在本章開(kāi)頭我們有討論過(guò). Private成員有助于封裝數(shù)據(jù). 他們可以隱藏在一個(gè)類內(nèi)部而不被類外部的代碼接觸到. 同時(shí)他們還有助于實(shí)現(xiàn)松散的耦合. 如果數(shù)據(jù)結(jié)構(gòu)外的代碼不能直接訪問(wèn)內(nèi)部屬性,那么就不會(huì)產(chǎn)生一個(gè)隱性的關(guān)聯(lián)性.

當(dāng)然,大部分private屬性仍然可以被外部代碼共享. 解決方法是用一對(duì)public方法,一個(gè)是get(獲取屬性的值),另一個(gè)是set(設(shè)置屬性的值). 構(gòu)造函數(shù)也接受屬性的初始值. 這使得成員間的交流通過(guò)一個(gè)狹窄的,經(jīng)過(guò)良好限定的接口來(lái)進(jìn)行. 這也提供改變傳遞給方法的值的機(jī)會(huì). 注意在例子6.8中,構(gòu)造函數(shù)如何強(qiáng)制使price成為一個(gè)float數(shù)(floadval()).

Protected(受保護(hù)的) 成員能被同個(gè)類中的所有方法和繼承出的類的中所有方法訪問(wèn)到. Public屬性有違封裝的精神,因?yàn)樗鼈冊(cè)试S子類依賴于一個(gè)特定的屬性來(lái)書寫.protected方法則不會(huì)帶來(lái)這方面的擔(dān)憂.一個(gè)使用protected方法的子類需要很清楚它的父類的結(jié)構(gòu)才行.

例子6.9由例子6.8改進(jìn)而得到,包含了一個(gè)Widget的子類Thing. 注意Widget現(xiàn)在有一個(gè)叫作getName的protected方法. 如果Widget的實(shí)例試圖調(diào)用protected方法將會(huì)出錯(cuò): $w1->getName()產(chǎn)生了一個(gè)錯(cuò)誤. 但子類Thing中的getName方法可以調(diào)用這個(gè)protected方法.當(dāng)然對(duì)于證明Widget::getName方法是protected,這個(gè)例子顯得過(guò)于簡(jiǎn)單. 在實(shí)際情況下,使用protected方法要依賴于對(duì)對(duì)象的內(nèi)部結(jié)構(gòu)的理解.

Listing 6.9 Protected members
PHP代碼:
class Widget
{
private $name;
private $price;
private $id;

public function __construct($name, $price)
{
$this->name = $name;
$this->price = floatval($price);
$this->id = uniqid();
}

//checks if two widgets are the same
public function equals($widget)
{
return(($this->name == $widget->name)AND
($this->price == $widget->price));
}

protected function getName()
{
return($this->name);
}
}

class Thing extends Widget
{
private $color;

public function setColor($color)
{
$this->color = $color;
}

public function getColor()
{
return($this->color);
}

public function getName()
{
return(parent::getName());
}
}

$w1 = new Widget('Cog', 5.00);
$w2 = new Thing('Cog', 5.00);
$w2->setColor('Yellow');

//TRUE (still!) 結(jié)果仍然為真
if($w1->equals($w2))
{
print("w1 and w2 are the same
\n");
}

//print Cog 輸出 Cog
print($w2->getName());
?>
一個(gè)子類可能改變通過(guò)覆寫父類方法來(lái)改變方法的訪問(wèn)方式,盡管如此,仍然有一些限制. 如果你覆寫了一個(gè)public類成員,他子類中必須保持public. 如果你覆寫了一個(gè)protected成員,它可保持protected或變成public.Private成員仍然只在當(dāng)前類中可見(jiàn). 聲明一個(gè)與父類的private成員同名的成員將簡(jiǎn)單地在當(dāng)前類中建立一個(gè)與原來(lái)不同的成員. 因此,在技術(shù)上你不能覆寫一個(gè)private成員.

Final關(guān)鍵字是限制訪問(wèn)成員方法的另一個(gè)方法. 子類不能覆寫父類中標(biāo)識(shí)為final的方法. Final關(guān)鍵字不能用于屬性.

//haohappy注:PHP5的面向?qū)ο竽P腿匀徊粔蛲晟?如final不像Java中那樣對(duì)Data,Method甚至Class都可以用.
第九節(jié)--綁定

除了限制訪問(wèn),訪問(wèn)方式也決定哪個(gè)方法將被子類調(diào)用或哪個(gè)屬性將被子類訪問(wèn). 函數(shù)調(diào)用與函數(shù)本身的關(guān)聯(lián),以及成員訪問(wèn)與變量?jī)?nèi)存地址間的關(guān)系,稱為綁定.

在計(jì)算機(jī)語(yǔ)言中有兩種主要的綁定方式—靜態(tài)綁定和動(dòng)態(tài)綁定. 靜態(tài)綁定發(fā)生于數(shù)據(jù)結(jié)構(gòu)和數(shù)據(jù)結(jié)構(gòu)間,程序執(zhí)行之前. 靜態(tài)綁定發(fā)生于編譯期, 因此不能利用任何運(yùn)行期的信息. 它針對(duì)函數(shù)調(diào)用與函數(shù)的主體,或變量與內(nèi)存中的區(qū)塊. 因?yàn)镻HP是一種動(dòng)態(tài)語(yǔ)言,它不使用靜態(tài)綁定. 但是可以模擬靜態(tài)綁定.

動(dòng)態(tài)綁定則針對(duì)運(yùn)行期產(chǎn)生的訪問(wèn)請(qǐng)求,只用到運(yùn)行期的可用信息. 在面向?qū)ο蟮拇a中,動(dòng)態(tài)綁定意味著決定哪個(gè)方法被調(diào)用或哪個(gè)屬性被訪問(wèn),將基于這個(gè)類本身而不基于訪問(wèn)范圍.

Public和protected成員的動(dòng)作類似于PHP的前幾個(gè)版本中函數(shù)的動(dòng)作,使用動(dòng)態(tài)綁定. 這意味著如果一個(gè)方法訪問(wèn)一個(gè)在子類中被覆寫的類成員,并是一個(gè)子類的實(shí)例,子類的成員將被訪問(wèn)(而不是訪問(wèn)父類中的成員).

看例子6.10. 這段代碼輸出” Hey! I am Son.” 因?yàn)楫?dāng)PHP調(diào)用getSalutation, 是一個(gè)Son的實(shí)例,是將Father中的salutation覆寫而來(lái). 如果salutation是public的,PHP將產(chǎn)生相同的結(jié)果. 覆寫方法的操作很類似.在Son中,對(duì)于identify的調(diào)用綁定到那個(gè)方法.

即使在子類中訪問(wèn)方式被從protected削弱成public, 動(dòng)態(tài)綁定仍然會(huì)發(fā)生. 按照訪問(wèn)方式使用的原則,增強(qiáng)對(duì)于類成員的訪問(wèn)限制是不可能的. 所以把訪問(wèn)方式從public改變成protected不可能進(jìn)行.

Listing 6.10 Dynamic binding 動(dòng)態(tài)綁定
PHP代碼:
class Father
{
protected $salutation = "Hello there!"; //問(wèn)候

public function getSalutation()
{
print("$this->salutation\n");
$this->identify();
}

protected function identify()
{
print("I am Father.
\n");
}
};

class Son extends Father
{
protected $salutation = "Hey!"; //父類中的protected $salutation 被覆寫

protected function identify() //父類中的protected identify() 被覆寫
{
print("I am Son.
\n");
}
};

$obj = new Son();
$obj->getSalutation(); //輸出Hey! I am Son.
?>
//注: 在子類中沒(méi)有覆寫getSalutation(),但實(shí)際上仍然存在一個(gè)getSalutation().這個(gè)類中的$salutation和identify()
//與Son子類的實(shí)例中的getSalutation()方法動(dòng)態(tài)綁定,所以調(diào)用Son的實(shí)例的getSalutation()方法,
//將調(diào)用Son類中的成員salutation及identify(),而不是父類中的成員salutation及identify().

Private成員只存在于它們所在的類內(nèi)部. 不像public和protected成員那樣,PHP模擬靜態(tài)綁定. 看例子6.11. 它輸出”Hello there! I am Father.”,盡管子類覆寫了salutation的值. 腳本將this->salutation和當(dāng)前類Father綁定. 類似的原則應(yīng)用于private方法identify().

Listing 6.11 Binding and private members
PHP代碼:
class Father
{
private $salutation = "Hello there!";

public function getSalutation()
{
print("$this->salutation\n");
$this->identify();
}

private function identify()
{
print("I am Father.
\n");
}
}

class Son extends Father
{
private $salutation = "Hey!";
private function identify()
{
print("I am Son.
\n");
}
}

$obj = new Son();
$obj->getSalutation(); //輸出Hello there! I am Father.
?>
動(dòng)態(tài)綁定的好處是允許繼承類來(lái)改變父類的行為,同時(shí)可以保持父類的接口和功能. 看例子6.12. 由于使用了動(dòng)態(tài)綁定,在deleteUser中被調(diào)用的isAuthorized的version 可以由對(duì)象的類型來(lái)確定. 如果是一個(gè)普通的user,PHP調(diào)用User::isAuthorized會(huì)返回FALSE.如果是一個(gè)AuthorizedUser的實(shí)例,PHP調(diào)用AuthorizedUser::isAuthorized,將允許deleteUser順利執(zhí)行.

//haohappy注:用一句話說(shuō)清楚,就是對(duì)象類型與方法,屬性綁定. 調(diào)用一個(gè)父類與子類中都存在的方法或訪問(wèn)一個(gè)屬性時(shí),會(huì)先判斷實(shí)例屬于哪種對(duì)象類型,再調(diào)用相應(yīng)的類中的方法和屬性.

Listing 6.12 動(dòng)態(tài)綁定的好處
PHP代碼:
class User //用戶
{
protected function isAuthorized() //是否是驗(yàn)證用戶
{
return(FALSE);
}

public function getName() //獲得名字
{
return($this->name);
}

public function deleteUser($username) //刪除用戶
{
if(!$this->isAuthorized())
{
print("You are not authorized.
\n");
return(FALSE);
}

//delete the user
print("User deleted.
\n");
}
}

class AuthorizedUser extends User //認(rèn)證用戶
{
protected function isAuthorized() //覆寫isAuthorized()
{
return(TRUE);
}
}

$user = new User;
$admin = new AuthorizedUser;

//not authorized
$user->deleteUser("Zeev");

//authorized
$admin->deleteUser("Zeev");
?>
為什么private的類成員模擬靜態(tài)綁定? 為了回答這個(gè)問(wèn)題, 你需要回憶一下為什么需要有private成員.什么時(shí)候用它們來(lái)代替protected成員是有意義的?

private成員只有當(dāng)你不想讓子類繼承改變或特殊化父類的行為時(shí)才用到. 這種情況比你想像的要少. 通常來(lái)說(shuō),一個(gè)好的對(duì)象分層結(jié)構(gòu)應(yīng)當(dāng)允許絕大多數(shù)功能被子類特殊化,改進(jìn),或改變—這是面向?qū)ο缶幊痰幕A(chǔ)之一. 一定的情況下需要private方法或變量,例如當(dāng)你確信你不想允許子類改變父類中的某個(gè)特定的部份.


第十節(jié)--抽象方法和抽象類

面向?qū)ο蟪绦蛲ㄟ^(guò)類的分層結(jié)構(gòu)構(gòu)建起來(lái). 在單重繼承語(yǔ)言如PHP中, 類的繼承是樹(shù)狀的. 一個(gè)根類有一個(gè)或更多的子類,再?gòu)拿總€(gè)子類繼承出一個(gè)或更多下一級(jí)子類. 當(dāng)然,可能存在多個(gè)根類,用來(lái)實(shí)現(xiàn)不同的功能. 在一個(gè)良好設(shè)計(jì)的體系中,每個(gè)根類都應(yīng)該有一個(gè)有用的接口, 可以被應(yīng)用代碼所使用. 如果我們的應(yīng)用代碼被設(shè)計(jì)成與根類一起工作,那么它也可以和任何一個(gè)從根類繼承出來(lái)的子類合作.

抽象方法是就像子類中一般的方法的占位符(占個(gè)地方但不起作用),它與一般方法不同—沒(méi)有任何代碼. 如果類中存在一個(gè)或更多抽象方法, 那么這個(gè)類就成了抽象類. 你不能實(shí)例化抽象類. 你必須繼承它們,然后實(shí)例化子類. 你也可以把抽象類看成是子類的一個(gè)模板.

如果你覆寫所有的抽象方法, 子類就變成一個(gè)普通的類. 如果沒(méi)有覆寫所有方法, 子類仍是抽象的. 如果一個(gè)類中中包含有抽象方法(哪怕只有一個(gè)), 你必須聲明這個(gè)類是抽象的, 在class關(guān)鍵字前加上abstract.

聲明抽象方法的語(yǔ)法與聲明一般方法不同. 抽象方法的沒(méi)有像一般方法那樣包含在大括號(hào){}中的主體部份,并用分號(hào);來(lái)結(jié)束.

在例子6.13中, 我們定義了一個(gè)含有g(shù)etArea方法的類Shape. 但由于不知道形狀不可能確定圖形的面積,確良我們聲明了getArea方法為抽象方法. 你不能實(shí)例化一個(gè)Shape對(duì)象,但你可以繼承它或在一個(gè)表達(dá)式中使用它, 就像例6.13中那樣.

如果你建立了一個(gè)只有抽象方法的類,你就定義了一個(gè)接口(interface). 為了說(shuō)明這種情況, PHP中有interface 和implements關(guān)鍵字. 你可以用interface來(lái)代替抽象類, 用implements來(lái)代替extends來(lái)說(shuō)明你的類定義或使用一個(gè)接口. 例如, 你可以寫一個(gè)myClass implements myIterface. 這兩種方法可以依個(gè)人偏愛(ài)來(lái)選擇.

/*注:
兩種方法即指:
1. abstract class aaa{} (注意aaa中只有抽象方法,沒(méi)有一般方法)
class bbb extends aaa{} (在bbb中覆寫aaa中的抽象方法)
2. interface aaa{}
class bbb implements aaa{} (在bbb中覆寫aaa中的抽象方法)
*/

Listing 6.13 Abstract classes
PHP代碼:
//abstract root class 抽象根類
abstract class Shape
{
abstract function getArea(); //定義一個(gè)抽象方法
}

//abstract child class 抽象子類
abstract class Polygon extends Shape //多邊形
{
abstract function getNumberOfSides();
}

//concrete class 實(shí)體類 三角形類
class Triangle extends Polygon
{
public $base;
public $height;

public function getArea() //覆寫計(jì)算面積方法
{
return(($this->base * $this->height)/2);
}

public function getNumberOfSides() //覆寫邊數(shù)統(tǒng)計(jì)方法
{
return(3);
}
}

//concrete class 實(shí)體類四邊形
class Rectangle extends Polygon
{
public $width;
public $height;

public function getArea()
{
return($this->width * $this->height);
}

public function getNumberOfSides()
{
return(4);
}
}

//concrete class 實(shí)體類 圓形
class Circle extends Shape
{
public $radius;

public function getArea()
{
return(pi() * $this->radius * $this->radius);
}
}

//concrete root class 定義一個(gè)顏色類
class Color
{
public $name;
}

$myCollection = array(); //建立形狀的集合,放入數(shù)組

//make a rectangle
$r = new Rectangle;
$r->width = 5;
$r->height = 7;
$myCollection[] = $r;
unset($r);

//make a triangle
$t = new Triangle;
$t->base = 4;
$t->height = 5;
$myCollection[] = $t;
unset($t);

//make a circle
$c = new Circle;
$c->radius = 3;
$myCollection[] = $c;
unset($c);

//make a color
$c = new Color;
$c->name = "blue";
$myCollection[] = $c;
unset($c);

foreach($myCollection as $s)
{
if($s instanceof Shape) //如果$s是Shape類的實(shí)例
{
print("Area: " . $s->getArea() .
"
\n");
}

if($s instanceof Polygon)
{
print("Sides: " .
$s->getNumberOfSides() .
"
\n");
}

if($s instanceof Color)
{
print("Color: $s->name
\n");
}

print("
\n");
}

?>
第十一節(jié)--重載

PHP4中已經(jīng)有了重載的語(yǔ)法來(lái)建立對(duì)于外部對(duì)象模型的映射,就像Java和COM那樣. PHP5帶來(lái)了強(qiáng)大的面向?qū)ο笾剌d,允許程序員建立自定義的行為來(lái)訪問(wèn)屬性和調(diào)用方法.

重載可以通過(guò)__get, __set, and __call幾個(gè)特殊方法來(lái)進(jìn)行. 當(dāng)Zend引擎試圖訪問(wèn)一個(gè)成員并沒(méi)有找到時(shí),PHP將會(huì)調(diào)用這些方法.

在例6.14中,__get和__set代替所有對(duì)屬性變量數(shù)組的訪問(wèn). 如果必要,你可以實(shí)現(xiàn)任何類型你想要的過(guò)濾. 例如,腳本可以禁止設(shè)置屬性值, 在開(kāi)始時(shí)用一定的前綴或包含一定類型的值.

__call方法說(shuō)明了你如何調(diào)用未經(jīng)定義的方法. 你調(diào)用未定義方法時(shí),方法名和方法接收的參數(shù)將會(huì)傳給__call方法, PHP傳遞__call的值返回給未定義的方法.

Listing 6.14 User-level overloading
PHP代碼:
class Overloader
{
private $properties = array();

function __get($property_name)
{
if(isset($this->properties[$property_name]))
{
return($this->properties[$property_name]);
}
else
{
return(NULL);
}
}

function __set($property_name, $value)
{
$this->properties[$property_name] = $value;
}

function __call($function_name, $args)
{
print("Invoking $function_name()
\n");
print("Arguments: ");
print_r($args);

return(TRUE);
}
}
$o = new Overloader();

//invoke __set() 給一個(gè)不存在的屬性變量賦值,激活__set()
$o->dynaProp = "Dynamic Content";

//invoke __get() 激活__get()
print($o->dynaProp . "
\n");

//invoke __call() 激活__call()
$o->dynaMethod("Leon", "Zeev");
?>
第十二節(jié)--類的自動(dòng)加載

當(dāng)你嘗試使用一個(gè)未定義的類時(shí),PHP會(huì)報(bào)告一個(gè)致命錯(cuò)誤. 解決方法就是添加一個(gè)類,可以用include包含一個(gè)文件. 畢竟你知道要用到哪個(gè)類. 但是,PHP提供了類的自動(dòng)加載功能, 這可以節(jié)省編程的時(shí)間. 當(dāng)你嘗試使用一個(gè)PHP沒(méi)有組織到的類, 它會(huì)尋找一個(gè)__autoload的全局函數(shù). 如果存在這個(gè)函數(shù),PHP會(huì)用一個(gè)參數(shù)來(lái)調(diào)用它,參數(shù)即類的名稱.

例子6.15說(shuō)明了__autoload是如何使用的. 它假設(shè)當(dāng)前目錄下每個(gè)文件對(duì)應(yīng)一個(gè)類. 當(dāng)腳本嘗試來(lái)產(chǎn)生一個(gè)類User的實(shí)例,PHP會(huì)執(zhí)行__autoload. 腳本假設(shè)class_User.php中定義有User類.. 不管調(diào)用時(shí)是大寫還是小寫,PHP將返回名稱的小寫.

Listing 6.15 Class autoloading
PHP代碼:
//define autoload function
function __autoload($class)
{
include("class_" . ucfirst($class) . ".php");
}

//use a class that must be autoloaded
$u = new User;
$u->name = "Leon";
$u->printName();
?>
第十三節(jié)--對(duì)象串行化

串行化可以把變量包括對(duì)象,轉(zhuǎn)化成連續(xù)bytes數(shù)據(jù). 你可以將串行化后的變量存在一個(gè)文件里或在網(wǎng)絡(luò)上傳輸. 然后再反串行化還原為原來(lái)的數(shù)據(jù). 你在反串行化類的對(duì)象之前定義的類,PHP可以成功地存儲(chǔ)其對(duì)象的屬性和方法. 有時(shí)你可能需要一個(gè)對(duì)象在反串行化后立即執(zhí)行. 為了這樣的目的,PHP會(huì)自動(dòng)尋找__sleep和__wakeup方法.

當(dāng)一個(gè)對(duì)象被串行化,PHP會(huì)調(diào)用__sleep方法(如果存在的話). 在反串行化一個(gè)對(duì)象后,PHP 會(huì)調(diào)用__wakeup方法. 這兩個(gè)方法都不接受參數(shù). __sleep方法必須返回一個(gè)數(shù)組,包含需要串行化的屬性. PHP會(huì)拋棄其它屬性的值. 如果沒(méi)有__sleep方法,PHP將保存所有屬性.

例子6.16顯示了如何用__sleep和__wakeup方法來(lái)串行化一個(gè)對(duì)象. Id屬性是一個(gè)不打算保留在對(duì)象中的臨時(shí)屬性. __sleep方法保證在串行化的對(duì)象中不包含id屬性. 當(dāng)反串行化一個(gè)User對(duì)象,__wakeup方法建立id屬性的新值. 這個(gè)例子被設(shè)計(jì)成自我保持. 在實(shí)際開(kāi)發(fā)中,你可能發(fā)現(xiàn)包含資源(如圖像或數(shù)據(jù)流)的對(duì)象需要這些方法.

Listing 6.16 Object serialization
PHP代碼:

class User
{
public $name;
public $id;

function __construct()
{
//give user a unique ID 賦予一個(gè)不同的ID
$this->id = uniqid();
}

function __sleep()
{
//do not serialize this->id 不串行化id
return(array("name"));
}

function __wakeup()
{
//give user a unique ID
$this->id = uniqid();
}
}

//create object 建立一個(gè)對(duì)象
$u = new User;
$u->name = "Leon";

//serialize it 串行化 注意不串行化id屬性,id的值被拋棄
$s = serialize($u);

//unserialize it 反串行化 id被重新賦值
$u2 = unserialize($s);

//$u and $u2 have different IDs $u和$u2有不同的ID
print_r($u);
print_r($u2);
?>
第十四節(jié)--命名空間

命名變量,函數(shù)和類是挺困難的,除了要考慮到變量的名稱要易于理解,還要擔(dān)心是否這個(gè)名稱在其它某個(gè)地方已經(jīng)使用過(guò). 在一小段腳本中,第二個(gè)問(wèn)題是基本問(wèn)題. 當(dāng)你考慮重用你的代碼, 在這之后的項(xiàng)目代碼必須避免使用你用過(guò)的命名. 通常來(lái)說(shuō),可重用的代碼總是包含在函數(shù)或類中, 需要處理許多可能發(fā)生的命名沖突. 但函數(shù)和類之間也可能發(fā)生命名沖突. 你可以嘗試避免出現(xiàn)這種情況,通過(guò)在所有類前添加前綴的方法,或者你可以使用namespace語(yǔ)句.

Namespace關(guān)鍵字給一塊代碼命名. 在這個(gè)代碼塊外部,腳本必須用操作符::加上命名空間的名稱來(lái)引用這個(gè)代碼塊. 引用靜態(tài)的類成員也是用相同的方法. 在命名空間內(nèi)代碼不需要聲明命名空間, 它本身就是默認(rèn)的. 這種方法比添加前綴的方法好. 你的代碼可由此變得更加緊湊和可讀.

你可能想知道是否可以建立分層的(嵌套的)命名空間. 答案是不可以. 但你可以在命名空間名稱后加上冒號(hào), 你可以再次調(diào)用在名稱中不包含冒號(hào)的變量,函數(shù)和類. 命名空間允許存在冒號(hào),只要不是第一個(gè)字符和最后一個(gè)字符或接著另一個(gè)冒號(hào). 命名空間的名稱中的冒號(hào)對(duì)于PHP來(lái)說(shuō)沒(méi)有任何意義, 但如果你用他們來(lái)區(qū)分邏輯上的區(qū)塊, 他們可以很好地說(shuō)明你的代碼中的父子(parent-child)關(guān)系.


/* 注: 即可以使用這樣:
namespace animal:dog {}
namespace animalig {}

用冒號(hào)來(lái)說(shuō)明parent-child關(guān)系.
*/


你可能在一個(gè)命名空間語(yǔ)句內(nèi)沒(méi)有包含函數(shù),類或常量定義以外的任何東西. 這將阻止你使用他們來(lái)改進(jìn)舊的使用全局變量的函數(shù)庫(kù). 命名空間最適合于面向?qū)ο? 命名空間內(nèi)的常量與類中的常量使用相同的語(yǔ)法.

例子6.17顯示了如何使用命名空間.

Listing 6.17 Using a namespace
PHP代碼:
namespace core_php:utility
{
class textEngine
{
public function uppercase($text) //大寫
{
return(strtoupper($text));
}
}

//make non-OO interface 建立一個(gè)非OO的接口
function uppercase($text)
{
$e = new textEngine;
return($e->uppercase($text));
}

}

//test class in namespace 測(cè)試命名空間中的類
$e = new core_php:utility::textEngine;
print($e->uppercase("from object") . "
");

//test function in namespace 測(cè)試命名空間中的函數(shù)
print(core_php:utility::uppercase("from function") . "
");

//bring class into global namespace 把類導(dǎo)入全局命名空間
import class textEngine from core_php:utility;
$e2 = new textEngine;
?>
Import語(yǔ)句把命名空間中的某個(gè)部份導(dǎo)入全局的命名空間.
要導(dǎo)入單一的命名空間的成員,可以指定類型為constant,function或class,接著寫上成員的名稱;
//如import class XXX
如果你想導(dǎo)入某一特定類型的所有成員,你可以用*來(lái)代替名稱;
//如 import constant * 導(dǎo)入所有常量
如果你想導(dǎo)入所有類型的所有成員,用*即可.
//如 import *

在成員之后,用from關(guān)鍵字加上命名空間的名稱.
//如 import class textEngine from core_php:utility;

總之你要寫成像import * from myNamespace或 import class textEngine from core_php:utility這樣的語(yǔ)句,就像例6.17中那樣.

第十五節(jié)--Zend引擎的發(fā)展

本章的最后一節(jié),Zeev討論了Zend引擎帶來(lái)的對(duì)象模型,特別提到它與PHP的前幾個(gè)版本中的模型有什么不同.
當(dāng)1997年夏天,我們開(kāi)發(fā)出PHP3, 我們沒(méi)有計(jì)劃要使PHP具備面向?qū)ο蟮哪芰? 當(dāng)時(shí)沒(méi)有任何與類和對(duì)象有關(guān)的想法. PHP3是一個(gè)純粹面向過(guò)程的語(yǔ)言. 但是,在1997.8.27的晚上PHP3 alpha版中增加了對(duì)類的支持. 增加一個(gè)新特性給PHP,當(dāng)時(shí)僅需要極少的討論,因?yàn)楫?dāng)時(shí)探索PHP的人太少. 于是從1997年八月起, PHP邁出了走向面向?qū)ο缶幊陶Z(yǔ)言的第一步.

確實(shí),這只是第一步. 因?yàn)樵谶@個(gè)設(shè)計(jì)中只有極少的相關(guān)的想法,對(duì)于對(duì)象的支持不夠強(qiáng)大. 這個(gè)版本中使用對(duì)象僅是訪問(wèn)數(shù)組的一個(gè)很酷的方法而已. 取代使用$foo[“bar”],你可以使用看起來(lái)更漂亮的$foo->bar. 面向?qū)ο蠓椒ǖ闹饕膬?yōu)勢(shì)是通過(guò)成員函數(shù)或方法來(lái)儲(chǔ)存功能. 例子6.18中顯示了一個(gè)典型的代碼塊. 但是它和例6.19中的做法其實(shí)并沒(méi)有太大不同.

Listing 6.18 PHP 3 object-oriented programming PHP3中的面向?qū)ο缶幊?br>PHP代碼:
class Example
{
var $value = "some value";
function PrintValue()
{
print $this->value;
}
}
$obj = new Example();
$obj->PrintValue();
?>
Listing 6.19 PHP 3 structural programming PHP3 PHP3中的結(jié)構(gòu)化編程
PHP代碼:
function PrintValue($arr)
{
print $arr["value"];
}

function CreateExample()
{
$arr["value"] = "some value";
$arr["PrintValue"] = "PrintValue";

return $arr;
}

$arr = CreateExample();

//Use PHP's indirect reference
$arr["PrintValue"]($arr);
?>
以上我們?cè)陬愔袑懮蟽尚写a,或者顯示地傳遞數(shù)組給函數(shù). 但考慮到PHP3中這兩種選擇并沒(méi)有任何不同,我們?nèi)匀豢梢詢H把對(duì)象模型當(dāng)成一種”語(yǔ)法上的粉飾”來(lái)訪問(wèn)數(shù)組.

想要用PHP來(lái)進(jìn)行面向?qū)ο箝_(kāi)發(fā)的人們,特別是想使用設(shè)計(jì)模式的人,很快就發(fā)現(xiàn)他們碰壁了. 幸運(yùn)地,當(dāng)時(shí)(PHP3時(shí)代)沒(méi)有太多人想用PHP來(lái)進(jìn)行面向?qū)ο箝_(kāi)發(fā).

PHP4改變了這種情況. 新的版本帶來(lái)了引用(reference)的概念, 它允許PHP的不同標(biāo)識(shí)符指向內(nèi)存中的同一個(gè)地址. 這意味著你可以使用兩個(gè)或更多的名稱來(lái)給同一個(gè)變量命名,就像例6.20那樣.

Listing 6.20 PHP 4 references PHP4中的引用
PHP代碼:
$a = 5;

//$b points to the same place in memory as $a $b與$a指向內(nèi)存中同個(gè)地址
$b = &$a;

//we're changing $b, since $a is pointing to 改變$b,指向的地址改變
//the same place - it changes too $a指向的地址也改變
$b = 7;

//prints 7 輸出7
print $a;
?>
由于構(gòu)建一個(gè)指向彼此的對(duì)象網(wǎng)絡(luò)是所有面向?qū)ο笤O(shè)計(jì)模式的基礎(chǔ),這個(gè)改進(jìn)具有非常重大的意義.當(dāng)引用允許建立更多強(qiáng)大的面向?qū)ο髴?yīng)用程序, PHP對(duì)待對(duì)象和其它類型數(shù)據(jù)相同的做法帶給開(kāi)發(fā)者極大的痛苦.就像任何PHP4的程序員將會(huì)告訴你的, 應(yīng)用程序?qū)?huì)遭遇WTMA(Way Too Many Ampersands過(guò)多&)綜合癥. 如果你想構(gòu)建一個(gè)實(shí)際應(yīng)用,你會(huì)感到極為痛苦,看看例6.21你就明白.

Listing 6.21 Problems with objects in PHP 4 PHP4中使用對(duì)象的問(wèn)題

1 class MyFoo {
2 function MyFoo()
3 {
4 $this->me = &$this;
5 $this->value = 5;
6 }
7
8 function setValue($val)
9 {
10 $this->value = $val;
11 }
12
13 function getValue()
14 {
15 return $this->value;
16 }
17
18 function getValueFromMe()
19 {
20 return $this->me->value;
21 }
22 }
23
24 function CreateObject($class_type)
25 {
26 switch ($class_type) {
27 case "foo":
28 $obj = new MyFoo();
29 break;
30 case "bar":
31 $obj = new MyBar();
32 break;
33 }
34 return $obj;
35 }
36
37 $global_obj = CreateObject ("foo");
38 $global_obj->setValue(7);
39
40 print "Value is " . $global_obj->getValue() . "\n";
41 print "Value is " . $global_obj->getValueFromMe() . "\n";





讓我們一步步來(lái)討論. 首先,有一個(gè)MyFoo類.在構(gòu)造函數(shù)里,我們給$this->me一個(gè)引用,并設(shè)定
我們有其它三個(gè)成員函數(shù): 一個(gè)設(shè)定this->value的值;一個(gè)返回this->value的值;另一個(gè)返回this->value->me的值. 但是--$this不是相同的東西嗎? MyFoo::getValue()和MyFoo::getValueFromMe()返回的值不是一樣的嗎?

首先,我們調(diào)用CreateObject("foo"),這會(huì)返回一個(gè)MyFoo類型的對(duì)象. 然后我們調(diào)用MyFoo::setValue(7). 最后,我們調(diào)用MyFoo::getValue() 和MyFoo::getValueFromMe(), 期望得到返回值7.
當(dāng)然,如果我們?cè)谌魏吻闆r下都得到7, 以上這個(gè)例子將不是本書中最沒(méi)有意義的例子. 所以我相信你已經(jīng)猜到—我們得不到兩個(gè)7這樣的結(jié)果.

但是我們將得到什么結(jié)果,并且更重要地,為什么呢?

我們將得到的結(jié)果分別是7和5. 至于為什么—--有三個(gè)很好的理由.

首先,看構(gòu)造函數(shù). 當(dāng)在構(gòu)造函數(shù)內(nèi)部,我們?cè)趖his和this->me間建立引用. 換句話說(shuō),this和this->me是同個(gè)東西. 但是我們是在構(gòu)造函數(shù)內(nèi). 當(dāng)構(gòu)造函數(shù)結(jié)束,PHP要重新建立對(duì)象(new MyFoo的結(jié)果,第28行)分配給$obj. 因?yàn)閷?duì)象沒(méi)有特殊化對(duì)待,就像其它任何數(shù)據(jù)類型一樣,賦值X給Y意味著Y是X的一個(gè)副本. 也就是說(shuō),obj將是new MyFoo的一個(gè)副本,而new MyFoo是一個(gè)存在于構(gòu)造函數(shù)的對(duì)象. Obj->me怎么樣呢? 因?yàn)樗且粋€(gè)引用,它原封不動(dòng)仍然指向原來(lái)的對(duì)象—this. Voila-obj和obj->me不再是同個(gè)東西了—改變其中一個(gè)另一個(gè)不變.

以上是第一條理由. 還有其它類似于第一條的理由. 奇跡般地我們打算克服實(shí)例化對(duì)象這個(gè)問(wèn)題(第28行). 一旦我們把CreateObject返回的值賦給global_object,我們?nèi)匀灰采舷嗤膯?wèn)題—global_object將變成返回值的一個(gè)副本,并且再次地,global_object和global_object->me將不再相同. 這就是第二條理由.

但是,事實(shí)上我們還走不了那么遠(yuǎn)— 一旦CreateObject返回$obj,我們將破壞引用(第34行) . 這就是第三條理由.

那么,我們?nèi)绾胃恼@些? 有兩個(gè)選擇. 一是在所有地方增加&符號(hào),就像例6.22那樣(第24, 28, 31, 37行). 二.如果你幸運(yùn)地使用上了PHP5,你可以忘了以上這一切,PHP5會(huì)自動(dòng)為你考慮這些. 如果你想知道PHP5是如何考慮這些問(wèn)題的,繼續(xù)閱讀下去.

Listing 6.22 WTMA syndrome in PHP 4 PHP4中的WTMA綜合癥

1 class MyFoo {
2 function MyFoo()
3 {
4 $this->me = &$this;
5 $this->value = 2;
6 }
7
8 function setValue($val)
9 {
10 $this->value = $val;
11 }
12
13 function getValue()
14 {
15 return $this->value;
16 }
17
18 function getValueFromMe()
19 {
20 return $this->me->value;
21 }
22 };
23
24 function &CreateObject($class_type)
25 {
26 switch ($class_type) {
27 case "foo":
28 $obj =& new MyFoo();
29 break;
30 case "bar":
31 $obj =& new MyBar();
32 break;
33 }
34 return $obj;
35 }
36
37 $global_obj =& CreateObject ("foo");
38 $global_obj->setValue(7);
39
40 print "Value is " . $global_obj->getValue() . "\n";
41 print "Value is " . $global_obj->getValueFromMe() . "\n";




PHP5是第一個(gè)把對(duì)象看成與其它類型數(shù)據(jù)不同的PHP版本. 從用戶的角度看,這證明它非常明白的方式—在PHP5中,對(duì)象總是通過(guò)引用來(lái)傳遞,而其它類型數(shù)據(jù)(如integer,string,array)都是通過(guò)值來(lái)傳遞. 最顯著地,沒(méi)有必要再用&符號(hào)來(lái)表示通過(guò)引用來(lái)傳遞對(duì)象了.

面向?qū)ο缶幊虖V泛利用了對(duì)象網(wǎng)絡(luò)和對(duì)象間的復(fù)雜關(guān)系,這些都需要用到引用. 在PHP的前些版本中,需要顯示地指明引用. 因此, 現(xiàn)在默認(rèn)用引用來(lái)移動(dòng)對(duì)象,并且只有在明確要求復(fù)制時(shí)才復(fù)制對(duì)象,這樣比以前更好.

它是如何實(shí)現(xiàn)的呢?

在PHP5之前,所有值都存在一個(gè)名為zval(Zend Value)的特殊結(jié)構(gòu)里. 這些值可以存入簡(jiǎn)單的值,如數(shù)字和字符串,或復(fù)雜的值如數(shù)組和對(duì)象. 當(dāng)值傳給函數(shù)或從函數(shù)返回時(shí),這些值會(huì)被復(fù)制,在內(nèi)存的另一個(gè)地址建立一個(gè)帶有相同內(nèi)容的結(jié)構(gòu).

在PHP5中,值仍存為zval結(jié)構(gòu)中,但對(duì)象除外. 對(duì)象存在一個(gè)叫做Object Store的結(jié)構(gòu)里,并且每個(gè)對(duì)象有一個(gè)不同的ID. Zval中,不儲(chǔ)存對(duì)象本身,而是存著對(duì)象的指針. 當(dāng)復(fù)制一個(gè)持有對(duì)象的zval結(jié)構(gòu),例如我們把一個(gè)對(duì)象當(dāng)成參數(shù)傳給某個(gè)函數(shù),我們不再?gòu)?fù)制任何數(shù)據(jù). 我們僅僅保持相同的對(duì)象指針并由另一個(gè)zval通知現(xiàn)在這個(gè)特定的對(duì)象指向的Object Store. 因?yàn)閷?duì)象本身位于Object Store,我們對(duì)它所作的任何改變將影響到所有持有該對(duì)象指針的zval結(jié)構(gòu).這種附加的間接作用使PHP對(duì)象看起來(lái)就像總是通過(guò)引用來(lái)傳遞,用透明和有效率的方式.

使用PHP5,我們現(xiàn)在可以回到示例6.21,除去所有的&符號(hào), 一切代碼都仍然可以正常工作.當(dāng)我們?cè)跇?gòu)造函數(shù)(第4行)中持有一個(gè)引用時(shí)一個(gè)&符號(hào)都不用.



Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undress AI Tool

Undress AI Tool

Undress images for free

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Hot Topics

PHP Tutorial
1488
72
PHP calls AI intelligent voice assistant PHP voice interaction system construction PHP calls AI intelligent voice assistant PHP voice interaction system construction Jul 25, 2025 pm 08:45 PM

User voice input is captured and sent to the PHP backend through the MediaRecorder API of the front-end JavaScript; 2. PHP saves the audio as a temporary file and calls STTAPI (such as Google or Baidu voice recognition) to convert it into text; 3. PHP sends the text to an AI service (such as OpenAIGPT) to obtain intelligent reply; 4. PHP then calls TTSAPI (such as Baidu or Google voice synthesis) to convert the reply to a voice file; 5. PHP streams the voice file back to the front-end to play, completing interaction. The entire process is dominated by PHP to ensure seamless connection between all links.

How to use PHP to build social sharing functions PHP sharing interface integration practice How to use PHP to build social sharing functions PHP sharing interface integration practice Jul 25, 2025 pm 08:51 PM

The core method of building social sharing functions in PHP is to dynamically generate sharing links that meet the requirements of each platform. 1. First get the current page or specified URL and article information; 2. Use urlencode to encode the parameters; 3. Splice and generate sharing links according to the protocols of each platform; 4. Display links on the front end for users to click and share; 5. Dynamically generate OG tags on the page to optimize sharing content display; 6. Be sure to escape user input to prevent XSS attacks. This method does not require complex authentication, has low maintenance costs, and is suitable for most content sharing needs.

How to use PHP combined with AI to achieve text error correction PHP syntax detection and optimization How to use PHP combined with AI to achieve text error correction PHP syntax detection and optimization Jul 25, 2025 pm 08:57 PM

To realize text error correction and syntax optimization with AI, you need to follow the following steps: 1. Select a suitable AI model or API, such as Baidu, Tencent API or open source NLP library; 2. Call the API through PHP's curl or Guzzle and process the return results; 3. Display error correction information in the application and allow users to choose whether to adopt it; 4. Use php-l and PHP_CodeSniffer for syntax detection and code optimization; 5. Continuously collect feedback and update the model or rules to improve the effect. When choosing AIAPI, focus on evaluating accuracy, response speed, price and support for PHP. Code optimization should follow PSR specifications, use cache reasonably, avoid circular queries, review code regularly, and use X

PHP creates a blog comment system to monetize PHP comment review and anti-brush strategy PHP creates a blog comment system to monetize PHP comment review and anti-brush strategy Jul 25, 2025 pm 08:27 PM

1. Maximizing the commercial value of the comment system requires combining native advertising precise delivery, user paid value-added services (such as uploading pictures, top-up comments), influence incentive mechanism based on comment quality, and compliance anonymous data insight monetization; 2. The audit strategy should adopt a combination of pre-audit dynamic keyword filtering and user reporting mechanisms, supplemented by comment quality rating to achieve content hierarchical exposure; 3. Anti-brushing requires the construction of multi-layer defense: reCAPTCHAv3 sensorless verification, Honeypot honeypot field recognition robot, IP and timestamp frequency limit prevents watering, and content pattern recognition marks suspicious comments, and continuously iterate to deal with attacks.

How to use PHP to combine AI to generate image. PHP automatically generates art works How to use PHP to combine AI to generate image. PHP automatically generates art works Jul 25, 2025 pm 07:21 PM

PHP does not directly perform AI image processing, but integrates through APIs, because it is good at web development rather than computing-intensive tasks. API integration can achieve professional division of labor, reduce costs, and improve efficiency; 2. Integrating key technologies include using Guzzle or cURL to send HTTP requests, JSON data encoding and decoding, API key security authentication, asynchronous queue processing time-consuming tasks, robust error handling and retry mechanism, image storage and display; 3. Common challenges include API cost out of control, uncontrollable generation results, poor user experience, security risks and difficult data management. The response strategies are setting user quotas and caches, providing propt guidance and multi-picture selection, asynchronous notifications and progress prompts, key environment variable storage and content audit, and cloud storage.

PHP realizes commodity inventory management and monetization PHP inventory synchronization and alarm mechanism PHP realizes commodity inventory management and monetization PHP inventory synchronization and alarm mechanism Jul 25, 2025 pm 08:30 PM

PHP ensures inventory deduction atomicity through database transactions and FORUPDATE row locks to prevent high concurrent overselling; 2. Multi-platform inventory consistency depends on centralized management and event-driven synchronization, combining API/Webhook notifications and message queues to ensure reliable data transmission; 3. The alarm mechanism should set low inventory, zero/negative inventory, unsalable sales, replenishment cycles and abnormal fluctuations strategies in different scenarios, and select DingTalk, SMS or Email Responsible Persons according to the urgency, and the alarm information must be complete and clear to achieve business adaptation and rapid response.

Beyond the LAMP Stack: PHP's Role in Modern Enterprise Architecture Beyond the LAMP Stack: PHP's Role in Modern Enterprise Architecture Jul 27, 2025 am 04:31 AM

PHPisstillrelevantinmodernenterpriseenvironments.1.ModernPHP(7.xand8.x)offersperformancegains,stricttyping,JITcompilation,andmodernsyntax,makingitsuitableforlarge-scaleapplications.2.PHPintegrateseffectivelyinhybridarchitectures,servingasanAPIgateway

PHP integrated AI speech recognition and translator PHP meeting record automatic generation solution PHP integrated AI speech recognition and translator PHP meeting record automatic generation solution Jul 25, 2025 pm 07:06 PM

Select the appropriate AI voice recognition service and integrate PHPSDK; 2. Use PHP to call ffmpeg to convert recordings into API-required formats (such as wav); 3. Upload files to cloud storage and call API asynchronous recognition; 4. Analyze JSON results and organize text using NLP technology; 5. Generate Word or Markdown documents to complete the automation of meeting records. The entire process needs to ensure data encryption, access control and compliance to ensure privacy and security.

See all articles