php機制
❶ php中如何實現Hook機制
給你推薦2個方法
類的__call 和__callstatic 。 這2個魔術方法是當調用類的內部方法不存在時執行。__call是實例化類之後調用方法不存在。__callstatic 是調用靜態方法不存在,它裡面的參數包含了方法名和傳遞的參數。這樣就可以利用這2個方法去實現hook機制。根據方法名和參數去找指定位置的文件和方法執行。use_call_func和use_call_func_array 具體看文檔
是反射機制。php已經很早就有反射機制了。利用類的反射機制。去實現hook。其實原理和1方法差不多。但是實現的方法比較高級而已。
❷ PHP運行機制
簡介
我們從未手動開啟過PHP的相關進程,它是隨著Apache的啟動而運行的;PHP通過mod_php5.so模塊和Apache相連(具體說來是SAPI,即伺服器應用程序編程介面);
PHP總共有三個模塊:內核、Zend引擎、以及擴展層; PHP內核用來處理請求、文件流、錯誤處理等相關操作; Zend引擎(ZE)用以將源文件轉換成機器語言,然後在虛擬機上運行它; 擴展層是一組函數、類庫和流,PHP使用它們來執行一些特定的操作。比如,我們需要mysql擴展來連接MySQL資料庫; 當ZE執行程序時可能會需要連接若干擴展,這時ZE將控制權交給擴展,等處理完特定任務後再返還;
最後,ZE將程序運行結果返回給PHP內核,它再將結果傳送給SAPI層,最終輸出到瀏覽器上。
深入探討
真是的內部運行過程沒有這么簡單。以上過程只是個簡略版,讓我們再深入挖掘一下,看看幕後還發生了些什麼。
◆Apache啟動後,PHP解釋程序也隨之啟動;
◆PHP的啟動過程有兩步:
第一步是初始化一些環境變數,這將在整個SAPI生命周期中發生作用;
第二步是生成只針對當前請求的一些變數設置。
PHP啟動第一步
不清楚什麼第一第二步是什麼?別擔心,我們接下來詳細討論一下。讓我們先看看第一步,也是最主要的一步。要記住的是,第一步的操作在任何請求到達之前就發生了。
啟動Apache後,PHP解釋程序也隨之啟動;
PHP調用各個擴展的MINIT方法,從而使這些擴展切換到可用狀態。看看php.ini文件里打開了哪些擴展吧; MINIT的意思是「模塊初始化」。各個模塊都定義了一組函數、類庫等用以處理其他請求。
一個典型的MINIT方法如下:
PHP_MINIT_FUNCTION(extension_name){
/* Initialize functions, classes etc */
}
PHP啟動第二步
當一個頁面請求發生時,SAPI層將控制權交給PHP層。於是PHP設置了用於回復本次請求所需的環境變數。同時,它還建立一個變數表,用來存放執行過程中產生的變數名和值。
PHP調用各個模塊的RINIT方法,即「請求初始化」。一個經典的例子是Session模塊的RINIT,如果在php.ini中啟用了Session模塊,那在調用該模塊的RINIT時就會初始化$_SESSION變數,並將相關內容讀入;
RINIT方法可以看作是一個准備過程,在程序執行之間就會自動啟動。
一個典型的RINIT方法如下:
PHP_RINIT_FUNCTION(extension_name) {
/* Initialize session variables,
pre-populate variables,
redefine global variables etc */
}
PHP關閉第一步
如同PHP啟動一樣,PHP的關閉也分兩步:
一旦頁面執行完畢(無論是執行到了文件末尾還是用exit或die函數中止),PHP就會啟動清理程序。它會按順序調用各個模塊的RSHUTDOWN方法。
RSHUTDOWN用以清除程序運行時產生的符號表,也就是對每個變數調用unset函數。
一個典型的RSHUTDOWN方法如下:
PHP_RSHUTDOWN_FUNCTION(extension_name) {
/* Do memory management,
unset all variables used in the last PHP call etc */
}
PHP關閉第二步
最後,所有的請求都已處理完畢,SAPI也准備關閉了,PHP開始執行第二步:
PHP調用每個擴展的MSHUTDOWN方法,這是各個模塊最後一次釋放內存的機會。
一個典型的RSHUTDOWN方法如下:
PHP_MSHUTDOWN_FUNCTION(extension_name) {
/* Free handlers and persistent memory etc */
}
這樣,整個PHP生命周期就結束了。要注意的是,只有在伺服器沒有請求的情況下才會執行「啟動第一步」和「關閉第二步」。
❸ php 運行機制
請看PHP手冊18章,裡面的內容你看了就明白。
第 18 章 類與對象(PHP 4)
目錄
類
繼承
構造函數
范圍解析操作符(::)
parent
序列化對象 - 會話中的對象
魔術函數 __sleep 和 __wakeup
構造函數中的引用
對象的比較
類
類是變數與作用於這些變數的函數的集合。使用下面的語法定義一個類:
<?php
class Cart {
var $items; // 購物車中的物品
// 將 $num 個 $artnr 物品加入購物車
function add_item($artnr, $num) {
$this->items[$artnr] += $num;
}
// 將 $num 個 $artnr 物品從購物車中取出
function remove_item($artnr, $num) {
if ($this->items[$artnr] > $num) {
$this->items[$artnr] -= $num;
return true;
} elseif ($this->items[$artnr] == $num) {
unset($this->items[$artnr]);
return true;
} else {
return false;
}
}
}
?>
上面的例子定義了一個 Cart 類,這個類由購物車中的商品構成的數組和兩個用於從購物車中添加和刪除商品的函數組成。
警告
不能將一個類的定義分割到多個文件中。也不能將一個類的定義分割到多個 PHP 塊中,除非該分割是在一個方法聲明內部。以下用法將不起作用:
<?php
class test {
?>
<?php
function test() {
print 'OK';
}
}
?>
但是以下用法是可以的:
<?php
class test {
function test() {
?>
<?php
print 'OK';
}
}
?>
以下警告僅用於 PHP 4。
小心
名稱 stdClass 已經被 Zend 使用並保留。不能在 PHP 代碼中定義名為 stdClass 的類。
小心
函數名 __sleep 和 __wakeup 在 PHP 類中是魔術函數。除非想要與之聯系的魔術功能,否則在任何類中都不能以此命名函數。
小心
PHP 將所有以 __ 開頭的函數名保留為魔術函數。除非想要使用一些見於文檔中的魔術功能,否則建議不要在 PHP 中將函數名以 __ 開頭。
在 PHP 4 中,var 變數的值只能初始化為常量。用非常量值初始化變數,需要一個初始化函數,該函數在對象被創建時自動被調用。這樣一個函數被稱之為構造函數(見下面)。
<?php
/* PHP 4 中不能這樣用 */
class Cart {
var $todays_date = date("Y-m-d");
var $name = $firstname;
var $owner = 'Fred ' . 'Jones';
/* 不過包含有常量的數組可以 */
var $items = array("VCR", "TV");
}
/* 應該這樣進行 */
class Cart {
var $todays_date;
var $name;
var $owner;
var $items = array("VCR", "TV");
function Cart() {
$this->todays_date = date("Y-m-d");
$this->name = $GLOBALS['firstname'];
/* etc. . . */
}
}
?>
類也是一種類型,就是說,它們是實際變數的藍圖。必須用 new 運算符來創建相應類型的變數。
<?php
$cart = new Cart;
$cart->add_item("10", 1);
$another_cart = new Cart;
$another_cart->add_item("0815", 3);
?>
上述代碼創建了兩個 Cart 類的對象 $cart 和 $another_cart,對象 $cart 的方法 add_item() 被調用時,添加了 1 件 10 號商品。對於對象 $another_cart,3 件 0815 號商品被添加到購物車中。
$cart 和 $another_cart 都有方法 add_item(),remove_item() 和一個 items 變數。它們都是明顯的函數和變數。可以把它們當作文件系統中的某些類似目錄的東西來考慮。在文件系統中,可以擁有兩個不同的 README.TXT 文件,只要不在相同的目錄中。正如從為了根目錄訪問每個文件需要輸入該文件的完整的路徑名一樣,必須指定需要調用的函數的完整名稱:在 PHP 術語中,根目錄將是全局名字空間,路徑名符號將是 ->。因而,名稱 $cart->items 和 $another_cart->items 命名了兩個不同的變數。注意變數名為 $cart->items,不是 $cart->$items,那是因為在 PHP 中一個變數名只有一個單獨的美元符號。
<?php
// 正確,只有一個 $
$cart->items = array("10" => 1);
// 不正確,因為 $cart->$items 變成了 $cart->""
$cart->$items = array("10" => 1);
// 正確,但可能不是想要的結果:
// $cart->$myvar 變成了 $cart->items
$myvar = 'items';
$cart->$myvar = array("10" => 1);
?>
在定義類的時候,無法得知將使什麼名字的對象來訪問:在編寫 Cart 類時,並不知道之後對象的名稱將會命名為 $cart 或者 $another_cart。因而你不能在類中使用 $cart->items。然而為了類定義的內部訪問自身的函數和變數,可以使用偽變數 $this 來達到這個目的。$this 變數可以理解為「我自己的」或者「當前對象」。因而 '$this->items[$artnr] += $num' 可以理解為「我自己的物品數組的 $artnr 計數器加 $num」或者「在當前對象的物品數組的 $artnr 計數器加 $num」。
注意: 偽變數 $this 通常未定義,如果其所在的方法是被靜態調用的話。但這不是個嚴格規定:如果一個方法被從另一個對象內靜態調用的話,則 $this 會被定義。此時 $this 的值是那個發出調用的對象。用下例演示:
<?php
class A
{
function foo()
{
if (isset($this)) {
echo '$this is defined (';
echo get_class($this);
echo ")\n";
} else {
echo "\$this is not defined.\n";
}
}
}
class B
{
function bar()
{
A::foo();
}
}
$a = new A();
$a->foo();
A::foo();
$b = new B();
$b->bar();
B::bar();
?>
上例將輸出:
$this is defined (a)
$this is not defined.
$this is defined (b)
$this is not defined.
注意: 有一些不錯的函數用來處理類和對象。應該關注一下類/對象函數。
❹ php怎麼構建vip機制,key
嗯。數據表裡加一個表示 vip的欄位,然後在你想差異化的地方加if(vip)然後寫邏輯 寫頁面 寫功能嘍。
❺ 簡單說明PHP的垃圾收集機制是怎樣的
PHP的基本GC概念
PHP語言同其他語言一樣,具有垃圾回收機制。那麼今天我們要為大家講解的內容就是關於PHP垃圾回收機制的相關問題。希望對大家有所幫助。PHP
strtotime應用經驗之談PHP memory_get_usage()管理內存PHP unset全局變數運用問題詳解PHP
unset()函數銷毀變數教你快速實現PHP全站許可權驗證一、PHP 垃圾回收機制(Garbage Collector 簡稱GC)
在PHP中,沒有任何變數指向這個對象時,這個對象就成為垃圾。PHP會將其在內存中銷毀;這是PHP的GC垃圾處理機制,防止內存溢出。當一個PHP線程結束時,當前佔用的所有內存空間都會被銷毀,當前程序中所有對象同時被銷毀。GC進程一般都跟著每起一個SESSION而開始運行的.gc目的是為了在session文件過期以後自動銷毀刪除這些文件.二、__destruct
/unset __destruct() 析構函數,是在垃圾對象被回收時執行。
unset 銷毀的是指向對象的變數,而不是這個對象。三、 Session
與PHP垃圾回收機制由於PHP的工作機制,它並沒有一個daemon線程來定期的掃描Session信息並判斷其是否失效,當一個有效的請求發生時,PHP
會根據全局變數 session.gc_probability和session.gc_divisor的值,來決定是否啟用一個GC,
在默認情況下,session.gc_probability=1, session.gc_divisor
=100也就是說有1%的可能性啟動GC(也就是說100個請求中只有一個gc會伴隨100個中的某個請求而啟動).PHP垃圾回收機制的工作就是掃描所有的Session信息,用當前時間減去session最後修改的時間,同session.gc_maxlifetime參數進行比較,如果生存時間超過gc_maxlifetime(默認24分鍾),就將該session刪除。
但是,如果你Web伺服器有多個站點,多個站點時,GC處理session可能會出現意想不到的結果,原因就是:GC在工作時,並不會區分不同站點的session.那麼這個時候怎麼解決呢?
1. 修改session.save_path,或使用session_save_path()讓每個站點的session保存到一個專用目錄,
2. 提供GC的啟動率,自然,PHP垃圾回收機制的啟動率提高,系統的性能也會相應減低,不推薦。
3. 在代碼中判斷當前session的生存時間,利用session_destroy()刪除。
引用計數基本知識
每個php變數存在一個叫做"zval"的變數容器中.一個zval變數容器,除了包含變數的類型和值,還包括兩個位元組的額外信息.第一個是"is_ref",是個bool值,用來標識這個變數是否是屬於引用集合(reference
set).通過這個位元組,php引擎才能把普通變數和引用變數區分開.由於php允許用戶通過使用&來使用自定義引用,zval變數容器中還有一個內部引用計數機制,來優化內存使用.第二個額外位元組是"refcount",用來表示指向這個zval變數容器的變數(也稱符號即symbol)個數.
當一個變數被賦常量值時,就會生成一個zval變數容器,如下例所示:
?
1
2
3
4
<?php
$a = "new string";
?>
在上例中,新的變數是a,是在當前作用域中生成的.並且生成了類型為string和值為"new
string"的變數容器.在額外的兩個位元組信息中,"is_ref"被默認設置為false,因為沒有任何自定義的引用生成."refcount"被設定為1,因為這里只有一個變數使用這個變數容器.調用xdebug查看一下變數內容:
?
1
2
3
4
5
<?php
$a = "new string";
xdebug_debug_zval('a');
?>
以上代碼會輸出:
?
1
a: (refcount=1, is_ref=0)='new string'
對變數a增加一個引用計數
?
1
2
3
4
5
6
<?php
$a = "new string";
$b = $a;
xdebug_debug_zval('a');
?>
以上代碼會輸出:
?
1
a: (refcount=2, is_ref=0)='new string'
這時,引用次數是2,因為同一變數容器被變數a和變數b關聯.當沒必要時,php不會去復制已生成的變數容器.變數容器在"refcount"變成0時就被銷毀.當任何關聯到某個變數容易的變數離開它的作用域(比如:函數執行結束),或者對變數調用了unset()函數,"refcount"就會減1,下面例子就能說明:
?
1
2
3
4
5
6
7
<?php
$a = "new string";
$b = $c = $a;
xdebug_debug_zval('a');
unset($b, $c);
xdebug_debug_zval('a');
?>
以上代碼會輸出:
?
1
a: (refcount=3, is_ref=0)='new string' a: (refcount=1, is_ref=0)='new string'
如果我們現在執行unset($a),$包含的類型和值的這個容器就會從內存刪除
復合類型(compound types)
當考慮像array和object這樣的復合類型時,事情會稍微有些復雜.與標量(scalar)類型的值不同,array和object類型的變數把它們的成員或屬性存在自己的符號表中.這意味著下面的例子將生成三個zval變數容器
?
1
2
3
4
5
<?php
$a = array('meaning' => 'life', 'number' => 42);
xdebug_debug_zval('a');
?>
以上代碼輸出:
?
1
a: (refcount=1, is_ref=0)=array ('meaning' => (refcount=1, is_ref=0)='life', 'number' => (refcount=1, is_ref=0)=42)
這三個zval變數容器是:a,meaning,number.增加和減少refcount的規則和上面提到的一樣
特例,添加數組本身作為數組元素時:
?
1
2
3
4
5
6
7
<?php
$a = array('one');
$a[] = &$a;
xdebug_debug_zval('a');
?>
以上代碼輸出的結果:
?
1
a: (refcount=2, is_ref=1)=array (0 => (refcount=1, is_ref=0)='one', 1 => (refcount=2, is_ref=1)=...)
可以看到數組a和數組本身元素a[1]指向的變數容器refcount為2
當對數組$a調用unset函數時,$a的refcount變為1,發生了內存泄漏
清理變數容器的問題
盡管不再有某個作用域中的任何符號指向這個結構(就是變數容器),由於數組元素"1"仍然指向數組本身,所以這個容器不能被消除.因為沒有另外的符號指向它,用戶沒有辦法清除這個結構,結果就會導致內存泄漏.慶幸的是,php將在請求結束時清除這個數據結構,但是php清除前,將耗費不少內存空間
回收周期
5.3.0PHP使用了新的同步周期回收演算法,來處理上面所說的內存泄漏問題
首先,我們先要建立一些基本規則:
如果一個引用計數增加,它將繼續被使用,當然就不再垃圾中.如果引用技術減少到零,所在的變數容器將被清除(free).就是說,僅僅在引用計數減少到非零值時,才會產生垃圾周期(grabage
cycle).其次,在一個垃圾周期中,通過檢查引用計數是否減1,並且檢查哪些變數容器的引用次數是零,來發現哪部分是垃圾
為避免不得不檢查所有引用計數可能減少的垃圾周期,這個演算法把所有可能根(possible roots
都是zval變數容器),放在根緩沖區(root buffer)中(用紫色標記),這樣可以同時確保每個可能的垃圾根(possible
garbage root)在緩沖區只出現一次.僅僅在根緩沖區滿了時,才對緩沖區內部所有不同的變數容器執行垃圾回收操作。
腳本之家查來的
❻ 請簡述php的autoload機制是什麼,有哪些實現方式
這個是類的自動載入。魔術方法,你聲明一個類,這個類你要用到其他類不用把其他類文件包含過來,當年實例化要用到類的時候,這個類就會被自動載入過來(類名字),autoload有個參數,你輸出一下就得到你實例化的那個類名,然後你拼好這個類文件名,在裡面再require一下。就可以用了。
❼ php的while循環機制
while() { }
檢測一次小括弧里的,符合條件的話,再執行大括弧里的語句。
$i=0;
while($i<10)
{
echo$i;
$i++;
}
❽ 總是搞不懂PHP的運行機制,不知道PHP代碼寫在頁面的什麼地方
嚴格的來說,寫在哪都行,除了使用之前不能有輸出的函數,比如說header()、session_start()。當然動態信息要輸出到需要的位置。
❾ php的網路訪問機制是什麼
client向server提交訪問申請,server根據申請內容,經過一定的演算法處理,把最終的輸出信息以HTML的形式返回給client