日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > php >内容正文

php

PHP中文手册1

發布時間:2023/12/14 php 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 PHP中文手册1 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1.入門

關于換行

PHP 會在輸出時自動刪除其結束符??>后的一個換行。該功能主要是針對在一個頁面中嵌入多段 PHP 代碼或者包含了無實質性輸出的 PHP 文件而設計,與此同時也造成了一些疑惑。如果需要在 PHP 結束符??>?之后輸出換行的話,可以在其后加一個空格,或者在最后的一個 echo/print 語句中加入一個換行。

<?php phpinfo();??>

調用函數?phpinfo(),將會看到很多有關自己系統的有用信息,例如預定義變量、已經加載的 PHP 模塊和配置信息。

echo?$_SERVER['HTTP_USER_AGENT']; 該腳本可能輸出是:Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.125 Safari/537.36

打印來自表單的數據:從表單提交姓名和年齡。

你好,<?php?echo?htmlspecialchars($_POST['name']);??>。
你?<?php?echo (int)$_POST['age'];??>?歲了。

htmlspecialchars()使得 HTML 之中的特殊字符被正確的編碼,從而不會被使用者在頁面注入 HTML 標簽或者? ?Javascript 代碼。超全局變量?$_REQUEST,它包含了所有 GET、POST、COOKIE 和 FILE 的數據。

有可能影響到老版本的代碼的最重要的兩點改動分別是:

  • 舊的?$HTTP_*_VARS?數組從 PHP 5.4.0 開始將不再有效。 PHP?? 4.1.0版本引入了如下超全局數組變量:?$_GET、$_POST、$_COOKIE、?$_SERVER、$_FILES、$_ENV、?$_REQUEST?以及?$_SESSION。? ? ?
  • 外部變量不再被默認注冊為全局變量。也就是說,從 PHP?? 4.2.0版開始,php.ini?中的設置選項 register_globals默認值變成了?off。建議用以上提到的超全局數組變量來訪問這些值。但可能老的腳本、書籍以及教程都可能建立在該設置為 on 的基礎上。

<?php 和 ?>:這告訴 PHP 開始和停止解析二者之間的代碼。此種解析方式使得 PHP 可以被嵌入到各種不同的文檔中去。PHP 也允許使用短標記?<??和??>,但不鼓勵使用。只有通過激活?php.ini中的?short_open_tag配置指令或者在編譯 PHP 時使用了配置選項?--enable-short-tags時才能使用短標記。

如果文件內容是純 PHP 代碼,最好在文件末尾刪除 PHP 結束標記。這可以避免在 PHP 結束標記之后萬一意外加入了空格或者換行符,會導致 PHP 開始輸出這些空白,而腳本中此時并無輸出的意圖。

<% echo 'You may optionally use ASP-style tags'; %>
<%= $variable; # This is a shortcut for "<% echo . . ." %>

ASP?風格標記僅在通過?php.ini配置文件中的指令 asp_tags 打開后才可用。

自 PHP 5.4 起,短格式的 echo 標記?<?=總會被識別并且合法,而不管?short_open_tag?的設置是什么。

在一個 PHP 代碼段中的最后一行可以不用分號結束。如果后面還有新行,則代碼段的結束標記包含了行結束。

2.類型

PHP 支持 8 種原始數據類型。

四種標量類型:boolean(布爾型) ? ?integer(整型) ? ?float(浮點型,也稱作?double) ? ?string(字符串)

兩種復合類型:array(數組) ? ?object(對象)

最后是兩種特殊類型:resource(資源) ? ?NULL(無類型)

偽類型:mixed(混合類型) ? ?number(數字類型) ? ?callback(回調類型)

以及偽變量?$...。

?

如果想查看某個表達式的值和類型,用?var_dump()?函數。如果只是想得到一個易讀懂的類型的表達方式用于調試,用?gettype()?函數。要查看某個類型,不要用?gettype(),而用?is_type?函數

如果要將一個變量強制轉換為某類型,可以對其使用強制轉換或者?settype()?函數。

要指定一個布爾值,使用關鍵字?TRUE?或?FALSE。兩個都不區分大小寫。

?

當轉換為 boolean 時,以下值被認為是?FALSE

布爾值?FALSE?本身,整型值 0(零),浮點型值 0.0(零),空字符串,以及字符串?"0"不,包括任何元素的數組,不包括任何成員變量的對象(僅 PHP 4.0 適用),特殊類型?NULL(包括尚未賦值的變量),從空標記生成的?SimpleXML?對象。

所有其它值都被認為是?TRUE(包括任何資源)。

?

一個?integer?是集合 ? = {..., -2, -1, 0, 1, 2, ...} 中的一個數。

整型值要使用八進制表達,數字前必須加上?0(零)。要使用十六進制表達,數字前必須加上?0x。要使用二進制表達,數字前必須加上?0b。

如果向八進制數傳遞了一個非法數字(即 8 或 9),則后面其余數字會被忽略。

var_dump(01090);?// 八進制 010 = 十進制 8
整數溢出:

如果給定的一個數超出了 integer 的范圍,將會被解釋為 float。同樣如果執行的運算結果超出了 integer 范圍,也會返回 float。

?

PHP 中沒有整除的運算符。1/2?產生出?float0.5。值可以舍棄小數部分強制轉換為?integer,或者使用round()?函數可以更好地進行四舍五入。還可以通過函數?intval()?來將一個值轉換成整型。從布爾值轉換,FALSE?將產生出?0(零),TRUE?將產生出?1(壹)。當從浮點數轉換成整數時,將向下取整。決不要將未知的分數強制轉換為?integer,這樣有時會導致不可預料的結果。

echo (int) ( (0.1+0.7) *?10?);?// 顯示 7!

floor((0.1+0.7)*10)通常會返回?7?而不是預期中的?8,因為該結果內部的表示其實是類似7.9999999999999991118...。

所以永遠不要相信浮點數結果精確到了最后一位,也永遠不要比較兩個浮點數是否相等。如果確實需要更高的精度,應該使用任意精度數學函數或者 gmp 函數。要測試浮點數是否相等,要使用一個僅比該數值大一丁點的最小誤差值。

某些數學運算會產生一個由常量?NAN所代表的結果。此結果代表著一個在浮點數運算中未定義或不可表述的值。任何拿此值與其它任何值進行的松散或嚴格比較的結果都是?FALSE。由于?NAN?代表著任何不同值,不應拿?NAN?去和其它值進行比較,包括其自身,應該用?is_nan()?來檢查。

?

string?最大可以達到 2GB。一個字符串可以用 4 種方式表達:

單引號,雙引號,heredoc 語法結構,nowdoc 語法結構(自 PHP 5.3.0 起)

?

要表達一個單引號自身,需在它的前面加個反斜線(\)來轉義。要表達一個反斜線自身,則用兩個反斜線(\\)。其它任何方式的反斜線都會被當成反斜線本身:也就是說如果想使用其它轉義序列例如?\r?或者?\n,并不代表任何特殊含義,就單純是這兩個字符本身。如果字符串是包圍在雙引號(")中, PHP 將對一些特殊的字符進行解析:

\n:換行;\r回車;\t:水平制表符;\v垂直制表符;\e:Escape;\f:換頁;\\:反斜線;\$:美元標記;\":雙引號;還有正則表達式。和單引號字符串一樣,轉義任何其它字符都會導致反斜線被顯示出來。用雙引號定義的字符串最重要的特征是變量會被解析。heredoc 句法結構:<<<。在該運算符之后要提供一個標識符,然后換行。接下來是字符串?string?本身,最后要用前面定義的標識符作為結束標志。

任何具有?string表達的標量變量,數組單元或對象屬性都可使用此語法。只需簡單地像在?string?以外的地方那樣寫出表達式,然后用花括號?{?和?}?把它括起來即可。由于?{?無法被轉義,只有?$緊挨著?{?時才會被識別。可以用?{\$?來表達?{$。

?

$great?=?'fantastic';
// 無效,輸出: This is { fantastic}
echo?"This is {?$great}";
// 有效,輸出: This is fantastic
echo?"This is?{$great}";
echo?"This is?${great}";
// 有效
echo?"This square is?{$square->width}00 centimeters broad.";?
// 有效,只有通過花括號語法才能正確解析帶引號的鍵名
echo?"This works:?{$arr['key']}";

自 5.4 起可以使用短數組定義語法,用?[]?替代?array()。key?可以是?integer?或者?string。value?可以是任意類型。如果在數組定義中多個單元都使用了同一個鍵名,則只使用了最后一個,之前的都被覆蓋了。PHP 數組可以同時含有?integer?和?string?類型的鍵名,因為 PHP 實際并不區分索引數組和關聯數組。如果對給出的值沒有指定鍵名,則取當前最大的整數索引值,而新的鍵名將是該值加一。如果指定的鍵名已經有了值,則該值會被覆蓋。還可以只對某些單元指定鍵名而對其它的空置。數組單元可以通過?array[key]?語法來訪問。

$array?= [
"foo"?=>?"bar",
"bar"?=>?"foo",
];

此外 key 會有如下的強制轉換:

  • 包含有合法整型值的字符串會被轉換為整型。例如鍵名?"8"?實際會被儲存為?8。但是?"08"則不會強制轉換,因為其不是一個合法的十進制數值。
  • 浮點數也會被轉換為整型,意味著其小數部分會被舍去。例如鍵名?8.7?實際會被儲存為?8。
  • 布爾值也會被轉換成整型。即鍵名?true?實際會被儲存為?1而鍵名?false?會被儲存為?0。
  • Null 會被轉換為空字符串,即鍵名?null?實際會被儲存為?""。
  • 數組和對象不能被用為鍵名。堅持這么做會導致警告:Illegal offset type。

?

<?php
$array?= array(
? ? "foo"?=>?"bar",
? ? 42?=>?24,
? ? "multi"?=> array(
? ? "dimensional"?=> array(
? ? "array"?=>?"foo"
? ? ? ? )
? ? )
);
var_dump($array["foo"]);
var_dump($array[42]);
var_dump($array["multi"]["dimensional"]["array"]);
?> string(3) "bar" int(24) string(3) "foo"

?

自 PHP 5.4 起可以用數組間接引用函數或方法調用的結果。之前只能通過一個臨時變量。自 PHP 5.5 起可以用數組間接引用一個數組原型。

<?php
function?getArray() {
return array(1,?2,?3);
}
// on PHP 5.4
$secondElement?=?getArray()[1];
// previously
$tmp?=?getArray();
$secondElement?=?$tmp[1];
// or
list(,?$secondElement) =?getArray();
?>

僅對部分單元指定鍵名:

?

<?php
$array?= array(
? ? ? ? "a",
? ? ? ? "b",
? ?6?=>?"c",
? ? ? ? "d",
);
var_dump($array);
?> array(4) {[0]=>string(1) "a"[1]=>string(1) "b"[6]=>string(1) "c"[7]=>string(1) "d" }

要修改某個值,通過其鍵名給該單元賦一個新值。要刪除某鍵值對,對其調用?unset()?函數。

<?php
$arr?= array(5?=>?1,?12?=>?2);
$arr[] =?56;?// This is the same as $arr[13] = 56;
$arr["x"] =?42;?// This adds a new element to
unset($arr[5]);?// This removes the element from the array
unset($arr);?// This deletes the whole array
?>

?

unset()?函數允許刪除數組中的某個鍵。但要注意數組將不會重建索引。如果需要刪除后重建索引,可以用array_values()?函數。

?

對于任意?integer,float,string,boolean和?resource?類型,如果將一個值轉換為數組,將得到一個僅有一個元素的數組,其下標為 0,該元素即為此標量的值。換句話說,(array)$scalarValue?與array($scalarValue)?完全一樣。

如果一個?object?類型轉換為?array,則結果為一個數組,其單元為該對象的屬性。鍵名將為成員變量名,不過有幾點例外:整數屬性不可訪問;私有變量前會加上類名作前綴;保護變量前會加上一個 '*' 做前綴。這些前綴的前后都各有一個 NULL 字符。這會導致一些不可預知的行為:

<?php
class?A?{
private?$A;?// This will become '\0A\0A'
}
class?B?extends?A?{
private?$A;?// This will become '\0B\0A'
public?$AA;?// This will become 'AA'
}
var_dump((array) new?B());
?>

上例會有兩個鍵名為 'AA',不過其中一個實際上是 '\0A\0A'。

數組(Array)?的賦值總是會涉及到值的拷貝。使用引用運算符通過引用來拷貝數組。

<?php
$arr1?= array(2,?3);
$arr2?=?$arr1;
$arr2[] =?4;?// $arr2 is changed,
? ? ? ? ? ? // $arr1 is still array(2, 3)
$arr3?= &$arr1;
$arr3[] =?4;?// now $arr1 and $arr3 are the same
?>

要創建一個新的對象?object,使用?new?語句實例化一個類。如果將一個對象轉換成對象,它將不會有任何變化。如果其它任何類型的值被轉換成對象,將會創建一個內置類?stdClass?的實例。如果該值為?NULL,則新的實例為空。數組轉換成對象將使鍵名成為屬性名并具有相對應的值。對于任何其它的值,名為?scalar?的成員變量將包含該值。

<?php
$obj?= (object)?'ciao';
echo?$obj->scalar;?// outputs 'ciao'
?>

資源?resource是一種特殊變量,保存了到外部資源的一個引用。資源是通過專門的函數來建立和使用的。

由于資源類型變量保存有為打開文件、數據庫連接、圖形畫布區域等的特殊句柄,因此將其它類型的值轉換為資源沒有意義。

特殊的?NULL?值表示一個變量沒有值。NULL?類型唯一可能的值就是?NULL。

?

在下列情況下一個變量被認為是?NULL

被賦值為?NULL。尚未被賦值。被?unset()。

?

NULL?類型只有一個值,就是不區分大小寫的常量?NULL

使用?(unset) $var?將一個變量轉換為?null將不會刪除該變量或 unset 其值。僅是返回?NULL?值而已。

一些函數如?call_user_func()?或?usort()?可以接受用戶自定義的回調函數作為參數。回調函數不止可以是簡單函數,還可以是對象的方法,包括靜態類方法。一個 PHP 的函數以?string類型傳遞其名稱??梢允褂萌魏蝺戎没蛴脩糇远x函數,但除了語言結構例如:array(),echo,empty(),eval(),exit(),isset(),list(),print或?unset()。一個已實例化的對象的方法被作為數組傳遞,下標 0 包含該對象,下標 1 包含方法名。除了普通的用戶自定義函數外,create_function()可以用來創建一個匿名回調函數。

<?php?
// An example callback function
function?my_callback_function() {
echo?'hello world!';
}
// An example callback method
class?MyClass?{
static function?myCallbackMethod() {
echo?'Hello World!';
? ? }
}
// Type 1: Simple callback
call_user_func('my_callback_function');?
// Type 2: Static class method call
call_user_func(array('MyClass',?'myCallbackMethod'));?
// Type 3: Object method call
$obj?= new?MyClass();
call_user_func(array($obj,?'myCallbackMethod'));
// Type 4: Static class method call (As of PHP 5.2.3)
call_user_func('MyClass::myCallbackMethod');
// Type 5: Relative static class method call (As of PHP 5.3.0)
class?A?{
public static function?who() {
echo?"A\n";
? ? }
}
class?B?extends?A?{
public static function?who() {
echo?"B\n";
? ? }
}
call_user_func(array('B',?'parent::who'));?// A
?>

在函數中注冊有多個回調內容時(如使用call_user_func()?與?call_user_func_array()),如在前一個回調中有未捕獲的異常,其后的將不再被調用。

mixed?說明一個參數可以接受多種不同的(但不一定是所有的)類型。例如?gettype()?可以接受所有的 PHP 類型,str_replace()?可以接受字符串和數組。number?說明一個參數可以是?integer?或者?float。本文檔中在 PHP 5.4 引入?callable?類型之前使用 了?callback?偽類型。二者含義完全相同。void?作為返回類型意味著函數的返回值是無用的。void作為參數列表意味著函數不接受任何參數。在函數原型中,$...?表示等等的意思。當一個函數可以接受任意個參數時使用此變量名。

?

<?php
$foo?=?"0";?// $foo 是字符串 (ASCII 48)
$foo?+=?2;?// $foo 現在是一個整數 (2)
$foo?=?$foo?+?1.3;?// $foo 現在是一個浮點數 (3.3)
$foo?=?5?+?"10 Little Piggies";?// $foo 是整數 (15)
$foo?=?5?+?"10 Small Pigs";?// $foo 是整數 (15)
?>

?

?

自動轉換為?數組?的行為目前沒有定義。

<?php $a?=?'car';?// $a is a string $a[0] =?'b';?// $a is still a string echo?$a;?// bar ?>

允許的強制轉換有:注意在括號內允許有空格和制表符

  • (int), (integer) - 轉換為整形 integer
  • (bool), (boolean) - 轉換為布爾類型 boolean
  • (float), (double), (real) - 轉換為浮點型 float
  • (string) - 轉換為字符串 string
  • (array) - 轉換為數組 array
  • (object) - 轉換為對象 object
  • (unset) - 轉換為 NULL (PHP 5)

3.變量

$this?是一個特殊的變量,它不能被賦值。 ? ?使用引用賦值,簡單地將一個 & 符號加到將要賦值的變量前(源變量)。

<?php
$foo?=?'Bob';?// 將 'Bob' 賦給 $foo
$bar?= &$foo;?// 通過 $bar 引用 $foo
$bar?=?"My name is?$bar";?// 修改 $bar 變量
echo?$bar;
echo?$foo;?// $foo 的值也被修改
?>

有一點重要事項須指出,那就是只有有名字的變量才可以引用賦值。$bar?= &(24?*?7);?// 非法; 引用沒有名字的表達式

未初始化的變量具有其類型的默認值 - 布爾類型的變量默認值是?FALSE,整形和浮點型變量默認值是零,字符串型變量(例如用于?echo中)默認值是空字符串以及數組變量的默認值是空數組。isset()?語言結構可以用來檢測一個變量是否已被初始化。

<?php
$a?=?1;
$b?=?2;
function?Sum(){
global?$a,?$b;
$b?=?$a?+?$b;
}
Sum();
echo?$b;
?>
等價于下面的(輸出為3): $GLOBALS['b'] =?$GLOBALS['a'] +?$GLOBALS['b'];

$GLOBALS是一個關聯數組,每一個變量為一個元素,鍵名對應變量名,值對應變量的內容。$GLOBALS之所以在全局范圍內存在,是因為 $GLOBALS 是一個超全局變量。變量范圍的另一個重要特性是靜態變量(static variable)。靜態變量僅在局部函數域中存在,但當程序執行離開此作用域時,其值并不丟失。如果在聲明中用表達式的結果對其賦值會導致解析錯誤。static?$int?=?0;?// correct

static?$int?=?1+2;?// wrong (as it is an expression)

static?$int?=?sqrt(121);?// wrong (as it is an expression too)

可變變量:一個變量的變量名可以動態的設置和使用。一個普通的變量通過聲明來設置。要將可變變量用于數組,必須解決一個模棱兩可的問題。這就是當寫下?$$a[1]時,解析器需要知道是想要?$a[1]作為一個變量呢,還是想要?$$a作為一個變量并取出該變量中索引為 [1] 的值。解決此問題的語法是,對第一種情況用${$a[1]},對第二種情況用?${$a}[1]。

類的屬性也可以通過可變屬性名來訪問??勺儗傩悦麑⒃谠撜{用所處的范圍內被解析。例如,對于?$foo->$bar?表達式,則會在本地范圍來解析?$bar并且其值將被用于?$foo?的屬性名。對于?$bar是數組單元時也是一樣。

<?php
class?foo?{
var?$bar?=?'I am bar.';
var?$arr?= array('I am A.',?'I am B.',?'I am C.');
var?$r?=?'I am r.';
}
$foo?= new?foo();
$bar?=?'bar';
$baz?= array('foo',?'bar',?'baz',?'quux');
echo?$foo->$bar?.?"\n";
echo?$foo->$baz[1] .?"\n";
$start?=?'b';
$end?=?'ar';
echo?$foo->{$start?.?$end} .?"\n";
$arr?=?'arr';
echo?$foo->$arr[1] .?"\n";
echo?$foo->{$arr}[1] .?"\n";
?>
I am bar.
I am bar.
I am bar.
I am r.
I am B.

注意,在 PHP 的函數和類的方法中,超全局變量不能用作可變變量。$this變量也是一個特殊變量,不能被動態引用。

變量名中的點和空格被轉換成下劃線。例如?<input name="a.b" />?變成了?$_REQUEST["a_b"]。

4.常量

可以用?define()?函數來定義常量,在 PHP 5.3.0 以后,可以使用?const關鍵字在類定義之外定義常量。一個常量一旦被定義,就不能再改變或者取消定義。常量只能包含標量數據(boolean,integer,float和?string)??梢远x?resource?常量,但應盡量避免,因為會造成不可預料的結果。如果常量名是動態的,也可以用函數?constant()?來獲取常量的值。用?get_defined_constants()?可以獲得所有已定義的常量列表。如果只想檢查是否定義了某常量,用?defined()?函數。

常量和變量有如下不同:

  • 常量前面沒有美元符號($);
  • 常量只能用 define() 函數定義,而不能通過賦值語句;
  • 常量可以不用理會變量的作用域而在任何地方定義和訪問;
  • 常量一旦定義就不能被重新定義或者取消定義;
  • 常量的值只能是標量。

和使用?define()?來定義常量相反的是,使用?const關鍵字定義常量必須處于最頂端的作用區域,因為用此方法是在編譯時定義的。這就意味著不能在函數內,循環內以及?if?語句之內用?const?來定義常量。

有八個魔術常量它們的值隨著它們在代碼中的位置改變而改變。

__LINE__文件中的當前行號。
__FILE__文件的完整路徑和文件名。如果用在被包含文件中,則返回被包含的文件名。
__DIR__文件所在的目錄。如果用在被包括文件中,則返回被包括的文件所在的目錄。
__FUNCTION__函數名稱(PHP 4.3.0 新加)。自 PHP 5 起本常量返回該函數被定義時的名字(區分大小寫)。在 PHP 4 中該值總是小寫字母的。
__CLASS__類的名稱(PHP 4.3.0 新加)。自 PHP 5 起本常量返回該類被定義時的名字(區分大小寫)。在 PHP 4 中該值總是小寫字母的。類名包括其被聲明的作用區域(例如?Foo\Bar)。注意自 PHP 5.4 起 __CLASS__ 對 trait 也起作用。當用在 trait 方法中時,__CLASS__ 是調用 trait 方法的類的名字。
__TRAIT__Trait 的名字(PHP 5.4.0 新加)。自 PHP 5.4 起此常量返回 trait 被定義時的名字(區分大小寫)。Trait 名包括其被聲明的作用區域(例如?Foo\Bar)。
__METHOD__類的方法名(PHP 5.0.0 新加)。返回該方法被定義時的名字(區分大小寫)。
__NAMESPACE__當前命名空間的名稱(區分大小寫)。此常量是在編譯時定義的(PHP 5.3.0 新增)。
5.運算符 運算符優先級結合方向運算符附加信息
clone newclone 和 new
[array()
++ -- ~ (int) (float) (string) (array) (object) (bool) @類型和遞增/遞減
instanceof類型
!邏輯運算符
* / %算術運算符
+ - .算術運算符和字符串運算符
<< >>位運算符
== != === !== <>比較運算符
&位運算符和引用
^位運算符
|位運算符
&&邏輯運算符
||邏輯運算符
? :三元運算符
= += -= *= /= .= %= &= |= ^= <<= >>= =>賦值運算符
and邏輯運算符
xor邏輯運算符
or邏輯運算符
,多處用到

除法運算符總是返回浮點數。只有在下列情況例外:兩個操作數都是整數(或字符串轉換成的整數)并且正好能整除,這時它返回一個整數。取模運算符的操作數在運算之前都會轉換成整數(除去小數部分)。取模運算符?%?的結果和被除數的符號(正負號)相同?;镜馁x值運算符是"="。實際上意味著把右邊表達式的值賦給左邊的運算數。

$a?= ($b?=?4) +?5;?// $a 現在成了 9,而 $b 成了 4。

在 PHP 中普通的傳值賦值行為有個例外就是碰到對象?object?時,在 PHP 5 中是以引用賦值的,除非明確使用了 clone 關鍵字來拷貝。PHP 支持引用賦值,使用"$var = &$othervar;"語法。引用賦值意味著兩個變量指向了同一個數據,沒有拷貝任何東西。

位運算符:

$a & $bAnd(按位與)將把?$a?和?$b?中都為 1 的位設為 1。
$a | $bOr(按位或)將把?$a?和?$b?中任何一個為 1 的位設為 1。
$a ^ $bXor(按位異或)將把?$a?和?$b?中一個為 1 另一個為 0 的位設為 1。
~ $aNot(按位取反)將?$a?中為 0 的位設為 1,反之亦然。
$a << $bShift left(左移)將?$a?中的位向左移動?$b?次(每一次移動都表示"乘以 2")。
$a >> $bShift right(右移)將?$a?中的位向右移動?$b?次(每一次移動都表示"除以 2")。

左移時右側以零填充,符號位被移走意味著正負號不被保留。右移時左側以符號位填充,意味著正負號被保留。

要注意數據類型的轉換。如果左右參數都是字符串,則位運算符將對字符的 ASCII 值進行操作。不要在 32 位系統下向右移超過 32 位。不要在結果可能超過 32 的情況下左移。使用 gmp 擴展對超出 PHP_INT_MAX 的數值來進行位操作。

比較運算符:
$a == $b等于TRUE,如果類型轉換后?$a?等于?$b。
$a === $b全等TRUE,如果?$a?等于?$b,并且它們的類型也相同。
$a != $b不等TRUE,如果類型轉換后?$a?不等于?$b。
$a <> $b不等TRUE,如果類型轉換后?$a?不等于?$b。
$a !== $b不全等TRUE,如果?$a?不等于?$b,或者它們的類型不同。
$a < $b小與TRUE,如果?$a?嚴格小于?$b。
$a > $b大于TRUE,如果?$a?嚴格大于?$b。
$a <= $b小于等于TRUE,如果?$a?小于或者等于?$b。
$a >= $b大于等于TRUE,如果?$a?大于或者等于?$b。
var_dump(0?==?"a");?// 0 == 0 -> true
var_dump("1"?==?"01");?// 1 == 1 -> true
var_dump("10"?==?"1e1");?// 10 == 10 -> true

由于浮點數?float?的內部表達方式,不應比較兩個浮點數是否相等。另一個條件運算符是"?:"(或三元)運算符 。

$action?= (empty($_POST['action'])) ??'default'?:?$_POST['action']; 表達式?(expr1) ? (expr2) : (expr3)?在?expr1?求值為?TRUE時的值為?expr2,在?expr1?求值為?FALSE?時的值為? ? ?expr3。

自 PHP 5.3 起,可以省略三元運算符中間那部分。表達式?expr1 ?: expr3?在?expr1?求值為?TRUE?時返回expr1,否則返回?expr3。

PHP 支持一個錯誤控制運算符:@。當將其放置在一個 PHP 表達式之前,該表達式可能產生的任何錯誤信息都被忽略掉。

如果用?set_error_handler()設定了自定義的錯誤處理函數,仍然會被調用,但是此錯誤處理函數可以(并且也應該)調用?error_reporting(),而該函數在出錯語句前有 @ 時將返回 0。如果激活了?track_errors特性,表達式所產生的任何錯誤信息都被存放在變量?$php_errormsg中。此變量在每次出錯時都會被覆蓋,所以如果想用它的話就要盡早檢查。

PHP 支持一個執行運算符:反引號(``)。注意這不是單引號!PHP 將嘗試將反引號中的內容作為外殼命令來執行,并將其輸出信息返回(即,可以賦給一個變量而不是簡單地丟棄到標準輸出)。使用反引號運算符"`"的效果與函數?shell_exec()?相同。

<?php
$output?= `ls -al`;
echo?"<pre>$output</pre>";
?>

反引號運算符在激活了安全模式或關閉了?shell_exec()?時是無效的。與其它某些語言不同,反引號不能在雙引號字符串中使用。

遞增或遞減布爾值沒有效果。遞增遞減運算符:

++$a前加$a?的值加一,然后返回?$a。
$a++后加返回?$a,然后將?$a?的值加一。
--$a前減$a?的值減一, 然后返回?$a。
$a--后減返回?$a,然后將?$a?的值減一。
邏輯運算符:
$a and $bAnd(邏輯與)TRUE,如果?$a?和?$b?都為?TRUE
$a or $bOr(邏輯或)TRUE,如果?$a?或?$b?任一為?TRUE
$a xor $bXor(邏輯異或)TRUE,如果?$a?或?$b?任一為?TRUE,但不同時是。
! $aNot(邏輯非)TRUE,如果?$a?不為?TRUE。
$a && $bAnd(邏輯與)TRUE,如果?$a?和?$b?都為?TRUE。
$a || $bOr(邏輯或)TRUE,如果?$a?或?$b?任一為?TRUE

"與"和"或"有兩種不同形式運算符的原因是它們運算的優先級不同

有兩個字符串(string)運算符。第一個是連接運算符("."),它返回其左右參數連接后的字符串。第二個是連接賦值運算符(".="),它將右邊參數附加到左邊的參數之后。

<?php
$a?=?"Hello ";
$b?=?$a?.?"World!";?// now $b contains "Hello World!"
$a?=?"Hello ";
$a?.=?"World!";?// now $a contains "Hello World!"
?>
數組運算符:
$a + $b聯合$a?和?$b?的聯合。
$a == $b相等如果?$a?和?$b?具有相同的鍵/值對則為?TRUE
$a === $b全等如果?$a?和?$b?具有相同的鍵/值對并且順序和類型都相同則為?TRUE
$a != $b不等如果?$a?不等于?$b?則為?TRUE。
$a <> $b不等如果?$a?不等于?$b?則為?TRUE
$a !== $b不全等如果?$a?不全等于?$b?則為?TRUE

+?運算符把右邊的數組元素附加到左邊的數組后面,兩個數組中都有的鍵名,則只用左邊數組中的,右邊的被忽略。

?

<?php
$a?= array("apple",?"banana");
$b?= array(1?=>?"banana",?"0"?=>?"apple");
var_dump($a?==?$b);?// bool(true)
var_dump($a?===?$b);?// bool(false)
?>
類型運算符:instanceof?用于確定一個 PHP 變量是否屬于某一類?class?的實例。instanceof 也可用來確定一個變量是不是繼承自某一父類的子類的實例。檢查一個對象是否不是某個類的實例,可以使用邏輯運算符?not。instanceof也可用于確定一個變量是不是實現了某個接口的對象的實例。雖然?instanceof?通常直接與類名一起使用,但也可以使用對象或字符串變量:

?

?

<?php
interface?MyInterface{?}
class?MyClass?implements?MyInterface{?}
$a?= new?MyClass;
$b?= new?MyClass;
$c?=?'MyClass';
$d?=?'NotMyClass';
var_dump($a?instanceof?$b);?// $b is an object of class MyClass
var_dump($a?instanceof?$c);?// $c is a string 'MyClass'
var_dump($a?instanceof?$d);?// $d is a string 'NotMyClass'
?>
bool(true) bool(true) bool(false)

如果被檢測的變量不是對象,instanceof 并不發出任何錯誤信息而是返回?FALSE。不允許用來檢測常量。instanceof?運算符是 PHP 5 引進的。在此之前用?is_a(),但是后來?is_a()?被廢棄而用?instanceof替代了。注意自 PHP 5.3.0 起,又恢復使用?is_a()?了。

6.流程控制

?

?

if?語句可以無限層地嵌套在其它?if?語句中,這給程序的不同部分的條件執行提供了充分的彈性。

else?語句僅在?if?以及?elseif(如果有的話)語句中的表達式的值為?FALSE?時執行。

elseif?的語句僅在之前的?if?和所有之前?elseif?的表達式值為?FALSE,并且當前的?elseif?表達式值為?TRUE?時執行

?

必須要注意的是?elseif?與?else if只有在類似上例中使用花括號的情況下才認為是完全相同。如果用冒號來定義? ?if/elseif?條件,那就不能用兩個單詞的?else if,否則 PHP 會產生解析錯誤。

?

<?php
/* 不正確的使用方法: */
if($a?>?$b):
? ? echo?$a." is greater than ".$b;
else if($a?==?$b):?// 將無法編譯
? ? echo?"The above line causes a parse error.";
endif;
/* 正確的使用方法: */
if($a?>?$b):
? ? echo?$a." is greater than ".$b;
elseif($a?==?$b):?// 注意使用了一個單詞的 elseif
? ? echo?$a." equals ".$b;
else:
? ? echo?$a." is neither greater than or equal to ".$b;
endif;
?>

?

?

PHP 提供了一些流程控制的替代語法,包括?if,while,for,foreach和?switch。替代語法的基本形式是把左花括號({)換成冒號(:),把右花括號(})分別換成?endif;,endwhile;,endfor;,endforeach;以及?endswitch;。

不支持在同一個控制塊內混合使用兩種語法。

?

do-while?循環和?while循環非常相似,區別在于表達式的值是在每次循環結束時檢查而不是開始時。和一般的?while?循環主要的區別是?do-while的循環語句保證會執行一次(表達式的真值在每次循環結束后檢查),然而在一般的?while?循環中就不一定了(表達式真值在循環開始時檢查,如果一開始就為?FALSE?則整個循環立即終止)。

foreach?語法結構提供了遍歷數組的簡單方式。foreach僅能夠應用于數組和對象,如果嘗試應用于其他數據類型的變量,或者未初始化的變量將發出錯誤信息。有兩種語法:

foreach (array_expression as $value)statement foreach (array_expression as $key => $value)statement

?

?

當?foreach開始執行時,數組內部的指針會自動指向第一個單元。這意味著不需要在?foreach?循環之前調用?reset()。

由于?foreach?依賴內部數組指針,在循環中修改其值將可能導致意外的行為。

?

?

<?php
$arr?= array(1,?2,?3,?4);
foreach ($arr?as &$value) {
? ? $value?=?$value?*?2;
}
// $arr is now array(2, 4, 6, 8)
unset($value);?// 最后取消掉引用
?>

數組最后一個元素的?$value?引用在?foreach?循環之后仍會保留。建議使用?unset()?來將其銷毀。

以下的代碼功能完全相同:

?

?

<?php
$arr?= array("one",?"two",?"three");
reset($arr);
while (list(,?$value) =?each($arr)) {
? ? echo?"Value:?$value<br>\n";
}

foreach ($arr?as?$value) {
? ? echo?"Value:?$value<br />\n";
}
?>
或者:

?

?

<?php
$arr?= array("one",?"two",?"three");
reset($arr);
while (list($key,?$value) =?each($arr)) {
? ? echo?"Key:?$key; Value:?$value<br />\n";
}
foreach ($arr?as?$key?=>?$value) {
? ? echo?"Key:?$key; Value:?$value<br />\n";
}
?>

?

?

PHP 5.5 增添了遍歷一個數組的數組的功能并且把嵌套的數組解包到循環變量中,只需將?list()?作為值提供。

<?php
$array?= [
? ? [1,?2],
? ? [3,?4],
];
foreach ($array?as list($a,?$b)) {
? ? // $a contains the first element of the nested array,
? ? // and $b contains the second element.
? ? echo?"A:?$a; B:?$b\n";
}
?>
A: 1; B: 2 A: 3; B: 4

list()?中的單元可以少于嵌套數組的,此時多出來的數組單元將被忽略。echo?"$a\n"; ? ?//會輸出1 3

如果?list()?中列出的單元多于嵌套數組則會發出一條消息級別的錯誤信息。echo?"A:?$a; B:?$b; C:?$c\n";//會輸出

Notice: Undefined offset: 2 in example.php on line 7 A: 1; B: 2; C: Notice: Undefined offset: 2 in example.php on line 7 A: 3; B: 4; C:

break?可以接受一個可選的數字參數來決定跳出幾重循環。

<?php
$arr?= array('one',?'two',?'three',?'four',?'stop',?'five');
while (list (,?$val) =?each($arr)) {
? ? if ($val?==?'stop') {
? ? ? ? break;?/* You could also write 'break 1;' here. */
? ? }
? ? echo?"$val<br />\n";
}
/* 使用可選參數 */
$i?=?0;
while (++$i) {
? ? switch ($i) {
? ? case?5:echo?"At 5<br />\n";
? ? ? ? ? ?break?1;?/* 只退出 switch. */
? ? case?10:echo?"At 10; quitting<br />\n";
? ? ? ? ? ? break?2;?/* 退出 switch 和 while 循環 */
? ? default:
? ? ? ? ? ? break;
? ? ? ? }
}
?>

continue在循環結構用用來跳過本次循環中剩余的代碼并在條件求值為真時開始執行下一次循環。continue?接受一個可選的數字參數來決定跳過幾重循環到循環結尾。默認值是?1,即跳到當前循環末尾。省略?continue后面的分號會導致混淆。

<?php
while (list ($key,?$value) =?each($arr)) {
? ? if (!($key?%?2)) {?// skip odd members
? ? ? ? continue;
? ? }
? ? do_something_odd($value);
}
$i?=?0;
while ($i++ <?5) {
? ? echo?"Outer<br />\n";
? ? while (1) {
? ? ? ? echo?"Middle<br />\n";
? ? ? ? while (1) {
? ? ? ? ? ? echo?"Inner<br />\n";
? ? ? ? ? ? continue?3;
? ? ? ? }
? ? ? ? echo?"This never gets output.<br />\n";
? ? }
? ? echo?"Neither does this.<br />\n";
}
?>

?

?

注意和其它語言不同,continue語句作用到 switch 上的作用類似于?break。如果在循環中有一個 switch 并希望 continue 到外層循環中的下一輪循環,用?continue 2。注意 switch/case 作的是松散比較。允許使用分號代替 case 語句后的冒號.

?

?

declare?結構用來設定一段代碼的執行指令。declare的語法和其它流程控制結構相似:

declare (directive)statement

directive?部分允許設定?declare代碼段的行為。目前只認識兩個指令:ticks以及?encoding。

declare?代碼段中的?statement部分將被執行—怎樣執行以及執行中有什么副作用出現取決于?directive?中設定的指令。declare?結構也可用于全局范圍,影響到其后的所有代碼(但如果有?declare?結構的文件被其它文件包含,則對包含它的父文件不起作用)。

Tick(時鐘周期)是一個在?declare?代碼段中解釋器每執行?N?條可計時的低級語句就會發生的事件。N的值是在?declare?中的?directive?部分用?ticks=N?來指定的。不是所有語句都可計時。通常條件表達式和參數表達式都不可計時。在每個 tick 中出現的事件是由?register_tick_function()來指定的。注意每個 tick 中可以出現多個事件。

可以用 encoding 指令來對每段腳本指定其編碼方式。對腳本指定編碼方式:

<?php
declare(encoding='ISO-8859-1');
// code here
?>

如果在一個函數中調用?return語句,將立即結束此函數的執行并將它的參數作為函數的值返回。return也會終止?eval()?語句或者腳本文件的執行。如果在全局范圍中調用,則當前腳本文件中止運行。如果當前腳本文件是被?include?的或者?require的,則控制交回調用文件。此外,如果當前腳本是被?include的,則?return?的值會被當作?include調用的返回值。如果在主腳本文件中調用?return,則腳本中止運行。如果當前腳本文件是在?php.ini中的配置選項?auto_prepend_file?或者?auto_append_file?所指定的,則此腳本文件中止運行。當用引用返回值時永遠不要使用括號,這樣行不通。只能通過引用返回變量,而不是語句的結果。如果使用?return ($a);?時其實不是返回一個變量,而是表達式?($a)?的值(當然,此時該值也正是?$a?的值)。

?

?

?

?

require?和?include?幾乎完全一樣,除了處理失敗的方式不同之外。require?在出錯時產生?E_COMPILE_ERROR?級別的錯誤。換句話說將導致腳本中止而?include?只產生警告(E_WARNING),腳本會繼續運行。

被包含文件先按參數給出的路徑尋找,如果沒有給出目錄(只有文件名)時則按照 include_path 指定的目錄尋找。如果在 include_path 下沒找到該文件則?include?最后才在調用腳本文件所在的目錄和當前工作目錄下尋找。如果最后仍未找到文件則?include?結構會發出一條警告;這一點和?require?不同,后者會發出一個致命錯誤。當一個文件被包含時,其中所包含的代碼繼承了 include 所在行的變量范圍。從該處開始,調用文件在該行處可用的任何變量在被調用的文件中也都可用。不過所有在包含文件中定義的函數和類都具有全局作用域。

vars.php
<?php
$color?=?'green';
$fruit?=?'apple';
?>
test.php
<?php
echo?"A?$color?$fruit";?//?A
include?'vars.php';
echo?"A?$color?$fruit";?//?A?green?apple
?>

如果 include 出現于調用文件中的一個函數里,則被調用的文件中所包含的所有代碼將表現得如同它們是在該函數內部定義的一樣。所以它將遵循該函數的變量范圍。此規則的一個例外是魔術常量,它們是在發生包含之前就已被解析器處理的。

<?php
function?foo(){
????global?$color;
????include?'vars.php';
????echo?"A?$color?$fruit";
}
foo();????????????????????//?A?green?apple
echo?"A?$color?$fruit";???//?A?green
?>

處理返回值:在失敗時?include?返回?FALSE?并且發出警告。成功的包含則返回?1,除非在包含文件中另外給出了返回值??梢栽诒话ǖ奈募惺褂?return?語句來終止該文件中程序的執行并返回調用它的腳本。同樣也可以從被包含的文件中返回值??梢韵衿胀ê瘮狄粯荧@得 include 調用的返回值。不過這在包含遠程文件時卻不行,除非遠程文件的輸出具有合法的 PHP 開始和結束標記(如同任何本地文件一樣)。可以在標記內定義所需的變量,該變量在文件被包含的位置之后就可用了。

因為?include?是一個特殊的語言結構,其參數不需要括號。在比較其返回值時要注意。

return.php
<?php
$var?=?'PHP';
return?$var;
?>
noreturn.php
<?php
$var?=?'PHP';
?>
testreturns.php
<?php
$foo?=?include?'return.php';
echo?$foo;?//?prints?'PHP'
$bar?=?include?'noreturn.php';
echo?$bar;?//?prints?1
?>

如果在包含文件中定義有函數,這些函數不管是在?return?之前還是之后定義的,都可以獨立在主文件中使用。如果文件被包含兩次,PHP 5 發出致命錯誤因為函數已經被定義,但是 PHP 4 不會對在?return?之后定義的函數報錯。推薦使用?include_once?而不是檢查文件是否已包含并在包含文件中有條件返回。要在腳本中自動包含文件,參見?php.ini?中的?auto_prepend_file?和?auto_append_file?配置選項。

require_once?語句和?require?語句完全相同,唯一區別是 PHP 會檢查該文件是否已經被包含過,如果是則不會再次包含。

include_once?語句在腳本執行期間包含并運行指定文件。此行為和?include?語句類似,唯一區別是如果該文件中已經被包含過,則不會再次包含。如同此語句名字暗示的那樣,只會包含一次。

goto?操作符可以用來跳轉到程序中的另一位置。該目標位置可以用目標名稱加上冒號來標記,而跳轉指令是goto?之后接上目標位置的標記。PHP 中的?goto?有一定限制,目標位置只能位于同一個文件和作用域,也就是說無法跳出一個函數或類方法,也無法跳入到另一個函數。也無法跳入到任何循環或者 switch 結構中??梢蕴鲅h或者 switch,通常的用法是用?goto?代替多層的?break。

goto?操作符僅在 PHP 5.3及以上版本有效。

7.函數

?

?

函數無需在調用之前被定義,除非是下面例子中函數是有條件被定義時。當一個函數是有條件被定義時,其定義必須在調用之前先處理。

<?php
$makefoo?=?true;
/*?不能在此處調用foo()函數,因為它還不存在,但可以調用bar()函數。*/
bar();
if?($makefoo)?{
??function?foo(){
????echo?"I?don't?exist?until?program?execution?reaches?me.\n";
??}
}
/*?現在可以安全調用函數?foo()了,因為?$makefoo?值為真?*/
if?($makefoo)?foo();
function?bar(){
??echo?"I?exist?immediately?upon?program?start.\n";
}
?>

?

函數中的函數:

?

?

<?php
function?foo(){
??function?bar(){
????echo?"I?don't?exist?until?foo()?is?called.\n";
??}
}
/*?現在還不能調用bar()函數,因為它還不存在?*/
foo();
/*?現在可以調用bar()函數了,因為foo()函數的執行使得bar()函數變為已定義的函數?*/
bar();
?>

PHP 不支持函數重載,也不可能取消定義或者重定義已聲明的函數。PHP 的函數支持可變數量的參數和默認參數。

在 PHP 中可以調用遞歸函數。但是要避免遞歸函數/方法調用超過 100-200 層,因為可能會使堆棧崩潰從而使當前腳本終止。

<?php
function?recursion($a){
????if?($a?<?20)?{
????????echo?"$a\n";
????????recursion($a?+?1);
????}
}
?>

PHP 支持按值傳遞參數(默認),通過引用傳遞參數以及默認參數。也支持可變長度參數列表。默認情況下,函數參數通過值傳遞(因而即使在函數內部改變參數的值,它并不會改變函數外部的值)。如果希望允許函數修改它的參數值,必須通過引用傳遞參數。

如果想要函數的一個參數總是通過引用傳遞,可以在函數定義中該參數的前面加上符號 &。用引用傳遞函數參數:

<?php
function?add_some_extra(&$string){
????$string?.=?'and?something?extra.';
}
$str?=?'This?is?a?string,?';
add_some_extra($str);
echo?$str;????//?outputs?'This?is?a?string,?and?something?extra.'
?>

在函數中使用默認參數:

?

<?php
function?makecoffee($type?=?"cappuccino"){
????return?"Making?a?cup?of?$type.\n";
}
echo?makecoffee(); ? ?//Making a cup of cappuccino.?
echo?makecoffee(null); ? ?//Making a cup of .
echo?makecoffee("espresso"); ? ?//Making a cup of espresso.
?>

PHP 還允許使用數組?array?和特殊類型?NULL?作為默認參數:

<?php
function?makecoffee($types?=?array("cappuccino"),?$coffeeMaker?=?NULL){
????$device?=?is_null($coffeeMaker)???"hands"?:?$coffeeMaker;
????return?"Making?a?cup?of?".join(",?",?$types)."?with?$device.\n";
}
echo?makecoffee();
echo?makecoffee(array("cappuccino",?"lavazza"),?"teapot");
?>

?

默認值必須是常量表達式,不能是諸如變量,類成員,或者函數調用等。注意當使用默認參數時,任何默認參數必須放在任何非默認參數的右側;否則,函數將不會按照預期的情況工作。自 PHP 5 起,傳引用的參數也可以有默認值。

PHP 在用戶自定義函數中支持可變數量的參數列表。

<?php
function?sum(...$numbers)?{
????$acc?=?0;
????foreach?($numbers?as?$n)?{
????????$acc?+=?$n;
????}
????return?$acc;
}
echo?sum(1,?2,?3,?4); ? ?//10
?>

從函數返回一個引用,必須在函數聲明和指派返回值給一個變量時都使用引用運算符 &:

<?php
function?&returns_reference(){
????return?$someref;
}
$newref?=&?returns_reference();
?>

可變函數可以用來實現包括回調函數,函數表在內的一些用途。

匿名函數(Anonymous functions),也叫閉包函數(closures),允許 臨時創建一個沒有指定名稱的函數。最經常用作回調函數(callback)參數的值。當然,也有其它應用的情況。

<?php
echo?preg_replace_callback('~-([a-z])~',?function?($match)?{
????return?strtoupper($match[1]);
},?'hello-world');
//?輸出?helloWorld
?>

閉包函數也可以作為變量的值來使用。PHP 會自動把此種表達式轉換成內置類 Closure 的對象實例。

<?php
$greet?=?function($name){
????printf("Hello?%s\r\n",?$name);
};
$greet('World');
$greet('PHP');
?>

閉包可以從父作用域中繼承變量。 任何此類變量都應該用?use?語言結構傳遞進去。匿名函數目前是通過Closure?類來實現的。

8.類與對象

?

?

?

如果在?new?之后跟著的是一個包含有類名的字符串,則該類的一個實例被創建。如果該類屬于一個名字空間,則必須使用其完整名稱。

在類定義內部,可以用?new self?和?new parent?創建新對象。當把一個對象已經創建的實例賦給一個新變量時,新變量會訪問同一個實例,就和用該對象賦值一樣。此行為和給函數傳遞入實例時一樣??梢杂每寺〗o一個已創建的對象建立一個新實例。

<?php
$instance?=?new?SimpleClass();
$assigned???=??$instance;
$reference??=&?$instance;
$instance->var?=?'$assigned?will?have?this?value';
$instance?=?null;?//?$instance?and?$reference?become?null
var_dump($instance);
var_dump($reference);
var_dump($assigned);
?>
NULL NULL object(SimpleClass)#1 (1) {["var"]=>string(30) "$assigned will have this value" }

被繼承的方法和屬性可以通過用同樣的名字重新聲明被覆蓋。但是如果父類定義方法時使用了 final,則該方法不可被覆蓋。可以通過 parent:: 來訪問被覆蓋的方法或屬性。

當覆蓋方法時,參數必須保持一致否則 PHP 將發出?E_STRICT?級別的錯誤信息。但構造函數例外,構造函數可在被覆蓋時使用不同的參數。

自 PHP 5.5 起,關鍵詞?class?也可用于類名的解析。使用?ClassName::class?你可以獲取一個字符串,包含了類?ClassName?的完全限定名稱。這對使用了 命名空間 的類尤其有用。

<?php
namespace?NS?{
????class?ClassName?{
????}
????echo?ClassName::class; ? ?//NS\ClassName
}
?>

在類的成員方法里面,可以用?->(對象運算符):$this->property(其中?property?是該屬性名)這種方式來訪問非靜態屬性。靜態屬性則是用?::(雙冒號):self::$property?來訪問。當一個方法在類定義內部被調用時,有一個可用的偽變量?$this。$this?是一個到主叫對象的引用(通常是該方法所從屬的對象,但如果是從第二個對象靜態調用時也可能是另一個對象)。

跟 heredocs 不同,nowdocs 可在任何靜態數據上下文中使用,包括屬性聲明。

<?php
class?foo?{
???//?自?5.3.0?起
???public?$bar?=?<<<'EOT'
bar
EOT;
}
?>

常量的值必須是一個定值,不能是變量,類屬性,數學運算的結果或函數調用。和 heredoc 不同,nowdoc 可以用在任何靜態數據中。

<?php
class?foo?{
????//?自?PHP?5.3.0?起
????const?bar?=?<<<'EOT'
bar
EOT;
}
?>

?

可以定義一個?__autoload()?函數,它會在試圖使用尚未被定義的類時自動調用。通過調用此函數,腳本引擎在 PHP 出錯失敗前有了最后一個機會加載所需的類。spl_autoload_register()?提供了一種更加靈活的方式來實現類的自動加載。因此,不再建議使用?__autoload()?函數,在以后的版本中它可能被棄用。如果類名比如被用于?call_user_func(),則它可能包含一些危險的字符,比如?../。 建議您在這樣的函數中不要使用用戶的輸入,起碼需要在?__autoload()?時驗證下輸入。

本例嘗試加載接口?ITest。

<?php
function?__autoload($name)?{
????var_dump($name);
}
class?Foo?implements?ITest?{
}
/*
string(5)?"ITest"
Fatal?error:?Interface?'ITest'?not?found?in?...
*/
?>

本例拋出一個異常并在 try/catch 語句塊中演示。

<?php
function?__autoload($name)?{
????echo?"Want?to?load?$name.\n";
????throw?new?Exception("Unable?to?load?$name.");
}
try?{
????$obj?=?new?NonLoadableClass();
}?catch?(Exception?$e)?{
????echo?$e->getMessage(),?"\n";
}
?>
Want to load NonLoadableClass. Unable to load NonLoadableClass.

如果子類中定義了構造函數則不會隱式調用其父類的構造函數。要執行父類的構造函數,需要在子類的構造函數中調用?parent::__construct()。如果子類沒有定義構造函數則會如同一個普通的類方法一樣從父類繼承(假如沒有被定義為 private 的話)。

為了實現向后兼容性,如果 PHP 5 在類中找不到 __construct() 函數并且也沒有從父類繼承一個的話,它就會嘗試尋找舊式的構造函數,也就是和類同名的函數。和構造函數一樣,父類的析構函數不會被引擎暗中調用。要執行父類的析構函數,必須在子類的析構函數體中顯式調用?parent::__destruct()。此外也和構造函數一樣,子類如果自己沒有定義析構函數則會繼承父類的。析構函數即使在使用?exit()?終止腳本運行時也會被調用。在析構函數中調用?exit()?將會中止其余關閉操作的運行。析構函數在腳本關閉時調用,此時所有的 HTTP 頭信息已經發出。腳本關閉時的工作目錄有可能和在 SAPI(如 apache)中時不同。試圖在析構函數(在腳本終止時被調用)中拋出一個異常會導致致命錯誤。

對屬性或方法的訪問控制,是通過在前面添加關鍵字?public(公有),protected(受保護)或?private(私有)來實現的。被定義為公有的類成員可以在任何地方被訪問。被定義為受保護的類成員則可以被其自身以及其子類和父類訪問。被定義為私有的類成員則只能被其定義所在的類訪問。類屬性必須定義為公有,受保護,私有之一。如果用?var?定義,則被視為公有。

類中的方法可以被定義為公有,私有或受保護。如果沒有設置這些關鍵字,則該方法默認為公有。

同一個類的對象即使不是同一個實例也可以互相訪問對方的私有與受保護成員。這是由于在這些對象的內部具體實現的細節都是已知的。

<?php
class?Test{
????private?$foo;
????public?function?__construct($foo){
????????$this->foo?=?$foo;
????}
????private?function?bar(){
????????echo?'Accessed?the?private?method.';
????}
????public?function?baz(Test?$other){
????????//?We?can change?the?private?property:
????????$other->foo?=?'hello';
????????var_dump($other->foo);
????????//?We?can?also?call?the?private?method:
????????$other->bar();
????}
}
$test?=?new?Test('test');
$test->baz(new?Test('other'));
?>
string(5) "hello" Accessed the private method. 對象繼承:

?

<?php
class?foo{
????public?function?printItem($string)?{
????????echo?'Foo:?'?.?$string?.?PHP_EOL;
????}
????public?function?printPHP(){
????????echo?'PHP?is?great.'?.?PHP_EOL;
????}
}
class?bar?extends?foo{
????public?function?printItem($string){
????????echo?'Bar:?'?.?$string?.?PHP_EOL;
????}
}
$foo?=?new?foo();
$bar?=?new?bar();
$foo->printItem('baz');?//?Output:?'Foo:?baz'
$foo->printPHP();???????//?Output:?'PHP?is?great'?
$bar->printItem('baz');?//?Output:?'Bar:?baz'
$bar->printPHP();???????//?Output:?'PHP?is?great'
?>

范圍解析操作符(::):可以用于訪問靜態成員,類常量,還可以用于覆蓋類中的屬性和方法。當在類定義之外引用到這些項目時,要使用類名。自 PHP 5.3.0 起,可以通過變量來引用類,該變量的值不能是關鍵字(如? ?self,parent?和?static)。

self,parent?和?static?這三個特殊的關鍵字是用于在類定義的內部對其屬性或方法進行訪問的。當一個子類覆蓋其父類中的方法時,PHP 不會調用父類中已被覆蓋的方法。是否調用父類的方法取決于子類。這種機制也作用于構造函數和析構函數,重載以及魔術方法。

?

<?php
class?MyClass{
????protected?function?myFunc()?{
????????echo?"MyClass::myFunc()\n";
????}
}
class?OtherClass?extends?MyClass{????//?覆蓋了父類的定義
????public?function?myFunc(){????????//?但還是可以調用父類中被覆蓋的方法
????????parent::myFunc();
????????echo?"OtherClass::myFunc()\n";
????}
}
$class?=?new?OtherClass();
$class->myFunc();
?>

聲明類屬性或方法為靜態,就可以不實例化類而直接訪問。靜態屬性不能通過一個類已實例化的對象來訪問(但靜態方法可以)。

由于靜態方法不需要通過對象即可調用,所以偽變量?$this?在靜態方法中不可用。靜態屬性不可以由對象通過 -> 操作符來訪問。

用靜態方式調用一個非靜態方法會導致一個?E_STRICT?級別的錯誤。就像其它所有的 PHP 靜態變量一樣,靜態屬性只能被初始化為文字或常量,不能使用表達式。所以可以把靜態屬性初始化為整數或數組,但不能初始化為另一個變量或函數返回值,也不能指向一個對象。

自 PHP 5.3.0 起,可以用一個變量來動態調用類。但該變量的值不能為關鍵字?self,parent?或?static。

定義為抽象的類不能被實例化。任何一個類,如果它里面至少有一個方法是被聲明為抽象的,那么這個類就必須被聲明為抽象的。被定義為抽象的方法只是聲明了其調用方式(參數),不能定義其具體的功能實現。繼承一個抽象類的時候,子類必須定義父類中的所有抽象方法;另外,這些方法的訪問控制必須和父類中一樣(或者更為寬松)。

<?php
abstract?class?AbstractClass{
????//?我們的抽象方法僅需要定義需要的參數
????abstract?protected?function?prefixName($name);
}
class?ConcreteClass?extends?AbstractClass{
????//?我們的子類可以定義父類簽名中不存在的可選參數
????public?function?prefixName($name,?$separator?=?".")?{
????????if?($name?==?"Pacman")?{
????????????$prefix?=?"Mr";
????????}?elseif?($name?==?"Pacwoman")?{
????????????$prefix?=?"Mrs";
????????}?else?{
????????????$prefix?=?"";
????????}
????????return?"{$prefix}{$separator}?{$name}";
????}
}
$class?=?new?ConcreteClass;
echo?$class->prefixName("Pacman"),?"\n";
echo?$class->prefixName("Pacwoman"),?"\n";
?>

?

Mr. Pacman Mrs. Pacwoman

使用接口(interface),可以指定某個類必須實現哪些方法,但不需要定義這些方法的具體內容。接口中定義的所有方法都必須是公有,這是接口的特性。要實現一個接口,使用?implements?操作符。類中必須實現接口中定義的所有方法,否則會報一個致命錯誤。類可以實現多個接口,用逗號來分隔多個接口的名稱。接口也可以繼承,通過使用?extends?操作符。接口中也可以定義常量。接口常量和類常量的使用完全相同,但是不能被子類或子接口所覆蓋。接口加上類型約束,提供了一種很好的方式來確保某個對象包含有某些方法。

<?php
interface?a{
????const?b?=?'Interface?constant';
}
echo?a::b; ? ?//?輸出接口常量
class?b?implements?a{
????const?b?=?'Class?constant'; ? ?//?錯誤寫法,因為常量不能被覆蓋。接口常量的概念和類常量是一樣的。
}
?>

Traits 是一種為類似 PHP 的單繼承語言而準備的代碼復用機制。Trait 為了減少單繼承語言的限制,使開發人員能夠自由地在不同層次結構內獨立的類中復用方法集。Traits 和類組合的語義是定義了一種方式來減少復雜性,避免傳統多繼承和混入類(Mixin)相關的典型問題。

?

Trait 和一個類相似,但僅僅旨在用細粒度和一致的方式來組合功能。Trait 不能通過它自身來實例化。它為傳統繼承增加了水平特性的組合;也就是說,應用類的成員不需要繼承。

<?php
trait?ezcReflectionReturnInfo?{
????function?getReturnType()?{?/*1*/?}
????function?getReturnDescription()?{?/*2*/?}
}
class?ezcReflectionMethod?extends?ReflectionMethod?{
????use?ezcReflectionReturnInfo;
????/*?...?*/
}
class?ezcReflectionFunction?extends?ReflectionFunction?{
????use?ezcReflectionReturnInfo;
????/*?...?*/
}
?>

從基類繼承的成員被 trait 插入的成員所覆蓋。優先順序是來自當前類的成員覆蓋了 trait 的方法,而 trait 則覆蓋了被繼承的方法。

從基類繼承的成員被插入的 SayWorld Trait 中的 MyHelloWorld 方法所覆蓋。其行為 MyHelloWorld 類中定義的方法一致。優先順序是當前類中的方法會覆蓋 trait 方法,而 trait 方法又覆蓋了基類中的方法。

<?php
class?Base?{
????public?function?sayHello()?{
????????echo?'Hello?';
????}
}
trait?SayWorld?{
????public?function?sayHello()?{
????????parent::sayHello();
????????echo?'World!';
????}
}
class?MyHelloWorld?extends?Base?{
????use?SayWorld;
}
$o?=?new?MyHelloWorld();
$o->sayHello();//Hello World!
?>

通過逗號分隔,在 use 聲明列出多個 trait,可以都插入到一個類中。

<?php
trait?Hello?{
????public?function?sayHello()?{
????????echo?'Hello?';
????}
}
trait?World?{
????public?function?sayWorld()?{
????????echo?'World';
????}
}
class?MyHelloWorld?{
????use?Hello,?World;
????public?function?sayExclamationMark()?{
????????echo?'!';
????}
}
$o?=?new?MyHelloWorld();
$o->sayHello();
$o->sayWorld();
$o->sayExclamationMark();//Hello World!
?>

如果兩個 trait 都插入了一個同名的方法,如果沒有明確解決沖突將會產生一個致命錯誤。為了解決多個 trait 在同一個類中的命名沖突,需要使用?insteadof?操作符來明確指定使用沖突方法中的哪一個。以上方式僅允許排除掉其它方法,as?操作符可以將其中一個沖突的方法以另一個名稱來引入。

正如類能夠使用 trait 一樣,其它 trait 也能夠使用 trait。在 trait 定義時使用一個或多個 trait,它能夠組合其它 trait 中的部分或全部成員。

<?php
trait?Hello?{
????public?function?sayHello()?{
????????echo?'Hello?';
????}
}
trait?World?{
????public?function?sayWorld()?{
????????echo?'World!';
????}
}
trait?HelloWorld?{
????use?Hello,?World;
}
class?MyHelloWorld?{
????use?HelloWorld;
}
$o?=?new?MyHelloWorld();
$o->sayHello();
$o->sayWorld();//Hello World!
?>

為了對使用的類施加強制要求,trait 支持抽象方法的使用。

<?php
trait?Hello?{
????public?function?sayHelloWorld()?{
????????echo?'Hello'.$this->getWorld();
????}
????abstract?public?function?getWorld();
}
class?MyHelloWorld?{
????private?$world;
????use?Hello;
????public?function?getWorld()?{
????????return?$this->world;
????}
????public?function?setWorld($val)?{
????????$this->world?=?$val;
????}
}
?>

Traits 可以被靜態成員靜態方法定義。

<?php
trait?Counter?{
????public?function?inc()?{
????????static?$c?=?0;
????????$c?=?$c?+?1;
????????echo?"$c\n";
????}
}
class?C1?{
????use?Counter;
}
class?C2?{
????use?Counter;
}
$o?=?new?C1();?$o->inc();?//?echo?1
$p?=?new?C2();?$p->inc();?//?echo?1
?>

Trait 同樣可以定義屬性。

<?php
trait?PropertiesTrait?{
????public?$x?=?1;
}
class?PropertiesExample?{
????use?PropertiesTrait;
}
$example?=?new?PropertiesExample;
$example->x;
?>

如果 trait 定義了一個屬性,那類將不能定義同樣名稱的屬性,否則會產生一個錯誤。如果該屬性在類中的定義與在 trait 中的定義兼容(同樣的可見性和初始值)則錯誤的級別是?E_STRICT,否則是一個致命錯誤。

<?php
trait?PropertiesTrait?{
????public?$same?=?true;
????public?$different?=?false;
}
class?PropertiesExample?{
????use?PropertiesTrait;
????public?$same?=?true;?//?Strict?Standards
????public?$different?=?true;?//?致命錯誤
}
?>

當調用當前環境下未定義或不可見的類屬性或方法時,重載方法會被調用。所有的重載方法都必須被聲明為?public。PHP中的"重載"與其它絕大多數面向對象語言不同。傳統的"重載"是用于提供多個同名的類方法,但各方法的參數類型和個數不同。

屬性重載只能在對象中進行。在靜態方法中,這些魔術方法將不會被調用。所以這些方法都不能被 聲明為 static

publicvoid__set?(?string$name?,?mixed$value?) publicmixed__get?(?string$name?) publicbool__isset?(?string$name?) publicvoid__unset?(?string$name?)

在給不可訪問屬性賦值時,__set() 會被調用。

讀取不可訪問屬性的值時,__get() 會被調用。

當對不可訪問屬性調用?isset()?或?empty()?時,__isset()會被調用。

當對不可訪問屬性調用?unset()?時,__unset()會被調用。

參數?$name?是指要操作的變量名稱。__set()方法的?$value?參數指定了?$name?變量的值。

在除?isset()外的其它語言結構中無法使用重載的屬性,這意味著當對一個重載的屬性使用?empty()?時,重載魔術方法將不會被調用。為避開此限制,必須將重載屬性賦值到本地變量再使用?empty()。

方法重載:

?

publicmixed__call?(?string$name?,?array$arguments?) public staticmixed__callStatic?(?string$name?,?array$arguments?)

在對象中調用一個不可訪問方法時,__call() 會被調用。

用靜態方式中調用一個不可訪問方法時,__callStatic() 會被調用。

$name?參數是要調用的方法名稱。$arguments參數是一個枚舉數組,包含著要傳遞給方法?$name?的參數。

PHP 5 提供了一種定義對象的方法使其可以通過單元列表來遍歷,例如用 foreach語句。默認情況下,所有可見屬性都將被用于遍歷。foreach?遍歷了所有其能夠訪問的可見屬性。

<?php
class?MyClass{
public?$var1?=?'value 1';
public?$var2?=?'value 2';
public?$var3?=?'value 3';
protected?$protected?=?'protected var';
private?$private?=?'private var';
function?iterateVisible() {
? ? echo?"MyClass::iterateVisible:\n";
? ? foreach($this?as?$key?=>?$value) {
? ? ? ? print?"$key?=>?$value\n";
? ? ? ? }
? ? }
}
$class?= new?MyClass();
foreach($class?as?$key?=>?$value) {
? ? print?"$key?=>?$value\n";
}
echo?"\n";
$class->iterateVisible();
?> var1 => value 1 var2 => value 2 var3 => value 3MyClass::iterateVisible: var1 => value 1 var2 => value 2 var3 => value 3 protected => protected var private => private var

更進一步,可以實現?Iterator接口??梢宰寣ο笞孕袥Q定如何遍歷以及每次遍歷時那些值可用??梢杂?IteratorAggregate接口以替代實現所有的?Iterator?方法。IteratorAggregate只需要實現一個方法IteratorAggregate::getIterator(),其應返回一個實現了?Iterator?的類的實例。

9.類與對象:魔術方法

__construct(), __destruct(), __call(), __callStatic(), __get(), __set(), __isset(), __unset(), __sleep(), __wakeup(), __toString(), __invoke(), __set_state(), __clone() 和 __debugInfo()等方法在 PHP 中被稱為"魔術方法"(Magic methods)。在命名自己的類方法時不能使用這些方法名,除非是想使用其魔術功能。

publicarray__sleep?(?void?) void__wakeup?(?void?)

serialize()?函數會檢查類中是否存在一個魔術方法 __sleep()。如果存在,該方法會先被調用,然后才執行序列化操作。此功能可以用于清理對象,并返回一個包含對象中所有應被序列化的變量名稱的數組。如果該方法未返回任何內容,則?NULL?被序列化,并產生一個?E_NOTICE?級別的錯誤。__sleep()?不能返回父類的私有成員的名字。這樣做會產生一個?E_NOTICE?級別的錯誤??梢杂?Serializable?接口來替代。__sleep()?方法常用于提交未提交的數據,或類似的清理操作。同時,如果有一些很大的對象,但不需要全部保存,這個功能就很好用。與之相反,unserialize()?會檢查是否存在一個?__wakeup()方法。如果存在,則會先調用?__wakeup?方法,預先準備對象需要的資源。__wakeup()?經常用在反序列化操作中,例如重新建立數據庫連接,或執行其它初始化操作。

<?php
class?Connection?{
protected?$link;
private?$server,?$username,?$password,?$db;
public function?__construct($server,?$username,?$password,?$db){
$this->server?=?$server;
$this->username?=?$username;
$this->password?=?$password;
$this->db?=?$db;
$this->connect();
}
private function?connect(){
$this->link?=?mysql_connect($this->server,?$this->username,?$this->password);
mysql_select_db($this->db,?$this->link);
}
public function?__sleep(){
return array('server',?'username',?'password',?'db');
}
public function?__wakeup(){
$this->connect();
}
}
?> publicstring__toString?(?void?)

__toString() 方法用于一個類被當成字符串時應怎樣回應。例如?echo $obj;?應該顯示些什么。此方法必須返回一個字符串,否則將發出一條?E_RECOVERABLE_ERROR?級別的致命錯誤。不能在?__toString()方法中拋出異常。這么做會導致致命錯誤。

<?php
class?TestClass{
public?$foo;
public function?__construct($foo) {
$this->foo?=?$foo;
}
public function?__toString() {
return?$this->foo;
? ? }
}
$class?= new?TestClass('Hello');
echo?$class; ? ?//Hello
?> mixed__invoke?([?$...?] )

當嘗試以調用函數的方式調用一個對象時,__invoke() 方法會被自動調用。

<?php
class?CallableClass?{
? ? function?__invoke($x) {
? ? var_dump($x); ? ?//int(5)
? ? }
}
$obj?= new?CallableClass;
$obj(5);
var_dump(is_callable($obj)); ? ?//bool(true)
?> staticobject__set_state?(?array$properties?)

自 PHP 5.1.0 起當調用?var_export()?導出類時,此靜態 方法會被調用。本方法的唯一參數是一個數組,其中包含按?array('property' => value, ...)?格式排列的類屬性。

<?php
class?A{
public?$var1;
public?$var2;
public static function?__set_state($an_array)?// As of PHP 5.1.0{
? ? $obj?= new?A;
? ? $obj->var1?=?$an_array['var1'];
? ? $obj->var2?=?$an_array['var2'];
? ? return?$obj;
? ? }
}
$a?= new?A;
$a->var1?=?5;
$a->var2?=?'foo';
eval('$b = '?.?var_export($a,?true) .?';');?
var_dump($b);
?> object(A)#2 (2) {["var1"]=>int(5)["var2"]=>string(3) "foo" }

__debugInfo()

<?php
class?C?{
private?$prop;
public function?__construct($val) {
$this->prop?=?$val;
}
public function?__debugInfo() {
return [
'propSquared'?=>?$this->prop?**?2,
? ? ? ? ];
? ? }
}
var_dump(new?C(42));
?> object(C)#1 (1) {["propSquared"]=>int(1764) }

Final 關鍵字:如果父類中的方法被聲明為 final,則子類無法覆蓋該方法。如果一個類被聲明為 final,則不能被繼承。屬性不能被定義為 final,只有類和方法才能被定義為 final。

?

對象復制可以通過 clone 關鍵字來完成(如果可能,這將調用對象的 __clone() 方法)。對象中的 __clone() 方法不能被直接調用。$copy_of_object = clone $object;當對象被復制后,PHP 5 會對對象的所有屬性執行一個淺復制(shallow copy)。所有的引用屬性 仍然會是一個指向原來的變量的引用。void__clone?(?void?)當復制完成時,如果定義了?__clone()方法,則新創建的對象(復制生成的對象)中的?__clone()方法會被調用,可用于修改屬性的值(如果有必要的話)。

對象比較:當使用比較運算符(==)比較兩個對象變量時,比較的原則是:如果兩個對象的屬性和屬性值 都相等,而且兩個對象是同一個類的實例,那么這兩個對象變量相等。而如果使用全等運算符(===),這兩個對象變量一定要指向某個類的同一個實例(即同一個對象)。

類型約束:函數的參數可以指定必須為對象(在函數原型里面指定類的名字),接口,數組(PHP 5.1 起)或者?callable(PHP 5.4 起)。不過如果使用?NULL作為參數的默認值,那么在調用函數的時候依然可以使用?NULL?作為實參。如果一個類或接口指定了類型約束,則其所有的子類或實現也都如此。類型約束不能用于標量類型如?int?或?string。Traits?也不允許。

?

函數調用的參數與定義的參數類型不一致時,會拋出一個可捕獲的致命錯誤。類型約束允許 NULL 值:

<?php
/* 接受 NULL 值 */
function?test(stdClass $obj?=?NULL) { ? ?}
test(NULL);
test(new?stdClass);
?> 后期靜態綁定:后期綁定"的意思是說,static::不再被解析為定義當前方法所在的類,而是在實際運行時計算的。也可以稱之為"靜態綁定",因為它可以用于(但不限于)靜態方法的調用。

?

?

使用?self::?或者?__CLASS__?對當前類的靜態引用,取決于定義當前方法所在的類:

<?php
class?A?{
public static function?who() {
? ? echo?__CLASS__;
}
public static function?test() {
? ? self::who();
? ? }
}
class?B?extends?A?{
public static function?who() {
? ? echo?__CLASS__;
? ? }
}
B::test(); ? ?//A
?> <?php
class?A?{
public static function?who() {
? ? echo?__CLASS__;
}
public static function?test() {
? ? static::who();?// 后期靜態綁定從這里開始
? ? }
}
class?B?extends?A?{
public static function?who() {
? ? echo?__CLASS__;
? ? }
}
B::test(); ? ?//B
?>

?

?

在非靜態環境下,所調用的類即為該對象實例所屬的類。由于?$this->會在同一作用范圍內嘗試調用私有方法,而?static::則可能給出不同結果。另一個區別是?static::?只能用于靜態屬性。

?

?

<?php
class?A?{
private function?foo() {
? ? echo?"success!\n";
}
public function?test() {
? ? $this->foo();
? ? static::foo();
? ? }
}
class?B?extends?A?{
/* foo() will be copied to B, hence its scope will still be A and
* the call be successful */
}
class?C?extends?A?{
private function?foo() {
? ? /* original method is replaced; the scope of the new one is C */
? ? }
}
$b?= new?B();
$b->test();
$c?= new?C();
$c->test();?//fails
?> success! success! success! Fatal error: Call to private method C::foo() from context 'A' in /tmp/test.php on line 9

?

?

后期靜態綁定的解析會一直到取得一個完全解析了的靜態調用為止。另一方面,如果靜態調用使用?parent::?或者?self::?將轉發調用信息。

<?php

class?A?{

public static function?foo() {

? ? static::who();

}

public static function?who() {

? ? echo?__CLASS__."\n";

? ? }

}

class?B?extends?A?{

? ? public static function?test() {

? ? ? ? A::foo();

? ? ? ? parent::foo();

? ? ? ? self::foo();

? ? }

? ? public static function?who() {

? ? ? ? echo?__CLASS__."\n";

? ? }

}

class?C?extends?B?{

? ? public static function?who() {

? ? ? ? echo?__CLASS__."\n";

? ? }

}

C::test(); ? ? ? ?//會輸出:A C C

?>

?

?

php的引用是別名,就是兩個不同的變量名字指向相同的內容。在php5,一個對象變量已經不再保存整個對象的值。只是保存一個標識符來訪問真正的對象內容。 當對象作為參數傳遞,作為結果返回,或者賦值給另外一個變量,另外一個變量跟原來的不是引用的關系,只是他們都保存著同一個標識符的拷貝,這個標識符指向同一個對象的真正內容。

<?php
class?A?{?public?$foo?=?1;}?
$a?= new?A;
$b?=?$a;?// $a ,$b都是同一個標識符的拷貝?// ($a) = ($b) = <id>
$b->foo?=?2;
echo?$a->foo."\n"; ? ?//2
$c?= new?A;
$d?= &$c;?// $c ,$d是引用?// ($c,$d) = <id>
$d->foo?=?2;
echo?$c->foo."\n"; ? ?//2
$e?= new?A;
function?foo($obj) {?$obj->foo?=?2;}// ($obj) = ($e) = <id>
foo($e);
echo?$e->foo."\n"; ? ?//2
?>

所有php里面的值都可以使用函數serialize()來返回一個包含字節流的字符串來表示。unserialize()函數能夠重新把字符串變回php原來的值。 序列化一個對象將會保存對象的所有變量,但是不會保存對象的方法,只會保存類的名字。

為了能夠unserialize()一個對象,這個對象的類必須已經定義過。如果序列化類A的一個對象,將會返回一個跟類A相關,而且包含了對象所有變量值的字符串。 如果要想在另外一個文件中解序列化一個對象,這個對象的類必須在解序列化之前定義,可以通過包含一個定義該類的文件或使用函數spl_autoload_register()來實現。

<?php
// classa.inc:
class?A?{
public?$one?=?1;
public function?show_one() {
? ? echo?$this->one;
? ? }
}
// page1.php:
include("classa.inc");
$a?= new?A;
$s?=?serialize($a);
file_put_contents('store',?$s); ? ?// 把變量$s保存起來以便文件page2.php能夠讀到
// page2.php:
include("classa.inc"); ? ?// 要正確了解序列化,必須包含下面一個文件
$s?=?file_get_contents('store');
$a?=?unserialize($s);
$a->show_one(); ? ?// 現在可以使用對象$a里面的函數 show_one()
?>

在應用程序中序列化對象以便在之后使用,強烈推薦在整個應用程序都包含對象的類的定義。 不然有可能出現在解序列化對象的時候,沒有找到該對象的類的定義,從而把沒有方法的類__PHP_Incomplete_Class_Name作為該對象的類,導致返回一個沒有用的對象。所以在上面的例子中,當運行session_register("a"),把變量$a放在會話里之后,需要在每個頁面都包含文件classa.inc,而不是只有文件page1.php和page2.php。

10.命名空間

?

?

在PHP中,命名空間用來解決在編寫類庫或應用程序時創建可重用的代碼如類或函數時碰到的兩類問題:

?

?

  • 用戶編寫的代碼與PHP內部的類/函數/常量或第三方類/函數/常量之間的名字沖突。
  • 為很長的標識符名稱(通常是為了緩解第一類問題而定義的)創建一個別名(或簡短)的名稱,提高源代碼的可讀性。
  • 雖然任意合法的PHP代碼都可以包含在命名空間中,但只有三種類型的代碼受命名空間的影響,它們是:類,函數和常量。

    命名空間通過關鍵字namespace來聲明。如果一個文件中包含命名空間,它必須在其它所有代碼之前聲明命名空間。

    聲明單個命名空間:

    <?php
    namespace?MyProject;
    const?CONNECT_OK?=?1;
    class?Connection?{?/* ... */?}
    function?connect() {?/* ... */?}
    ?> 在聲明命名空間之前唯一合法的代碼是用于定義源文件編碼方式的?declare語句。另外,所有非 PHP 代碼包括空白符都不能出現在命名空間的聲明之前。允許將同一個命名空間的內容分割存放在不同的文件中。

    PHP 命名空間也允許指定層次化的命名空間的名稱。聲明分層次的單個命名空間:

    <?php
    namespace?MyProject\Sub\Level;
    const?CONNECT_OK?=?1;
    class?Connection?{?/* ... */?}
    function?connect() {?/* ... */?}
    ?> 上面的例子創建了常量MyProject\Sub\Level\CONNECT_OK,類?MyProject\Sub\Level\Connection和函數? ?MyProject\Sub\Level\Connection。

    也可以在同一個文件中定義多個命名空間。定義多個命名空間,簡單組合語法(不建議):

    <?php
    namespace?MyProject;
    const?CONNECT_OK?=?1;
    class?Connection?{?/* ... */?}
    function?connect() {?/* ... */?}

    namespace?AnotherProject;
    const?CONNECT_OK?=?1;
    class?Connection?{?/* ... */?}
    function?connect() {?/* ... */?}
    ?>

    定義多個命名空間,大括號語法:

    <?php
    namespace?MyProject?{
    const?CONNECT_OK?=?1;
    class?Connection?{?/* ... */?}
    function?connect() {?/* ... */?}
    }

    namespace?AnotherProject?{
    const?CONNECT_OK?=?1;
    class?Connection?{?/* ... */?}
    function?connect() {?/* ... */?}
    }
    ?>

    將全局的非命名空間中的代碼與命名空間中的代碼組合在一起,只能使用大括號形式的語法。全局代碼必須用一個不帶名稱的 namespace 語句加上大括號括起來:

    <?php
    namespace?MyProject?{
    const?CONNECT_OK?=?1;
    class?Connection?{?/* ... */?}
    function?connect() {?/* ... */?}
    }
    namespace {?// global code
    session_start();
    $a?=?MyProject\connect();
    echo?MyProject\Connection::start();
    }
    ?>

    定義多個命名空間和不包含在命名空間中的代碼:

    <?php
    declare(encoding='UTF-8');
    namespace?MyProject?{
    const?CONNECT_OK?=?1;
    class?Connection?{?/* ... */?}
    function?connect() {?/* ... */?}
    }
    namespace {?// 全局代碼
    session_start();
    $a?=?MyProject\connect();
    echo?MyProject\Connection::start();
    }
    ?>

    在文件系統中訪問一個文件有三種方式:

    <?php
    namespace?Foo\Bar\subnamespace;
    const?FOO?=?1;
    function?foo() {}
    class?foo{?static function?staticmethod() {}?}
    ?> <?php
    namespace?Foo\Bar;
    include?'file1.php';
    const?FOO?=?2;
    function?foo() {}
    class?foo{?static function?staticmethod() {}?}
    /* 非限定名稱 */
    foo();?// 解析為 Foo\Bar\foo resolves to function Foo\Bar\foo
    foo::staticmethod();?// 解析為類 Foo\Bar\foo的靜態方法staticmethod。resolves to class Foo\Bar\foo, method staticmethod
    echo?FOO;?// resolves to constant Foo\Bar\FOO
    /* 限定名稱 */
    subnamespace\foo();?// 解析為函數 Foo\Bar\subnamespace\foo
    subnamespace\foo::staticmethod();?// 解析為類 Foo\Bar\subnamespace\foo,
    // 以及類的方法 staticmethod
    echo?subnamespace\FOO;?// 解析為常量 Foo\Bar\subnamespace\FOO
    /* 完全限定名稱 */
    \Foo\Bar\foo();?// 解析為函數 Foo\Bar\foo
    \Foo\Bar\foo::staticmethod();?// 解析為類 Foo\Bar\foo, 以及類的方法 staticmethod
    echo \Foo\Bar\FOO;?// 解析為常量 Foo\Bar\FOO
    ?>

    注意訪問任意全局類、函數或常量,都可以使用完全限定名稱,例如?\strlen()?或?\Exception?或?\INI_ALL。

    <?php
    namespace?Foo;
    function?strlen() {}
    const?INI_ALL?=?3;
    class?Exception?{}
    $a?= \strlen('hi');?// 調用全局函數strlen
    $b?= \INI_ALL;?// 訪問全局常量 INI_ALL
    $c?= new \Exception('error');?// 實例化全局類 Exception
    ?>

    PHP 命名空間的實現受到其語言自身的動態特征的影響。

    <?php
    class?classname{?function?__construct(){?echo?__METHOD__,"\n";?}?}
    function?funcname(){?echo?__FUNCTION__,"\n";?}
    const?constname?=?"global";
    $a?=?'classname';
    $obj?= new?$a;?// prints classname::__construct
    $b?=?'funcname';
    $b();?// prints funcname
    echo?constant('constname'),?"\n";?// prints global
    ?> 必須使用完全限定名稱(包括命名空間前綴的類名稱)。注意因為在動態的類名稱、函數名稱或常量名稱中,限定名稱和完全限定名稱沒有區別,因此其前導的反斜杠是不必要的。動態訪問命名空間的元素: <?php
    namespace?namespacename;
    class?classname{?function?__construct()?{?echo?__METHOD__,"\n";?}?}
    function?funcname()?{?echo?__FUNCTION__,"\n";?}
    const?constname?=?"namespaced";
    include?'example1.php';
    $a?=?'classname';
    $obj?= new?$a;?// prints classname::__construct
    $b?=?'funcname';
    $b();?// prints funcname
    echo?constant('constname'),?"\n";?// prints global
    /* note that if using double quotes, "\\namespacename\\classname" must be used */
    $a?=?'\namespacename\classname';
    $obj?= new?$a;?// prints namespacename\classname::__construct
    $a?=?'namespacename\classname';
    $obj?= new?$a;?// also prints namespacename\classname::__construct
    $b?=?'namespacename\funcname';
    $b();?// prints namespacename\funcname
    $b?=?'\namespacename\funcname';
    $b();?// also prints namespacename\funcname
    echo?constant('\namespacename\constname'),?"\n";?// prints namespaced
    echo?constant('namespacename\constname'),?"\n";?// also prints namespaced
    ?> PHP支持兩種抽象的訪問當前命名空間內部元素的方法,__NAMESPACE__魔術常量和namespace關鍵字。 常量__NAMESPACE__的值是包含當前命名空間名稱的字符串。在全局的,不包括在任何命名空間中的代碼,它包含一個空的字符串。常量?__NAMESPACE__?在動態創建名稱時很有用。 <?php
    namespace?MyProject;
    echo?'"',?__NAMESPACE__,?'"';?// 輸出 "MyProject"
    ?> <?php
    namespace?MyProject;
    function?get($classname){
    ? ? $a?=?__NAMESPACE__?.?'\\'?.?$classname;
    ? ? return new?$a;
    }
    ?>

    關鍵字?namespace?可用來顯式訪問當前命名空間或子命名空間中的元素。它等價于類中的?self?操作符。

    <?php
    namespace?MyProject;
    use?blah\blah?as?mine;?// see "Using namespaces: importing/aliasing"
    blah\mine();?// calls function MyProject\blah\mine()
    namespace\blah\mine();?// calls function MyProject\blah\mine()
    namespace\func();?// calls function MyProject\func()
    namespace\sub\func();?// calls function MyProject\sub\func()
    namespace\cname::method();?// calls static method "method" of class MyProject\cname
    $a?= new namespace\sub\cname();?// instantiates object of class MyProject\sub\cname
    $b?= namespace\CONSTANT;?// assigns value of constant MyProject\CONSTANT to $b
    ?>

    允許通過別名引用或導入外部的完全限定名稱,是命名空間的一個重要特征。這有點類似于在類 unix 文件系統中可以創建對其它的文件或目錄的符號連接。為類名稱使用別名,或為命名空間名稱使用別名。注意PHP不支持導入函數或常量。

    在PHP中,別名是通過操作符?use?來實現的.

    <?php
    namespace?foo;
    use?My\Full\Classname?as?Another;
    // 下面的例子與 use My\Full\NSname as NSname 相同
    use?My\Full\NSname;
    // 導入一個全局類
    use \ArrayObject;
    $obj?= new namespace\Another;?// 實例化 foo\Another 對象
    $obj?= new?Another;?// 實例化 My\Full\Classname 對象
    NSname\subns\func();?// 調用函數 My\Full\NSname\subns\func
    $a?= new?ArrayObject(array(1));?// 實例化 ArrayObject 對象
    // 如果不使用 "use \ArrayObject" ,則實例化一個 foo\ArrayObject 對象
    ?> 注意對命名空間中的名稱(包含命名空間分隔符的完全限定名稱如?Foo\Bar以及相對的不包含命名空間分隔符的全局名稱如?FooBar)來說,前導的反斜杠是不必要的也不允許有反斜杠,因為導入的名稱必須是完全限定的,不會根據當前的命名空間作相對解析。通過use操作符導入/使用別名,一行中包含多個use語句: <?php
    use?My\Full\Classname?as?Another,?My\Full\NSname;
    $obj?= new?Another;?// 實例化一個 My\Full\Classname 對象
    $a?=?'Another';
    $obj?= new?$a;?// 實際化一個 Another 對象
    ?>

    另外,導入操作只影響非限定名稱和限定名稱。完全限定名稱由于是確定的,故不受導入的影響。

    <?php
    use?My\Full\Classname?as?Another,?My\Full\NSname;
    $obj?= new?Another;?// instantiates object of class My\Full\Classname
    $obj?= new \Another;?// instantiates object of class Another
    $obj?= new?Another\thing;?// instantiates object of class My\Full\Classname\thing
    $obj?= new \Another\thing;?// instantiates object of class Another\thing
    ?>

    如果沒有定義任何命名空間,所有的類與函數的定義都是在全局空間,在名稱前加上前綴?\表示該名稱是全局空間中的名稱,即使該名稱位于其它的命名空間中時也是如此。

    <?php
    namespace?A\B\C;
    /* 這個函數是 A\B\C\fopen */
    function?fopen() {?
    /* ... */
    $f?= \fopen(...);?// 調用全局的fopen函數
    return?$f;
    }?
    ?>

    ?

    在一個命名空間中,當 PHP 遇到一個非限定的類、函數或常量名稱時,它使用不同的優先策略來解析該名稱。類名稱總是解析到當前命名空間中的名稱。因此在訪問系統內部或不包含在命名空間中的類名稱時,必須使用完全限定名稱。

    <?php
    namespace?A\B\C;
    class?Exception?extends \Exception?{}
    $a?= new?Exception('hi');?// $a 是類 A\B\C\Exception 的一個對象
    $b?= new \Exception('hi');?// $b 是類 Exception 的一個對象
    $c?= new?ArrayObject;?// 致命錯誤, 找不到 A\B\C\ArrayObject 類
    ?>

    對于函數和常量來說,如果當前命名空間中不存在該函數或常量,PHP 會退而使用全局空間中的函數或常量。

    <?php
    namespace?A\B\C;
    const?E_ERROR?=?45;
    function?strlen($str){
    ? ? return \strlen($str) -?1;
    }
    echo?E_ERROR,?"\n";?// 輸出 "45"
    echo?INI_ALL,?"\n";?// 輸出 "7" - 使用全局常量 INI_ALL
    echo?strlen('hi'),?"\n";?// 輸出 "1"
    if (is_array('hi')) {?// 輸出 "is not array"
    ? ? echo?"is array\n";
    } else {
    ? ? echo?"is not array\n";
    }
    ?> 命名空間名稱定義: 非限定名稱Unqualified name,例如?Foo;限定名稱Qualified name,例如?Foo\Bar完全限定名稱Fully qualified name,例如?\Foo\Bar。?namespace\Foo?也是一個完全限定名稱。 <?php
    namespace?A;
    use?B\D,?C\E?as?F;
    // 函數調用
    foo();?// 首先嘗試調用定義在命名空間"A"中的函數foo()
    // 再嘗試調用全局函數 "foo"
    \foo();?// 調用全局空間函數 "foo"?
    my\foo();?// 調用定義在命名空間"A\my"中函數 "foo"?
    F();?// 首先嘗試調用定義在命名空間"A"中的函數 "F"?
    // 再嘗試調用全局函數 "F"
    // 類引用
    new?B();?// 創建命名空間 "A" 中定義的類 "B" 的一個對象
    // 如果未找到,則嘗試自動裝載類 "A\B"
    new?D();?// 使用導入規則,創建命名空間 "B" 中定義的類 "D" 的一個對象
    // 如果未找到,則嘗試自動裝載類 "B\D"
    new?F();?// 使用導入規則,創建命名空間 "C" 中定義的類 "E" 的一個對象
    // 如果未找到,則嘗試自動裝載類 "C\E"
    new \B();?// 創建定義在全局空間中的類 "B" 的一個對象
    // 如果未發現,則嘗試自動裝載類 "B"
    new \D();?// 創建定義在全局空間中的類 "D" 的一個對象
    // 如果未發現,則嘗試自動裝載類 "D"
    new \F();?// 創建定義在全局空間中的類 "F" 的一個對象
    // 如果未發現,則嘗試自動裝載類 "F"
    // 調用另一個命名空間中的靜態方法或命名空間函數
    B\foo();?// 調用命名空間 "A\B" 中函數 "foo"
    B::foo();?// 調用命名空間 "A" 中定義的類 "B" 的 "foo" 方法
    // 如果未找到類 "A\B" ,則嘗試自動裝載類 "A\B"
    D::foo();?// 使用導入規則,調用命名空間 "B" 中定義的類 "D" 的 "foo" 方法
    // 如果類 "B\D" 未找到,則嘗試自動裝載類 "B\D"
    \B\foo();?// 調用命名空間 "B" 中的函數 "foo"?
    \B::foo();?// 調用全局空間中的類 "B" 的 "foo" 方法
    // 如果類 "B" 未找到,則嘗試自動裝載類 "B"
    // 當前命名空間中的靜態方法或函數
    A\B::foo();?// 調用命名空間 "A\A" 中定義的類 "B" 的 "foo" 方法
    // 如果類 "A\A\B" 未找到,則嘗試自動裝載類 "A\A\B"
    \A\B::foo();?// 調用命名空間 "A\B" 中定義的類 "B" 的 "foo" 方法
    // 如果類 "A\B" 未找到,則嘗試自動裝載類 "A\B"
    ?>

    FAQ: things you need to know about namespaces

    ?

    轉載于:https://www.cnblogs.com/echohao/p/4715425.html

    總結

    以上是生活随笔為你收集整理的PHP中文手册1的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    9999激情| 激情视频91 | 99视频在线精品国自产拍免费观看 | 久久不射电影网 | 视频二区在线视频 | 中文字幕之中文字幕 | 激情五月婷婷 | 日韩性xxx | 全黄网站 | 国产高清av | 欧美日韩一区二区三区免费视频 | 国产一区二区三区四区在线 | 中文字幕刺激在线 | 日韩精品中文字幕av | 在线观看91视频 | www亚洲视频 | 亚洲精品理论 | 91亚洲在线观看 | 色婷婷久久久综合中文字幕 | 亚洲综合色丁香婷婷六月图片 | www夜夜操com| 国产免费久久 | 天天操天天操天天操天天 | av免费电影在线观看 | 国产三级国产精品国产专区50 | 久草视频免费看 | 国产精品久久99综合免费观看尤物 | 韩国精品福利一区二区三区 | 在线精品在线 | 欧美性成人| 丰满少妇在线观看 | 九九视频网站 | 免费三级a | 久久免费99 | 国产人成在线视频 | 国产高清av在线播放 | 在线视频 国产 日韩 | 中文字幕黄色 | 亚洲成人av一区二区 | 中文字幕中文字幕在线中文字幕三区 | 天天性天天草 | 久久麻豆视频 | 国内精品视频一区二区三区八戒 | 久久99视频精品 | 五月婷视频 | 国产中文字幕视频在线观看 | 国产区欧美 | 最近日本mv字幕免费观看 | 99精品在线观看 | 国产乱视频 | 免费av网站在线看 | 国产精品夜夜夜一区二区三区尤 | 三上悠亚在线免费 | 国产999视频 | 欧美激情精品久久久久 | 欧美精品在线一区 | 国产小视频免费在线观看 | 成年人电影免费在线观看 | 亚州国产精品久久久 | 国产精品黄 | www.日韩免费| 亚洲精品久久久蜜臀下载官网 | 国产欧美精品在线观看 | 在线观看aaa | 91视频麻豆视频 | 涩涩伊人| 国产成人一区二区啪在线观看 | 深夜免费福利视频 | 欧美一级在线看 | 国产精品福利在线观看 | 黄色av三级在线 | av亚洲产国偷v产偷v自拍小说 | 四虎国产精品成人免费影视 | 精品99999 | 欧美综合色 | 国产一线二线三线在线观看 | 91av视频| 国产成人精品av在线观 | 精品一二| 一级免费黄视频 | 久久成人精品视频 | 欧美孕交vivoestv另类 | 日韩超碰在线 | 日韩免费中文 | 天天综合网在线观看 | 欧美国产视频在线 | 久久久午夜精品理论片中文字幕 | 免费电影一区二区三区 | 夜夜操天天操 | a午夜电影| 国产视频日韩视频欧美视频 | 成人在线免费看视频 | 在线观看完整版 | 亚洲欧洲成人精品av97 | 国产亚洲视频在线免费观看 | 欧美日韩中文在线 | 欧洲视频一区 | 中文字幕在线网址 | 欧美色综合天天久久综合精品 | 一区二区三区高清在线观看 | 精品国产日本 | 久久色网站| 久久在现| 国产精品福利无圣光在线一区 | 国产精品欧美一区二区 | 黄色大片免费播放 | 国产一区成人 | 91在线看视频免费 | 香蕉一区| 中文字幕av在线播放 | www久草 | 精品国产一区二区三区久久久蜜臀 | 久久精品成人热国产成 | 日本午夜免费福利视频 | 91av大全 | 一区中文字幕 | 婷婷精品进入 | 中文在线字幕免费观 | 日韩精品中文字幕久久臀 | 欧美极品少妇xxxxⅹ欧美极品少妇xxxx亚洲精品 | 黄色特级片| 超碰公开在线 | 欧美一级性生活片 | 在线日韩视频 | 亚洲国产三级 | 免费在线观看午夜视频 | 一区二区三区国 | 日批在线看 | 久久电影中文字幕视频 | 亚洲精品欧美专区 | 国产精品一区二区电影 | 日本乱视频 | 国产精品久久99综合免费观看尤物 | 天天做天天爱夜夜爽 | 97精品视频在线播放 | 一区二区三区四区影院 | 国产成人免费高清 | 久久婷婷国产色一区二区三区 | 亚洲人天堂 | 视频在线观看国产 | 五月婷婷黄色 | 欧美成人69av | 亚洲一二区视频 | 一区二区三区免费在线观看视频 | 中文字幕国产在线 | 欧美日韩国产精品一区二区 | 九九九九免费视频 | 这里只有精品视频在线观看 | 亚洲在线不卡 | 麻豆国产在线视频 | 中文字幕在线成人 | 国产精品嫩草影视久久久 | 亚洲免费不卡 | 国产精品aⅴ | 在线观看中文字幕一区二区 | 午夜国产福利在线 | 久久精品4 | 国产拍在线 | 日本精品在线看 | 亚洲专区在线播放 | 国产九色视频在线观看 | 外国av网 | 欧美一区二区日韩一区二区 | 黄色日本片 | 国产精品久久久久久久久毛片 | 最新av免费 | 一区二区 精品 | 三级黄色在线观看 | 色爱成人网 | 日韩高清在线看 | 黄色成人在线观看 | 天堂在线视频中文网 | 中文字幕在线免费看 | 中文字幕一区二区三区在线视频 | 日本护士三级少妇三级999 | 一级性av | 久久五月婷婷丁香社区 | 久久综合九色综合欧美就去吻 | 亚洲视频资源在线 | 狠狠干夜夜 | 日韩一区二区三区不卡 | 欧美日韩在线精品 | 日韩精品视频第一页 | 天天操月月操 | 国产精品美女久久久久久网站 | 九九热免费在线视频 | 日韩视频一区二区在线观看 | 精品国产区 | 99这里精品| 国产区在线看 | 中文字幕永久在线 | 91在线精品视频 | 99在线观看视频网站 | 国产精品三级视频 | 香蕉网站在线观看 | 亚洲一区二区三区miaa149 | 国产资源在线视频 | 亚洲国产无| 9在线观看免费高清完整版 玖玖爱免费视频 | 亚洲欧美国产精品va在线观看 | 中字幕视频在线永久在线观看免费 | 免费看国产黄色 | www.五月天婷婷.com | 久久经典国产视频 | 操操日 | 最新午夜电影 | 在线观看一级片 | 国产福利在线不卡 | 国产精品入口久久 | 欧美最猛性xxxxx亚洲精品 | 五月婷婷六月丁香在线观看 | 最近日本韩国中文字幕 | 亚洲mv大片欧洲mv大片免费 | 亚洲激情在线观看 | 成人三级av | 亚洲婷婷丁香 | 久久99精品热在线观看 | 国产精品男女视频 | 亚洲涩涩涩涩涩涩 | 日韩欧美一区视频 | 日韩系列在线观看 | 91精品国产91久久久久久三级 | 国产精品久久久久久久av大片 | 精品久久久久久亚洲综合网 | 九色在线视频 | 色婷婷激婷婷情综天天 | 黄色av播放 | 久久蜜臀一区二区三区av | 九九热在线免费观看 | 国产高清无线码2021 | 三级黄色片在线观看 | 色狠狠综合天天综合综合 | 天天操天天摸天天射 | 国产精品久久久久久久久大全 | 91在线播放综合 | 在线免费观看国产精品 | 中文字幕资源网 | 麻豆国产在线视频 | 91免费视频网站在线观看 | 人人超碰免费 | 五月婷影院| 久久伊人国产精品 | 最新国产精品久久精品 | 欧洲精品视频一区二区 | 国产视频资源在线观看 | 一区二区三区高清在线 | 91视频麻豆视频 | 在线免费观看黄色 | 天天干 天天摸 天天操 | 天天操天天操天天操天天操天天操 | 久久欧洲视频 | 天天操天天干天天爱 | 久久久久国产精品一区 | 西西444www大胆高清图片 | 午夜精品久久久久久久99水蜜桃 | 波多野结衣电影一区二区三区 | 亚洲欧洲中文日韩久久av乱码 | 激情婷婷在线观看 | 亚洲精品中文字幕视频 | 国产三级午夜理伦三级 | 国产精品18久久久久vr手机版特色 | 成年人精品 | 99视频精品 | 国产精品永久免费 | 国产精品久久久久久一区二区三区 | 丁香六月中文字幕 | 国产视频在线观看一区 | 97日日碰人人模人人澡分享吧 | 成人中文字幕+乱码+中文字幕 | 久久精品人人做人人综合老师 | 手机av资源 | 久久久久久高潮国产精品视 | 色资源网免费观看视频 | 五月色婷 | 婷婷色站| 97av影院 | 国产精品久久久久久婷婷天堂 | 久久99久久99免费视频 | 99精品国产免费久久久久久下载 | 天天爱综合 | 国产操在线 | 久草影视在线 | 制服丝袜天堂 | 黄色网址中文字幕 | 国产手机视频精品 | 国产天天爽 | 午夜久久久久久久久久久 | 成年人在线免费视频观看 | 伊人狠狠色丁香婷婷综合 | 一区二区精 | 国产又粗又长的视频 | 国产裸体视频网站 | 久久婷婷丁香 | 国产精品毛片一区二区在线看 | 成人久久久久久久久久 | 激情五月五月婷婷 | 中文字幕av全部资源www中文字幕在线观看 | 狠狠狠色丁香婷婷综合久久五月 | 欧美一区二区伦理片 | 最近中文字幕免费av | 免费a v在线 | 国产一级黄 | 99热网站| 超碰人人射 | 亚洲国产999 | 久久精品国产第一区二区三区 | 91av手机在线观看 | 激情狠狠干 | 精品一区 在线 | 日本激情视频中文字幕 | 黄色一区二区在线观看 | 婷婷久久一区 | 日韩av进入 | 天天做天天爱夜夜爽 | 欧美色图狠狠干 | 国产高清av免费在线观看 | 99色 | 97视频在线观看视频免费视频 | 亚洲精品中文在线资源 | 国产精品不卡视频 | 亚洲精品在线观看视频 | 天天摸日日摸人人看 | 国产黄在线播放 | 少妇精69xxtheporn | 美女黄频免费 | 国产美女在线免费观看 | 天天射一射 | 午夜体验区 | 国产欧美在线一区 | 日韩啪视频 | 欧美日韩裸体免费视频 | www.色午夜| 97超碰人| 一区二区精品在线观看 | 91香蕉视频色版 | 国产字幕av | 精品亚洲免a | 成人免费在线视频 | 一级黄色a视频 | 国产一区在线免费观看视频 | 成人资源网 | 夜夜视频资源 | 99久久电影 | 综合色爱| 国产成人av在线影院 | 久久综合狠狠综合久久综合88 | 在线观看久久 | 五月婷婷六月丁香在线观看 | 日韩视频在线一区 | 日韩视频免费观看高清 | 国产小视频在线观看 | 色综合天天综合网国产成人网 | 亚洲免费a| 国语精品免费视频 | 中文av影院 | 成人播放器 | 东方av在 | 欧美性猛片| 中文字幕乱码在线播放 | 成年人网站免费观看 | 国产亚洲精品久久19p | 久久精品99久久久久久 | 亚洲国产人午在线一二区 | 亚洲视频免费在线观看 | 91天天视频| 亚洲高清久久久 | 国产亚洲视频中文字幕视频 | 91色一区二区三区 | 久久午夜影视 | 天天摸天天舔天天操 | 91在线一区二区 | 伊人夜夜| 97超级碰碰碰视频在线观看 | 日韩av片无码一区二区不卡电影 | 欧美日韩免费在线视频 | 久草视频在线免费 | 日韩欧美视频二区 | 国产色啪| 国产一区二区影院 | 成人免费 在线播放 | 欧美日本不卡 | 美女性爽视频国产免费app | 国产精品一区二区三区久久久 | 91精品麻豆| 久久高清精品 | 亚洲乱码在线 | 91av免费在线观看 | 日韩欧美高清免费 | 久久久久综合 | 亚洲精品在线资源 | 久久综合在线 | 中文字幕日韩在线播放 | 免费污片| 丁香影院在线 | 国产精品一区二区免费在线观看 | 天天爽天天爽夜夜爽 | 天天搞天天干天天色 | 麻豆视频国产在线观看 | 欧美91视频| 激情 亚洲 | 激情av网址 | 高清av在线免费观看 | 91x色| 久久人人爽 | 日本久久久久久科技有限公司 | 日韩不卡高清视频 | av东方在线| 国产区av在线 | 在线看日韩 | 日韩大陆欧美高清视频区 | 午夜少妇一区二区三区 | 国产伦理久久精品久久久久_ | 四虎影视国产精品免费久久 | 91系列在线 | 一级α片 | 欧美日韩在线观看一区二区 | 亚洲高清在线观看视频 | 日韩欧美国产精品 | 最新色视频 | av激情五月 | 中文字幕av最新 | 国产精品久久久久久久久久妇女 | 一区二区中文字幕在线播放 | 啪啪肉肉污av国网站 | 久久久久国产一区二区三区四区 | 97在线免费 | 精品国产黄色片 | 国产香蕉久久精品综合网 | 国产精品久久久免费看 | 伊人日日干 | 麻豆91在线 | 久久久久久久av麻豆果冻 | 玖玖在线视频观看 | 最近2019中文免费高清视频观看www99 | 在线观影网站 | 日韩av男人的天堂 | 久热av在线 | 一区二区久久 | 96av麻豆蜜桃一区二区 | 久久免费国产 | 玖玖在线播放 | 狠狠操操操 | 区一区二区三在线观看 | 欧美一级性生活片 | 亚洲狠狠婷婷 | 日韩欧美极品 | 日韩久久久久久久久 | 日韩日韩日韩日韩 | 开心色激情网 | 最近最新中文字幕 | 在线亚洲高清视频 | 日韩精品免费一区二区三区 | 黄色毛片在线看 | av综合av| 成人国产精品av | 国模视频一区二区 | 激情五月婷婷综合网 | 成人小视频在线 | 伊人导航 | 日日噜噜噜噜夜夜爽亚洲精品 | 99久久99久久免费精品蜜臀 | 欧美 亚洲 另类 激情 另类 | 日本三级吹潮在线 | 久久首页| 超薄丝袜一二三区 | 亚洲91网站 | 在线观看免费视频 | 免费在线91| 91大神精品视频在线观看 | 亚洲精品 在线视频 | 97超碰人人澡 | 亚洲成人黄色av | 亚洲二区精品 | 96视频在线 | 日韩有码第一页 | 天天草夜夜 | 成人免费在线观看电影 | av片在线看| 99久久精品免费视频 | 日韩欧美一区视频 | 日本视频不卡 | 久久se视频 | 成人亚洲网 | 欧美精品一区在线发布 | 天天插日日射 | 久久久国产精品网站 | 六月丁香社区 | 国产精品久久久久久久毛片 | 欧美婷婷色 | 久久视频在线视频 | 国产黄免费在线观看 | 最新国产视频 | 在线一二三区 | 久久久久成人精品亚洲国产 | 一区二区av| 高清av免费观看 | 五月天开心 | 在线观看黄色免费视频 | 一区二区三区日韩在线观看 | 久久久久久久综合色一本 | 香蕉久草在线 | 国产精品久久久久久久久久久免费 | 视频成人永久免费视频 | 黄色大全在线观看 | 久久久69 | 在线播放一区二区三区 | 97操操操| 欧美极品少妇xxxxⅹ欧美极品少妇xxxx亚洲精品 | 欧美污污网站 | 色婷婷www | 超碰97国产在线 | 丁香婷婷成人 | 国产亚洲精品久久久久久久久久久久 | 日韩一区二区免费视频 | 国产区精品区 | 国产精品美女在线观看 | 91九色视频在线播放 | 国产小视频在线免费观看视频 | 日韩精品久久久久久久电影99爱 | 国产日本高清 | 2023亚洲精品国偷拍自产在线 | 激情五月激情综合网 | 六月色| 国产黄色精品在线 | 9i看片成人免费看片 | 噜噜色官网| 99久久国产免费看 | 久久综合影视 | 久久国产精品小视频 | 808电影免费观看三年 | 97精品超碰一区二区三区 | 久久精品视频2 | 色网站黄 | 一区二区三区四区不卡 | 久久免费视频精品 | 丁香六月激情婷婷 | 岛国精品一区二区 | 日日夜夜网站 | 日韩精品第1页 | 色婷av | 日日干夜夜干 | 免费涩涩网站 | 久久国产亚洲 | a天堂在线看 | 成人片在线播放 | 黄色字幕网 | 欧美日韩在线网站 | 国内成人精品2018免费看 | 欧美夫妻生活视频 | 久久综合狠狠综合久久狠狠色综合 | 99久久精品日本一区二区免费 | 日韩免费一区 | 国产欧美高清 | 日本中文字幕高清 | 国产一区二区不卡视频 | 免费观看av网站 | 96久久| 亚洲欧美综合精品久久成人 | 午夜av免费看 | 国产一二三在线视频 | 国产高清在线看 | 成人av电影网址 | 午夜精品久久久久久久99水蜜桃 | 免费三级黄色片 | 免费成人黄色 | 91秒拍国产福利一区 | 亚洲理论在线 | 美女视频黄免费的 | 国产破处视频在线播放 | 免费毛片一区二区三区久久久 | 欧美精彩视频在线观看 | 丁香亚洲 | 中文字幕视频免费观看 | 久久伦理 | 一区二区三区日韩在线观看 | 蜜臀av夜夜澡人人爽人人 | 手机色站 | 亚洲精品午夜aaa久久久 | 国产精品嫩草影院123 | 激情欧美一区二区三区免费看 | 国产午夜精品理论片在线 | 永久免费av在线播放 | 久久精品国产亚洲精品 | 久久精品亚洲精品国产欧美 | 欧美午夜精品久久久久久浪潮 | 在线国产日韩 | 日批网站在线观看 | 色婷婷综合久久久 | 国产96在线视频 | 最近日本韩国中文字幕 | 日韩精品一区二区三区第95 | 久久99精品国产一区二区三区 | 久久蜜臀一区二区三区av | 欧美巨大 | 国产福利免费在线观看 | 91少妇精拍在线播放 | 在线观看一级视频 | 精品国产精品久久一区免费式 | 国产一区在线观看视频 | 粉嫩一区二区三区粉嫩91 | 久久久久久亚洲精品 | 欧美乱大交 | 国产成人av网站 | 日韩av电影网站在线观看 | 中文字幕人成不卡一区 | 97超碰国产精品 | 91国内在线 | av中文电影 | 99tvdz@gmail.com| 成人香蕉视频 | 99久久久久久 | 国产一区二区精品 | 免费又黄又爽的视频 | 国产亚洲精品电影 | 婷婷色在线资源 | 亚洲乱码精品久久久 | 97网站| av黄免费看 | 午夜天使 | av三级av| 色吧久久 | 欧美性黑人 | 日韩精品在线一区 | 欧美日韩中文视频 | 激情久久综合 | 国产电影一区二区三区四区 | 日韩黄色免费电影 | 免费a v观看 | www.天天操 | 中文av字幕在线观看 | 中文一区二区三区在线观看 | 麻豆av电影 | 六月天综合网 | 免费网站在线观看成人 | 成人观看 | 日韩影片在线观看 | 97国产一区二区 | 九九免费在线观看 | 青青河边草观看完整版高清 | 人人澡超碰碰 | 在线 日韩 av| 久久久久久久久久免费视频 | 久久精品人人做人人综合老师 | 国产精品区二区三区日本 | 特级西西444www大精品视频免费看 | 精品久久亚洲 | 国产精品亚洲人在线观看 | 91在线精品秘密一区二区 | 99热这里精品 | a视频免费看 | 日韩a级免费视频 | 天天干天天上 | 亚洲欧美日本一区二区三区 | 一区精品久久 | 久久免费视频这里只有精品 | 日本午夜在线观看 | 久久精品欧美 | 国产精品久久久久久久久久久久 | 高清不卡免费视频 | 色99久久 | 国产91在线免费视频 | 97自拍超碰 | 超碰99在线 | 91丨porny丨九色 | 免费观看丰满少妇做爰 | 99色亚洲 | 亚洲欧美日韩中文在线 | 最近日韩免费视频 | 久久久久久免费视频 | 91九色在线播放 | 国产精品一区一区三区 | 国内精品久久久久久久久久久久 | 国产永久免费高清在线观看视频 | 亚洲涩涩涩 | 日韩三级一区 | 91最新地址永久入口 | 在线欧美最极品的av | 超碰人人舔 | 国产在线精品国自产拍影院 | www黄com| 欧美福利片在线观看 | 亚洲免费高清视频 | 久久高视频 | 免费欧美| 国产自产高清不卡 | 91在线播放国产 | 日韩中文字幕a | 99久久精品国产欧美主题曲 | 天天看天天操 | 91亚洲视频在线观看 | 91av美女| 欧美日韩精品在线视频 | 国产人成精品一区二区三 | 91精品天码美女少妇 | 国产精品免费观看久久 | 成人黄色小说在线观看 | 91欧美国产 | 国产一卡久久电影永久 | 少妇bbbb | 激情五月在线 | 成人欧美一区二区三区黑人麻豆 | 激情av资源| 91成人在线视频 | 手机看片| h网站免费在线观看 | 国产成人精品国内自产拍免费看 | avsex| 久久人人干 | 日韩在线电影观看 | a黄色影院 | aaa日本高清在线播放免费观看 | 操操操夜夜操 | 高清不卡毛片 | 黄色成人在线观看 | 日韩特黄av | 中文字幕丝袜美腿 | 色婷婷国产精品 | 精品久久久久久久久久久院品网 | 毛片www | 一区二区 精品 | 黄色av免费| 国内精品久久久久影院一蜜桃 | 成人性生交大片免费看中文网站 | 国产成人精品综合久久久 | 麻豆精品国产传媒 | 狠狠色丁香婷婷综合久小说久 | 亚洲视频网站在线观看 | 91成品人影院 | 久久久久久久免费看 | 久久91网 | 国模吧一区 | 欧美激情视频一区 | 最新国产精品拍自在线播放 | 中文字幕在线免费看线人 | 久久亚洲精品电影 | 伊人超碰在线 | 成人av一区二区三区 | 欧美日韩精品影院 | 国产精品毛片久久久久久久 | 97成人精品视频在线观看 | 日韩三级视频在线观看 | av一级网站 | 国产午夜av | 99视频网址| 亚洲精品小区久久久久久 | 五月婷婷综合激情网 | 欧美在线视频不卡 | 人人dvd| 麻豆视频免费入口 | 欧美日韩在线观看一区二区三区 | 亚洲精品久久久久久久不卡四虎 | 久久99操 | 欧美性大胆 | 欧美性大胆 | www五月天| 午夜精品福利一区二区三区蜜桃 | 欧美成人h版在线观看 | 伊人中文在线 | 国产一区二区三区免费观看视频 | 欧美色久 | 精品欧美日韩 | 午夜国产福利在线 | 亚洲视频精品 | 日韩精品久久久久 | 欧美日在线观看 | 久久国产精品一区二区 | 最新日韩中文字幕 | 免费看黄色小说的网站 | 国产成年人av | 日本三级吹潮在线 | 久久丁香网 | 91看片黄色| 99精品视频在线播放观看 | 日韩中文免费视频 | 成人免费视频视频在线观看 免费 | 成人资源站 | 日韩精品资源 | 国产精品久久久一区二区 | 91传媒在线播放 | 色综合久久88色综合天天免费 | 韩国精品视频在线观看 | 日日夜夜爱| 国产精品久久久久一区二区 | 91av99| 免费毛片一区二区三区久久久 | 国产精品免费视频网站 | 91久久久久久国产精品 | 亚洲综合色视频 | 99精品免费在线观看 | 一级精品视频在线观看宜春院 | 成人三级网站在线观看 | 欧美性猛片| 久久免费公开视频 | 美女av免费看 | 欧美色图视频一区 | 一级α片免费看 | 日韩在线视频看看 | 在线免费观看视频一区二区三区 | 久久夜色电影 | 中文字幕欧美日韩va免费视频 | 中文一二区 | 国产99亚洲 | 9999在线视频 | 国产一区二区三区四区大秀 | 国产 日韩 欧美 中文 在线播放 | 久久天天综合网 | 黄色大全视频 | 永久免费的啪啪网站免费观看浪潮 | 91日韩在线 | 97**国产露脸精品国产 | 国产人在线成免费视频 | 亚洲最新视频在线 | 久久天天躁狠狠躁夜夜不卡公司 | 成年人在线观看免费视频 | 国产精品久久久久久影院 | 久久精品国产99国产 | 91一区一区三区 | 91pony九色丨交换 | 97在线观看免费视频 | 在线观看久久久久久 | 在线一区电影 | 一区二区三区四区影院 | 亚洲禁18久人片 | 丁香婷婷射 | 日韩狠狠操 | 日本精品一区二区在线观看 | 欧美在线视频一区二区三区 | 婷婷久久五月 | 99精品免费网 | 久久影视一区二区 | 亚洲.www| 狠狠干婷婷| 欧美人交a欧美精品 | 天天草天天干天天射 | 色资源在线观看 | www.亚洲精品视频 | 欧美日韩三区二区 | 在线免费观看视频你懂的 | 国产最新在线 | 亚洲综合导航 | 久久综合九色综合97_ 久久久 | 国产午夜精品免费一区二区三区视频 | 亚洲精品视频在线观看网站 | 97在线免费视频观看 | 欧美a免费 | 国产1区2区3区精品美女 | 日韩精品一区二区三区不卡 | 中文字幕电影网 | 久99久在线 | 国产成人一区二区三区电影 | 国产一区二区久久 | 国产在线 一区二区三区 | 日韩欧美黄色网址 | 日韩欧美视频在线观看免费 | 国产精品成人久久久 | 在线亚洲成人 | 一区二区三区手机在线观看 | www.色com| 中文字幕综合在线 | 九月婷婷人人澡人人添人人爽 | 欧美一级视频免费看 | 国产美女精品人人做人人爽 | 免费看国产a | 91精品久久久久久 | 久二影院 | 日韩电影久久久 | 成人午夜av电影 | 免费久草视频 | 国产午夜在线观看视频 | 日韩在线观看三区 | 免费成人看片 | 欧美日韩一区二区三区免费视频 | 欧美日韩中字 | 色婷婷国产在线 | 天天爽夜夜爽精品视频婷婷 | 蜜臀av性久久久久av蜜臀三区 | 日韩av在线小说 | 日韩高清在线观看 | 日韩欧美视频在线播放 | 97香蕉视频 | 黄网站色欧美视频 | 激情久久久久久久久久久久久久久久 | 香蕉视频在线免费看 | 成人国产精品入口 | 久久神马影院 | 欧美精品xx | 日本中文字幕在线视频 | 日韩一区二区三区观看 | 免费a级大片 | 国产韩国日本高清视频 | 黄色在线网站噜噜噜 | 综合久久久久 | 香蕉久久国产 | 亚洲欧美乱综合图片区小说区 | 日韩精品视频免费看 | 日韩在线观看视频中文字幕 | 国产在线永久 | 91精品久久香蕉国产线看观看 | 国产在线自 | 色在线最新 | av成人免费观看 | 精品久久久久久一区二区里番 | 激情视频久久 | 国产xxxx性hd极品 | 亚洲国产精品成人综合 | 亚洲春色成人 | av片在线观看 | 99草在线视频 | 国产日韩欧美在线观看 | 99一区二区三区 | 国产99久久久久久免费看 | 中文字幕精品一区 | 18岁免费看片 | 99超碰在线播放 | 国产99久久久国产 | 丝袜av一区 | 色综合久久中文综合久久牛 | 国产成人精品久久亚洲高清不卡 | 视频一区二区在线 | 夜夜操综合网 | 免费观看91视频大全 | 久久夜色精品国产欧美一区麻豆 | 超碰97.com | 亚洲精品黄网站 | 色妞色视频一区二区三区四区 | 亚洲乱码精品久久久久 | 久久社区视频 | 国产视频不卡一区 | 日韩伦理片hd | 97在线观看免费观看高清 | 97超碰.com| 在线观看国产日韩 | 天天操夜操 | 三级黄免费看 | 制服丝袜一区二区 | 国产日韩精品一区二区三区在线 | 国产精品久久精品国产 | 在线观看黄色av | av亚洲产国偷v产偷v自拍小说 | 91精选在线| 少妇bbw搡bbbb搡bbbb| 欧美午夜久久 | 亚洲国产视频直播 | 国模精品一区二区三区 | 免费看片成年人 | 国产精品 日韩 欧美 | 天天干天天天天 | 香蕉视频国产在线观看 | 久久久五月婷婷 | 久久午夜鲁丝片 | 亚洲精品视频播放 | 欧美五月婷婷 | 国产亚洲精品电影 | 99r在线播放 | 黄色网在线免费观看 | 五月开心色 | 欧美a性| 久草免费手机视频 | 色婷婷综合久久久久中文字幕1 | 激情六月婷婷久久 | 久草视频首页 | 一级片免费观看视频 | 99国内精品久久久久久久 | 欧美大片在线看免费观看 | 国产成免费视频 | 日日夜夜噜 | 中国精品一区二区 | 91丨九色丨首页 | 久久五月天色综合 | 91中文字幕网 | 99久久精品一区二区成人 | 亚洲专区中文字幕 | av在线短片 | 久久在线 | 97视频在线免费观看 | 亚洲精品国产高清 | 激情欧美日韩一区二区 | 黄a在线看 | 亚洲视频1 | 亚洲综合欧美激情 | 国产精品久久久久久久久久不蜜月 | 在线看国产 | 国外调教视频网站 | 麻豆影视网| 97av超碰 | 亚洲黄色小说网 | 国产18精品乱码免费看 | 午夜在线免费视频 | 国产自在线 | 丝袜美腿一区 | 久久成人人人人精品欧 | 成人免费网站在线观看 | 久久美女免费视频 | 91少妇精拍在线播放 | 欧美性天天| 国产视频久久久 | 黄色aa久久 | 久久视频免费在线 |