php基礎複習

基礎撿漏:php

一、短標記<??> 經過修改ini文件的short_open_tag或編譯時 --enable-short-tags 可用 不推薦使用、html

二、?>默認有隱藏分號結束,而文件最後能夠省略?>前端

三、使用條件的高級分離術node

<?php if ($expression == true): ?>
  This will show if the expression is true.
<?php else: ?>
  Otherwise this will show.
<?php endif; ?>
web

!!後面的程序不執行了??正則表達式

php解析器會在條件未達成時直接跳過該條件語句塊??因此比echo、print更有效率shell

因此適用輸出大段文本數據庫

四、script式express

<script language="php">
        echo 'some editors (like FrontPage) don\'t
              like processing instructions';
    </script>
windows

好像沒什麼意義阿,又輸出不出來

五、自 PHP 5.4 起,短格式的 echo 標記 <?= 總會被識別而且合法,而無論 short_open_tag 的設置是什麼。因此1不成立

六、9種原始數據類型

標量類型

boolean

integer

float

string

複合類型
array

object

Callback/Callable(可調用)??與類有關

特殊類型

resource(資源)

NULL(無類型)

爲了確保代碼的易讀性,本手冊還介紹了一些僞類型://就是實際沒有這種類型

mixed(混合類型)
number(數字類型)
callback(回調類型,又稱爲 callable)
array|object(數組 | 對象類型)
void (無類型)

 七、php是弱類型語言,因此php根據變量的上下文來判斷變量的類型;

查看變量的值和類型:var_dump();

輸出類型:gettype();

判斷是不是某類型:is_int/string/object()

八、變量強制轉換爲某類型

(boolean/bool) $foo

settype($a, 'string');//返回true/false

九、echo(false);爲空白!

十、類型比較表,https://www.php.net/manual/zh/types.comparisons.php 比較很特殊的值

十一、空數組轉換爲boolean時,爲false,變量在流程控制中if($a),自動轉化爲boolean類型

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

1三、整數是有符號的,整數的最大最小值與系統有關,32位,0/1 (符號位)31個1 因此是2^31-1 (二進制計算喲) 2147483647

同理64位系統,則是2^63-1 爲9223372036854775807

超過這兩個數,則將轉化成float類型

1四、強制轉化爲整形 

(int) 或 (integer) 

intval($非object,0/10/2/8/16)  object會報錯,後面參數爲何進制,若是是0,則根據變量自己來判斷

成功時返回 var 的 integer 值,失敗時返回 0。 空的 array 返回 0,非空的 array 返回 1

 1五、浮點數的精度有限。儘管取決於系統,PHP一般使用IEEE 754雙精度格式(64位),永遠不要相信浮點數結果精確到了最後一位,也永遠不要比較兩個浮點數是否相等

1六、計算浮點數相等的例子

<?php
$a = 1.23456789;
$b = 1.23456780;
$epsilon = 0.00001;

if(abs($a-$b) < $epsilon) {
    echo "true";
}
?>

1七、NAN  is_nan()

1八、每一個字符等同於一個字節。這意味着 PHP 只能支持 256 的字符集,所以不支持 Unicode,最大可達2GB

1九、四種表達方式

  單引號

  雙引號

  heredoc 語法結構

  nowdoc 語法結構

 20、單引號除\' \\外 其餘\轉義均無效

2一、\[0-7]{1,3} 符合該正則表達式序列的是一個以八進制方式來表達的字符

\x[0-9A-Fa-f]{1,2} 符合該正則表達式序列的是一個以十六進制方式來表達的字符

不太明白

2二、heredoc 句法結構:<<<

$str = <<<EOD
Example of string
spanning multiple lines
using heredoc syntax.
EOD;

EOD是遵照 PHP 的規則:只能包含字母、數字和下劃線,而且必須以字母和下劃線做爲開頭。

echo <<<EOT
My name is "$name". I am printing some $foo->foo.
Now, I am printing some {$foo->bar[1]}.
This should print a capital 'A': \x41
EOT;

裏面能夠包含變量

Heredoc 結構還能夠來初始化靜態變量和類的屬性和常量

或者

$str = <<<「EOD」
Example of string
spanning multiple lines
using heredoc syntax.
EOD;

2三、Nowdoc 結構

$str = <<<‘EOD’
Example of string
spanning multiple lines
using heredoc syntax.
EOD;

裏面純文本,不解析,相似單引號

 2四、當 PHP 解析器遇到一個美圓符號($)時,它會和其它不少解析器同樣,去組合儘可能多的標識以造成一個合法的變量名。能夠用花括號來明確變量名的界線。一個 array 索引或一個 object 屬性也可被解析

// Invalid. "s" is a valid character for a variable name, but the variable is $juice.
echo "He drank some juice made of $juices.";

He drank some juice made of .
echo "He drank some $juices[0] juice.".PHP_EOL;
echo "$people->john drank some $juices[0] juice.".PHP_EOL;

2五、php換行符PHP_EOL,以提升代碼的源代碼級可移植性

 2六、變量解析複雜模式(花括號)

{$} $必須和{緊挨着

// 有效,只有經過花括號語法才能正確解析帶引號的鍵名
echo "This works: {$arr['key']}";

// 有效,輸出: This is fantastic

echo "This is ${great}";

echo "This is the value of the var named by the return value of getName(): {${getName()}}";

// 無效,輸出: This is the return value of getName(): {getName()}
echo "This is the return value of getName(): {getName()}"

<?php

class beers {
    const softdrink = 'rootbeer';
    public static $ale = 'ipa';
}

$rootbeer = 'A & W';
$ipa = 'Alexander Keith\'s';

// 有效,輸出: I'd like an A & W
echo "I'd like an {${beers::softdrink}}\n";

// 也有效,輸出: I'd like an Alexander Keith's
echo "I'd like an {${beers::$ale}}\n";

總結:複雜的起始{${ 表達式,能夠是類的變量或者函數}}

2七、string 中的字符能夠經過一個從 0 開始的下標 相似array

// 取得字符串的第一個字符
$str = 'This is a test.';
$first = $str[0];

string 也可用花括號訪問,好比 $str{42}

用超出字符串長度的下標寫入將會拉長該字符串並以空格填充,非整數的下標將會轉成整數

2八、substr(string $string, int $start[, int $length]) : string

length 和 start 可爲負 從末尾開始算

substr_replace( mixed $string , mixed $replacement , mixed $start [, mixed $length ] ) : mixed)

 length 和 start 可爲負 從末尾開始算

2九、(string)$var 和 strval() 不能將 strval() 用於數組或對象

30、一個布爾值 boolean 的 TRUE 被轉換成 string 的 "1"。Boolean 的 FALSE 被轉換成 ""(空字符串)

 3一、獲取類的名稱

get_class($object) 和 __toString()

3二、大部分的 PHP 值能夠轉變成 string 來永久保存,這被稱做串行化

serialize() 返回字符串,此字符串包含了表示 value 的字節流,能夠存儲於任何地方。

這有利於存儲或傳遞 PHP 的值,同時不丟失其類型和結構。

想要將已序列化的字符串變回 PHP 的值,可以使用 unserialize()

[1,2,3,4] => string(38) "a:4:{i:0;i:1;i:1;i:2;i:2;i:3;i:3;i:4;}"

3三、字符串轉數值

$foo = 1 + "10.5";                // $foo is float (11.5)
$foo = 1 + "-1.3e3";              // $foo is float (-1299)
$foo = 1 + "bob-1.3e3";           // $foo is integer (1)
$foo = 1 + "bob3";                // $foo is integer (1)
$foo = 1 + "10 Small Pigs";       // $foo is integer (11)
$foo = 4 + "10.2 Little Piggies"; // $foo is float (14.2)
$foo = "10.0 pigs " + 1;          // $foo is float (11)
$foo = "10.0 pigs " + 1.0;        // $foo is float (11) 

3三、ord() 查字符的ascii嗎

chr()反過來

3四、字符串類型詳解

 

PHP 中的 string 的實現方式是一個由字節組成的數組再加上一個整數指明緩衝區長度

NUL 和 NULL

Bin
(二進制)
Oct
(八進制)
Dec
(十進制)
Hex
(十六進制)
縮寫/字符
解釋
0000 0000
00
0
0x00
NUL(null)
空字符
0000 0001
01
1
0x01
SOH(start of headline)
標題開始
0000 0010
02
2
0x02
STX (start of text)
正文開始

一個‘L’的NUL用於結束一個ASCII字符串,

兩個‘L’的NULL用於表示什麼也不指向(空指針)

字符串類型的此特性解釋了爲何 PHP 中沒有單獨的「byte」類型 - 已經用字符串來代替了

3五、棧(stack)又名堆棧,

它是一種運算受限的線性表。其限制是僅容許在表的一端進行插入和刪除運算。這一端被稱爲棧頂,相對地,把另外一端稱爲棧底。向一個棧插入新元素又稱做進棧、入棧或壓棧,它是把新元素放到棧頂元素的上面,使之成爲新的棧頂元素;從一個棧刪除元素又稱做出棧或退棧,它是把棧頂元素刪除掉,使其相鄰的元素成爲新的棧頂元素

3六、數組

PHP 中的數組其實是一個有序映射。映射是一種把 values 關聯到 keys 的類型。

key 爲整數或者字符串

5.4起 可[]定義

布爾值也會被轉換成整型。即鍵名 true 實際會被儲存爲 1 而鍵名 false 會被儲存爲 0。

 Null 會被轉換爲空字符串,即鍵名 null 實際會被儲存爲 ""。

 亦可用花括號來訪問  $array[42] 和 $array{42} $array{「a」}

 3七、5.4以前不能進行數組解引用

 <?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();

list()爲一個語言結構,將數組按順序賦值於變量,7.1.0以後能夠用於字符串數組,方向從左到右

3八、$arr[] = value;加在末尾

3九、刪除某鍵值

unset($arr[5]);

40、array_values ()

返回全部的值,並重建數字索引

$array = array("size" => "XL", "color" => "gold");
print_r(array_values($array));

Array
(
[0] => XL
[1] => gold
)

4一、注意這裏所使用的最大整數鍵名不必定當前就在數組中。它只要在上次數組從新生成索引後曾經存在過就好了

好比unset數組的全部元素,可是索引的排序一直都在

4二、unset() 函數容許刪除數組中的某個鍵。但要注意數組將不會重建索引

4三、

$foo[bar] = 'enemy';
echo $foo[bar];

如以前無常量bar,則php自動轉爲'bar'; but

this will throw an Error in a future version of PHP

4四、儘可能不要用常量來作key,由於常量可能隨着版本變化而變化,保留字也是同樣的

4五、轉化爲數組

(array)$var $var若是是除對象和數組外其餘類型,則轉爲一個只有0索引的數組

null將轉成一個空數組

 4六、對象轉成數組

 其單元爲該對象的屬性。鍵名將爲成員變量名,不過有幾點例外:整數屬性不可訪問;私有變量前會加上類名做前綴;保護變量前會加上一個 '*' 作前綴。這些前綴的先後都各有一個 NULL 字符。

class A {
private $A=1; // This will become '\0A\0A'
}

class B extends A {
private $A=2; // This will become '\0B\0A'
public $AA=3; // This will become 'AA'

protected $AAA=4;
}

var_dump((array) new B());

array(3) { ["BA"]=> int(2) ["AA"]=> int(3) ["*AAA"]=> int(4)  ["AA"]=> int(1) } 後面的AA 實際上是'\0A\0A';

類中函數將會被忽視

4七、比較數組

arr_diff(不少array) 返回在第一個數組中可是不在其餘 array 裏的值

$a = array("a" => "apple", "b" => "banana");
$b = array("a" => "pear", "b" => "strawberry", "c" => "cherry");

$c = $a + $b; // 誰在前,以誰爲尊

array(3) {
["a"]=>
string(5) "apple"
["b"]=>
string(6) "banana"
["c"]=>
string(6) "cherry"
}
$c = $b + $a;

array(3) {
["a"]=>
string(4) "pear"
["b"]=>
string(10) "strawberry"
["c"]=>
string(6) "cherry"
}

4八、數組傳引用,直接改數組值

$colors = array('red', 'blue', 'green', 'yellow');
foreach ($colors as &$color) {
$color = strtoupper($color);
}
var_dump($colors);

array(4) { [0]=> string(3) "RED" [1]=> string(4) "BLUE" [2]=> string(5) "GREEN" [3]=> &string(6) "YELLOW" }以前認爲&爲bug

//去掉引用關係unset

$colors = array('red', 'blue', 'green', 'yellow');

$index = 1;
foreach ($colors as &$color) {
$color = strtoupper($color);
if($index == 4)
unset($color);
$index++;
}
var_dump($colors);

在打印以前unset($color),則會解決這個bug

4九、填充數組

$handle = opendir('.');//打開讀取,關閉,並將文件名寫入一個數組
while (false !== ($file = readdir($handle))) {
    $files[] = $file;
}
closedir($handle);

50、數組(Array) 的賦值老是會涉及到值的拷貝。使用引用運算符經過引用來拷貝數組。

$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

5一、對象

要建立一個新的對象 object,使用 new 語句實例化一個類。

5二、轉化爲對象

除數組外,若是其它任何類型的值被轉換成對象,將會建立一個內置類 stdClass 的實例

var_dump((object)NULL);
var_dump((object)"abc");

object(stdClass)#1 (0) { }

object(stdClass)#1 (1) { ["scalar"]=> string(3) "abc" }

數組轉對象

var_dump((object) array('1' => 'foo'));

object(stdClass)#1 (1) { ["1"]=> string(3) "foo" }

$obj = (object) array('1' => 'foo');
var_dump(isset($obj->{'1'}));//注意花括號的使用

 5三、資源 resource 是一種特殊變量,保存了到外部資源的一個引用

5四、null類型 只有一個值null 特殊的 NULL 值表示一個變量沒有值

三種狀況認定爲null

被賦值爲 NULL。

還沒有被賦值。

被 unset()。

5五、轉換爲null值

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

$a = 123;
var_dump((unset)$a);
var_dump($a);

NULL

int(123)

5六、call_user_func(funcname, argu1,argu2),把第一個參數做爲回調函數調用,後續爲該函數的參數,而funcname則爲callback類型,其實是以string形式傳遞的

請注意,傳入call_user_func()的參數不能爲引用傳遞!!

function increment () {
    global $a;
    $a ++;
}

$a = 0;

call_user_func('increment', $a);

var_dump($a);

call_user_func_array('increment', [$a]);

var_dump($a);

5七、usort — 使用用戶自定義的比較函數對數組中的值進行排序

usort(array &arr, callback): bool

在第一個參數小於,等於或大於第二個參數時,該比較函數必須相應地返回一個小於,等於或大於 0 的整數

callback($a, $b): int 

5七、Callback / Callable 類型

自 PHP 5.4 起可用 callable 類型指定回調類型 callback

callback 可使用任何內置或用戶自定義的函數,還能夠是對象的方法,包括靜態類方法,但除了語言結構外

當時對象的方法時,用array作參數

// An example callback method
class MyClass {
    static function myCallbackMethod() {
        echo 'Hello World!';
    }
}

// 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');

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

 // Type 6: Objects implementing __invoke can be used as callables (since PHP 5.3)
class C {
    public function __invoke($name) {
        echo 'Hello ', $name, "\n";
    }
}

$c = new C();
call_user_func($c, 'PHP!');

5八、魔術函數__invoke

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

class CallableClass 
{
    function __invoke($x) {
        var_dump($x);
    }
}
$obj = new CallableClass;
$obj(5);//把object當成函數使用,invoke就被調用了
var_dump(is_callable($obj)); //true

is_callable() 函數用於檢測函數在當前環境中是否可調用

5九、range()函數

建立一個包含從 "0" 到 "5" 之間的元素範圍的數組

$number = ;
print_r ($number);range(0,5)

60、Closure 閉包

閉包就是可以讀取其餘函數內部變量的函數,因此閉包能夠理解成「定義在一個函數內部的函數「。在本質上,閉包是將函數內部和函數外部鏈接起來的橋樑。

// Our closure
$double = function($a) {
    return $a * 2;
};

// This is our range of numbers
$numbers = range(1, 5);

// Use the closure as a callback here to 
// double the size of each element in our 
// range
$new_numbers = array_map($double, $numbers);//array_map:函數將用戶自定義函數做用到數組中的每一個值上,並返回用戶自定義函數做用後的帶有新值的數組

print implode(' ', $new_numbers);

6一、call_user_func_array(callable $callback , array $param_arr ) : mixed

第一個參數爲回調函數,後面的數組依次爲他的參數,若是出錯的話返回false

function foobar($arg, $arg2) {
    echo __FUNCTION__, " got $arg and $arg2\n";
}
class foo {
    function bar($arg, $arg2) {
        echo __METHOD__, " got $arg and $arg2\n";
    }
}


// Call the foobar() function with 2 arguments
call_user_func_array("foobar", array("one", "two"));

// Call the $foo->bar() method with 2 arguments
$foo = new foo;
call_user_func_array(array($foo, "bar"), array("three", "four"));//第一個array表示調用$foo實例的bar函數,第二個表示爲bar函數的依次參數

 若是有命名空間時,調用

namespace Foobar;

class Foo {
    static public function test($name) {
        print "Hello {$name}!\n";
    }
}

// 大於PHP 5.3.0
call_user_func_array(__NAMESPACE__ .'\Foo::test', array('Hannes'));//靜態函數簡便調用

// PHP 5.3.0 以前
call_user_func_array(array(__NAMESPACE__ .'\Foo', 'test'), array('Philip'));

//傳引用

function mega(&$a){//&5.4之前可省略,後不行,仍是寫完整
    $a = 55;
    echo "function mega \$a=$a\n";
}
$bar = 77;
call_user_func_array('mega',array(&$bar));
echo "global \$bar=$bar\n";

function mega $a=55
global $bar=55 //引用生效

 6二、在函數中註冊有多個回調內容時(如使用 call_user_func() 與 call_user_func_array()),如在前一個回調中有未捕獲的異常,其後的將再也不被調用

6三、僞類

number 說明一個參數能夠是 integer 或者 float

void 做爲返回類型意味着函數的返回值是無用的。void 做爲參數列表意味着函數不接受任何參數。

在函數原型中,$... 表示等等的意思。當一個函數能夠接受任意個參數時使用此變量名。

6四、類型轉換

容許的強制轉換有:

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

$binary = (binary)$string;
$binary = b"binary string";//轉化爲二進制字符串(php5.2 +)

$avar = "中國";

var_dump((binary)$avar);
var_dump(b"$avar");

string(6) "中國" string(6) "中國" //??啥意思 不是二進制??

6五、變量語法

$

區分大小寫,字母或下劃線開頭,後面任意數量的字母數字下劃線

$this 是一個特殊的變量,不能被賦值

$i站點is = 'mansikka';  // 合法變量名;能夠用中文

6六、如下代碼結構會進入全局命名空間:

functions(函數)

classes (類)

interfaces(接口)

constants (常量,非類常量)

在函數/方法以外定義的變量


function yy(){
define('XX','xxx');
$xx = 'xyz';
}
yy();
var_dump(XX);
var_dump($xx);

  string(3) "xxx"

NULL

要寫出能經受住時間考驗的代碼,建議給任何進入全局命名空間的符號都加上一個不常見的 3-4 字母的前綴(或後綴),中間用下劃線分開。爲了不與其它用戶空間代碼出現命名空間衝突,建議先研究一下其它項目中已有的前綴(或後綴)並適當地公佈出來。示例以下

MyPx_someFunc()

Foo_Date

$asdf_dbh

約定

函數名在兩個詞中間使用下劃線 例如curl_close

類名則使用camelCase 或 PascalCase

__魔術變量,不要用__開頭的符號

Iterators 和 Exceptions ?? 迭代器和異常??

 6七、變量默認值

未初始化的變量具備其類型的默認值 - 布爾類型的變量默認值是 FALSE,整形和浮點型變量默認值是零,字符串型變量(例如用於 echo 中)默認值是空字符串以及數組變量的默認值是空數組。

isset() 語言結構能夠用來檢測一個變量是否已被初始化

// String usage; outputs 'string(3) "abc"'
$unset_str .= 'abc';
var_dump($unset_str);

// Object usage; creates new stdClass object (see http://www.php.net/manual/en/reserved.classes.php)
// Outputs: object(stdClass)#1 (1) {  ["foo"]=>  string(3) "bar" }
$unset_obj->foo = 'bar';
var_dump($unset_obj);

6八、若是register_globals值爲false,PHP5.4已剔除這個

爲了獲得 DOCUMENT_ROOT 的值,將必須使用$_SERVER['DOCUMENT_ROOT'] 代替 $DOCUMENT_ROOT,又如,使用 $_GET['id'] 來代替 $id

6九、預約義變量

一、超全局變量

$GLOBALS --引用全局做用域中可用的所有變量
$_SERVER
$_GET
$_POST
$_FILES
$_COOKIE
$_SESSION
$_REQUEST
$_ENV //環境變量

二、其餘預約義變量

$_COOKIE — HTTP Cookies
$php_errormsg — 前一個錯誤信息
$HTTP_RAW_POST_DATA — 原生POST數據
$http_response_header — HTTP 響應頭
$argc — 傳遞給腳本的參數數目
$argv — 傳遞給腳本的參數數組

70、獲取原生POST數據

$HTTP_RAW_POST_DATA 通常而言,使用php://input 代替

php:// — 訪問各個輸入/輸出流

7一、函數中不可直接使用全局變量,要訪問有兩個方法

一、加一個global 的關鍵字

二、$GLOBALS['b'] 使用超全局變量

注意其餘預約義變量 不是超全局 因此仍是須要global關鍵字 如$HTTP_RAW_POST_DATA

7二、靜態變量 

關鍵字 static 

靜態變量僅在局部函數域中存在,但當程序執行離開此做用域時,其值並不丟失,至關於只運行一次

function test()
{
    static $a = 0;
    echo $a;
    $a++;
}//使用遞歸,之前開發都是傳參數進去,原來有更方便的static關鍵字

其實放在全局空間內,並無報錯,可是無心義

注意:static 賦值時不能用表達式

static $a = 1+1; //錯誤

 7三、Zend Engine 編譯器和執行器

Zend Engine最主要的特性就是把PHP的邊解釋邊執行的運行方式改成先進行預編譯(Compile),而後再執行(Execute) 相似GCC

7四、


function test_global_ref() {
global $obj;
$obj = &new stdclass;//這個php7.2會報語法錯誤
}

function test_global_noref() {
global $obj;
$obj = new stdclass;//正確用法
}

test_global_ref();
var_dump($obj);
test_global_noref();
var_dump($obj);

7五、引用:用兩個變量來指向同一個內容,指向了同一個地方

75.一、引用是什麼

在 PHP 中引用意味着用不一樣的名字訪問同一個變量內容,變量名和變量內容是不同的, 所以一樣的內容能夠有不一樣的名字。引用能夠被看做是 Unix 文件系統中的硬連接。參見76

 75.二、引用作什麼

第一件事:PHP 的引用容許用兩個變量來指向同一個內容

(1)、若是對一個未定義的變量進行引用賦值、引用參數傳遞或引用返回,則會自動建立該變量。

<?php
function foo(&$var) { }

foo($a); // $a is "created" and assigned to null

$b = array();
foo($b['b']);
var_dump(array_key_exists('b', $b)); // bool(true)

$c = new StdClass;
foo($c->d);
var_dump(property_exists($c, 'd')); // bool(true)

(2)、一樣的語法能夠用在函數中,它返回引用,以及用在 new 運算符中(自 PHP 5 起,new 自動返回對象的引用)

$bar =& new fooclass();// php5 以後會報錯
$foo =& find_var($bar);

(3)、若是在一個函數內部給一個聲明爲 global 的變量賦於一個引用,該引用只在函數內部可見。能夠經過使用 $GLOBALS 數組避免這一點。

$a = 123;
$b = 456;
function a(){
global $a,$b;
$a = &$b;或$GLOBALS["a"] = &$b;
echo $a;
}
a();//456 或123
echo $a;//123 或456

把 global $var; 當成是 $var =& $GLOBALS['var']; 的簡寫。從而將其它引用賦給 $var 只改變了本地變量的引用。

第二件事:引用作的第二件事是用引用傳遞變量

能夠將一個變量經過引用傳遞給函數,這樣該函數就能夠修改其參數的值

function foo(&$var)//注意在函數調用時沒有引用符號——只有函數定義中有,光是函數定義就足夠使參數經過引用來正確傳遞了
{
    $var++;
}

$a=5;
foo($a);

三種狀況能夠經過引用傳遞

變量,例如 foo($a)

New 語句,例如 foo(new foobar())

從函數中返回的引用,例如:

function &bar()
{
    $a = 5;
    return $a;
}
foo(bar());//相見引用返回

任何其它表達式都不能經過引用傳遞

第三件事:引用作的第三件事是引用返回

 定義:用在當想用函數找到引用應該被綁定在哪個變量上面時

不要用返回引用來增長性能,引擎足夠聰明來本身進行優化。僅在有合理的技術緣由時才返回引用

class foo {
    public $value = 42;

    public function &getValue() {
        return $this->value;
    }
}

$obj = new foo;
$myValue = &$obj->getValue(); // $myValue is a reference to $obj->value, which is 42.
$obj->value = 2;
echo $myValue;                // prints the new value of $obj->value, i.e. 2.

//和參數傳遞不一樣,這裏必須在兩個地方都用 & 符號——指出返回的是一個引用,而不是一般的一個拷貝,一樣也指出 $myValue 是做爲引用的綁定,而不是一般的賦值。

75.三、引用不是什麼

引用不是指針

function foo(&$var)
{
    $var =& $GLOBALS["baz"];
}
foo($bar);

var只能更改baz,不能更改bar;

75.三、取消引用

當 unset 一個引用,只是斷開了變量名和變量內容之間的綁定。這並不意味着變量內容被銷燬了

75.四、引用定位

許多 PHP 的語法結構是經過引用機制實現的

當用 global $var 聲明一個變量時實際上創建了一個到全局變量的引用,等於$var =& $GLOBALS["var"];

在一個對象的方法中,$this 永遠是調用它的對象的引用

7六、unix文件系統中的硬連接和軟鏈接 

 
 
 
 
 
 
 
 

硬連接:

通常狀況下,文件名和inode號碼是"一一對應"關係,每一個inode號碼對應一個文件名。可是,Unix/Linux系統容許,多個文件名指向同一個inode號碼。

這意味着,能夠用不一樣的文件名訪問一樣的內容;對文件內容進行修改,會影響到全部文件名;可是,刪除一個文件名,不影響另外一個文件名的訪問。這種狀況就被稱爲"硬連接"(hard link)。

共用同一個索引的許多不一樣名文件,修改一個文件會影響全部其餘的文件,可是刪除單個文件其餘文件依然存在,只有在全部硬連接鏈接的文件都被刪除以後,inode纔會被釋放。

軟鏈接:

文件A和文件B的inode號碼雖然不同,可是文件A的內容是文件B的路徑。讀取文件A時,系統會自動將訪問者導向文件B。所以,不管打開哪個文件,最終讀取的都是文件B。這時,文件A就稱爲文件B的"軟連接"(soft link)或者"符號連接(symbolic link)。

這意味着,文件A依賴於文件B而存在,若是刪除了文件B,打開文件A就會報錯:"No such file or directory"。這是軟連接與硬連接最大的不一樣:文件A指向文件B的文件名,而不是文件B的inode號碼,文件B的inode"連接數"不會所以發生變化。

7七、可變變量

$a = 'Hello';

$$a = 'World';

用於數組$$a[1],摸棱兩可

${$a[1]}:$a[1]做爲變量

${$a}[1]:$$a做爲變量,並取出索引1

類中數組屬性:

$fool->$arr[1]:先計算數組值,再取屬性

$fool->{$arr}[1]:先取屬性,再取數組值

超全局變量和$this不能做爲可變變量使用

7八、來自php以外的變量

 POST/GET html表單訪問數據

$_POST

$_REQUEST  //默認狀況下包含了 $_GET$_POST 和 $_COOKIE 的數組

$_GET

將 GET/POST/Cookie 變量導入到全局做用域中

import_request_variables('p or g or c', 'ud_'): bool //p表明post,g表明get,c表明cookie,ud_表明給變量加前綴

若是 PHP 指令 register_globals = on

html提交的變量自動導入到全局做用域,用import_request_variables更好

變量名中的點和空格被轉換成下劃線。例如 <input name="a.b" /> 變成了 $_REQUEST["a_b"] //因此儘可能規範表單中命名

7九、magic_quotes_gpc(php5.4-)配置將會把輸入的值先addslashes(),

addslashes()//該字符串爲了數據庫查詢語句等的須要在某些字符前加上了反斜線。這些字符是單引號(')、雙引號(")、反斜線(\)與 NUL(NULL 字符)

stripslashes()//正好相反效果

80、<input type="text" name="personal[name]"><br />
    <input type="text" name="personal[email]"><br /> 這樣傳到後端也是一個數組

8一、<input type="image" src="image.gif" name="sub" /> 點擊就圖片就會上傳 sub.x sub.y 傳到後臺將變成sub_x sub_y

8二、http cookies

Cookies 是一種在遠端瀏覽器端存儲數據並能追蹤或識別再次訪問的用戶的機制

Cookies 是 HTTP 信息頭中的一部分,所以 SetCookie 函數必須在向瀏覽器發送任何輸出以前調用

一旦設置 Cookie 後,下次打開頁面時可使用 $_COOKIE,$HTTP_COOKIE_VARS 和 $_REQUEST 讀取

若是想在僅僅一個 cookie 中設定多個值,考慮先在值上使用serialize() 或 explode() ??應該是implode()吧

8三、常量

 在腳本執行期間該值不能改變,常量默認爲大小寫敏感。傳統上常量標識符老是大寫的

合法的常量名以字母或下劃線開始,後面跟着任何字母,數字或下劃線

應該避免這樣作:(自定義常量不要以__開頭),和魔術常量衝突

不用管做用區域就能夠在腳本的任何地方訪問常量 在函數內也能全局?

8四、表達式

表達式是 PHP 最重要的基石。在 PHP 中,幾乎所寫的任何東西都是一個表達式。簡單但卻最精確的定義一個表達式的方式就是「任何有值的東西」

由於賦值操做的順序是由右到左的 $b = $a =5

8五、先後遞增

$a = ++$b,前遞增,寫作「++$variable」,求增長後的值(PHP 在讀取變量的值以前,增長變量的值,於是稱之爲「前遞增」)。

$a = $b++,後遞增,寫作「$variable++」,求變量未遞增以前的原始值(PHP 在讀取變量的值以後,增長變量的值,於是叫作「後遞增」)

8六、組合的運算賦值表達式

$a += 3

任何二元運算符均可以用運算賦值模式,例如「$a -= 5」(從變量 $a 的值中減去 5),「$b *= 7」

8七、語句

一條語句等於表達式(expr )加分號結尾

8八、運算符

運算符可按照其能接受幾個值來分組。一元運算符只能接受一個值,二元運算符可接受兩個值,三元運算符

三元條件運算符:$first ? $second : $third

8九、運算符優先級

若是優先級相同,那運算服結合方向決定改如何運算

https://www.php.net/manual/zh/language.operators.precedence.php

90、算術運算符

$a**$b 乘方 php5.6+ a的b次方

除法運算符老是返回浮點數

取模運算符的操做數在運算以前都會轉換成整數 %,取模運算符 % 的結果和被除數的符號(正負號)相同,即 $a % $b 的結果和 $a 的符號相同

9一、賦值運算符

基本運算符 =

引用賦值

new 運算符自動返回一個引用 php5+

9二、位運算 參見另外一個隨筆 http://www.javashuo.com/article/p-hygehers-n.html

9三、比較運算符

太空船比較符 $a<==>$b 當$a小於、等於、大於$b時 分別返回一個小於、等於、大於0的integer 值 php7+   -1 0 1

// Arrays
echo [] <=> []; // 0
echo [1, 2, 3] <=> [1, 2, 3]; // 0
echo [1, 2, 3] <=> []; // 1
echo [1, 2, 3] <=> [1, 2, 1]; // 1
echo [1, 2, 3] <=> [1, 2, 4]; // -1 一個一個比較

$a = (object) ["a" => "c"]; 
$b = (object) ["a" => "b"]; 
echo $a <=> $b; // 1
 
// 只比較值

$a = (object) ["a" => "b", "b" => "b"]; 
$b = (object) ["b" => "b", "a" => "a"];

先排序

  //abbb

  //aabb

而後比較,第二位分勝負
echo $a <=> $b; // 1

NULL 合併操做符 $a??$b 從左往右第一個存在且不爲 NULL 的操做數。若是都沒有定義且不爲 NULL,則返回 NULL php7+

9五、多種類型比較時

一、object>array>其餘任何類型 

二、array間比較

  具備較少成員的數組較小,若是運算數 1 中的鍵不存在於運算數 2 中則數組,則運算數2比較大,不然挨個值比較

三、object間的比較 php5+

當使用比較運算符(==)比較兩個對象變量時,比較的原則是:若是兩個對象的屬性和屬性值 都相等,並且兩個對象是同一個類的實例,那麼這兩個對象變量相等。

而若是使用全等運算符(===),這兩個對象變量必定要指向某個類的同一個實例(即同一個對象)

9四、Object of class stdClass could not be converted to string 內置stdClass類沒法轉成字符串
9五、因爲浮點數的內部表達方式,不該比較兩個浮點數是否相等
9六、三元運算符可省略中間那部分 表達式  expr1 ?: expr3 在  expr1 求值爲 TRUE 時返回 expr1,不然返回 expr3 php5.3+
此表達式將返回第一個非false的值
echo 0?:0?:0?:0?:1?:0;//1
9七、錯誤控制運算符@
將其放置在一個 PHP 表達式以前,該表達式可能產生的任何錯誤信息都被忽略掉
不能把它放在函數或類的定義以前,也不能用於條件結構例如  if 和  foreach 等,只能放在表達式中(若是能從某處獲得值,就能在它前面加上 @ 運算符)
若是用  set_error_handler() 設定了自定義的錯誤處理函數,仍然會被調用,可是此錯誤處理函數能夠(而且也應該)調用 error_reporting(),而該函數在出錯語句前有 @ 時將返回 0, or die();
9八、若是激活了 track_errors 特性,表達式所產生的任何錯誤信息都被存放在變量 $php_errormsg 中  

ini_set("track_errors", true);
printf(ini_get("track_errors"));

$file = @file('a.txt');

echo $php_errormsg;

9九、自定義錯誤處理函數 set_error_handler(callback, 錯誤級別);

 1 function myErrorHandler($errno, $errstr, $errfile, $errline){//錯誤級別,整形; 錯誤字符串;錯誤文件名;錯誤所在行號
 2     //error_reporting的設置對此機制無效,或者經過@過來的錯誤也會調用,依舊會調用這個函數,
 3     //設定當當前錯誤不在設定的error_reporting級別時,函數不作處理
 4     if(!(error_reporting()& $errno))
 5         return false;//如返回false, error_types 裏指定的錯誤類型都會繞過 PHP 標準錯誤處理程序, 除非回調函數返回了 FALSE
 6     switch ($errno) {
 7     case E_USER_ERROR:
 8         echo "<b>My ERROR</b> [$errno] $errstr<br />\n";
 9         echo "  Fatal errors on line $errline in file $errfile";
10         echo ", PHP " . PHP_VERSION . " (" . PHP_OS . ")<br />\n";
11         echo "Aborting...<br />\n";
12         exit(1);
13         break;
14 
15     case E_USER_WARNING:
16         echo "<b>My WARNING</b> [$errno] $errstr<br />\n";
17         break;
18 
19     case E_USER_NOTICE:
20         echo "<b>My NOTICE</b> [$errno] $errstr<br />\n";
21         break;
22     default:
23         echo "Unknown errors type: [$errno] $errstr<br />\n";
24         break;
25     }
26     //不執行默認處理函數
27     return true;
28 }
29 set_error_handler("myErrorHandler");
30 if(1==1){
31     trigger_error("測試錯誤", E_USER_ERROR);
32     //My ERROR [256] 測試錯誤
33     //Fatal errors on line 57 in file H:\mc\webroot\index.php, PHP 7.3.7 (WINNT)
34     //Aborting...
35 }

 

100、error_reporting();設置或返回錯誤級別

10一、執行運算符`` PHP 將嘗試將反引號中的內容做爲 shell 命令來執行,並將其輸出信息返回

10二、遞增/遞減運算符不影響布爾值。遞減 NULL 值也沒有效果,可是遞增 NULL 的結果是 1

1 $a = null;
2 $b = ++$a;
3 echo $b;//1

 10三、邏輯運算符異或xor 一個爲true 一個爲false才爲true

字符串運算符 .

10四、數組運算符

$a + $b 聯合 $a 和 $b 的聯合。運算符把右邊的數組元素附加到左邊的數組後面,兩個數組中都有的鍵名,則只用左邊數組中的,右邊的被忽略
$a == $b 相等 若是 $a 和 $b 具備相同的鍵/值對則爲 TRUE
$a === $b 全等 若是 $a 和 $b 具備相同的鍵/值對而且順序和類型都相同則爲 TRUE

 10五、類型運算符instanceof

繼承類也是true

$a = (object)[1=>123, 0=>321];

echo $a instanceOf stdClass;//1

雖然 instanceof 一般直接與類名一塊兒使用,但也可使用對象或字符串變量

$c = "stdClass";

echo $a instanceOf $c;

$b = (object)[1,2,3];

echo $a instanceOf $b

10六、do-while 保底運行一次

$i = 0;
do {
   echo $i;
} while ($i > 0);

10七、for循環

for(;;;)表達式能夠爲空,能夠用都好分開,判斷第二個表達式時,只取最後一個的值

for ($i = 1; $i <= 10; print $i, $i++);//12345678910 省略打法

10八、foreach

foreach 僅可以應用於數組和對象

因爲 foreach 依賴內部數組指針,在循環中修改其值將可能致使意外的行爲

養成習慣unset 最後一個value

$arr = array(1, 2);
foreach ($arr as &$value) {
    $value = $value * 2;
}
// $arr is now array(2, 4, 6, 8)
var_dump($arr);//array(2) { [0]=> int(2) [1]=> &int(4) }
unset($value); // 最後取消掉引用
var_dump($arr);//array(2) { [0]=> int(2) [1]=> int(4) }

10九、嵌套數組用list解包

$arr = [[1,2],[3,4]];
foreach($arr as list($a, $b)){
    echo $a.PHP_EOL.$b.PHP_EOL;//1 2 3 4 
}

1十、跳出循環或switch

break 結束當前 forforeachwhiledo-while 或者 switch 結構的執行

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

5.4.0 break 0; 再也不合法。這在以前的版本被解析爲 break 1;
5.4.0 取消變量做爲參數傳遞(例如 $num = 2; break $num;

break 1 代筆推出當前循環或switch,以此類推

continue 在循環結構用用來跳過本次循環中剩餘的代碼並在條件求值爲真時開始執行下一次循環,一樣switch也能夠用continue

5.4.0 continue 0; 再也不合法。這在以前的版本被解析爲 continue 1;
5.4.0 取消變量做爲參數傳遞(例如 $num = 2; continue $num;)。

1十一、鬆散比較== 嚴格比較===

1十二、switch作鬆散比較,內部continue至關於break效果

switch比elseif更高效

容許使用分號代替 case 語句後的冒號

case 'tuborg';
case 'carlsberg';

11三、流程控制的替代語法

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

 

$a=6;
if($a == 5):
    echo '5';
elseif($a == 6):
    echo '6';
else:
    echo 'else';
endif;
<?php $foo = 2?>
<?php switch ($foo): ?>
<?php case 1: ?>
    .(switch 和 case之間不能有其餘html輸出,空格也不行)
<?php case 2: ?>
    ..    
<?php endswitch ?>

11四、declare ticks encoding

declare (directive)
statement
Tick(時鐘週期)是一個在 declare 代碼段中解釋器每執行 N 條可計時的低級語句就會發生的事件。
不是全部語句均可計時。一般條件表達式和參數表達式都不可計時。

在每一個 tick 中出現的事件是由 register_tick_function() 來指定的。

declare(ticks = 1);
function tick_handler(){
    global $a;
    echo "handler runs once $a</br>";
    $a++;
}
//函數register_tick_function註冊時運行一次!!
register_tick_function('tick_handler');//handler runs once
$a = 1;//handler runs once 1

if ($a > 0) {
    
    $a += 2;//handler runs once 4
    
    echo ($a);//5handler runs once 5
    
}

 調用類中的函數

declare(ticks=1);
class TestDeclare{
    public function my_method($arg){
        echo $arg;
    }
}
$object = new TestDeclare();
register_tick_function([&$object, 'my_method'], 'test');
$a = 1;
$b = 2;

encording 能夠用 encoding 指令來對每段腳本指定其編碼方式

declare(encoding='ISO-8859-1');

11五、return

一、函數內return,離開結束函數執行,並返回他的參數;

二、全局範圍,停止當前腳本運行

echo 123;//123
return ;
echo 456;

include/require 返回值

a.php
<?php
include("b.php");
echo "a";
?>

b.php
<?php
echo "b";
return;
?>

include/require return以後的函數亦可搜索到

a.php 
<?php 
include 'b.php'; 

foo(); 
?> 

b.php 
<?php 
return; 

function foo() { 
     echo 'foo'; 
} 
?> 

11六、絕對路徑

在 Windows 下以盤符或者 \ 開頭,在 Unix/Linux 下以 / 開頭(撇捺Linux先行

11七、include

php.ini 中include_path設置默認include的目錄,若是沒有給出目錄,只有文件名,則按照這個路徑去找,沒找到的時候,纔在當前的目錄去找,因此爲了提升效率,對於當前的路徑,用.\(windows)前綴,..\表明父目錄,以此類推,以絕對路徑表示也是能夠的。

函數內include的變量,做用域同函數內變量一致

function a(){
    require '.\inc.php'; 
    echo $a.$b;//12 做用於在函數內
}
a();
echo $a.$b;//null

php.ini 設置allow_url_include爲On時,可include url文件,且爲php文件後綴,且文件爲php代碼

處理返回值:在失敗時 include 返回 FALSE 而且發出警告。成功的包含則返回 1,return 另說

// won't work, evaluated as include(('vars.php') == TRUE), i.e. include('')
if (include('inc.php') == TRUE) {
    echo 'OK';
}

// works
if ((include 'inc.php') == TRUE) {
    echo 'OK';
}
//include 不要用括號便可

另外一個將 PHP 文件「包含」到一個變量中的方法是用輸出控制函數結合 include 來捕獲其輸出

//index.php
function a($fileName){
    if(is_file($fileName)){
        ob_start();
        include $fileName;
        $contents = ob_get_contents();
        ob_end_clean();
        return $contents;
    }
    return false;
}
echo a('.\inc.php');//123
//inc.php
echo 123;

require和inlcude幾乎徹底相同,除了處理失敗的方式不一樣以外。require 在出錯時產生 E_COMPILE_ERROR 級別的錯誤。換句話說將致使腳本停止而 include 只產生警告(E_WARNING),腳本會繼續運行。require嚴父啊

11八、goto操做符 php5.3+

能夠用來跳轉到程序中的另外一位置,該目標位置能夠用目標名稱加上冒號來標記

goto a;
echo 123;//跳過不執行
a:
echo 456;//456

目標位置只能位於同一個文件和做用域;

沒法跳入到任何循環或者 switch 結構中。能夠跳出循環或者 switch,一般的用法是用 goto 代替多層的 break

for($i = 0, $j = 50; $i < 100; $i++){
    while($j--){
        if($j==48) goto a;
    }
}
echo '123';
a:
echo 'j hits 48';

 

11九、換行\r\n,必須在雙引號中,且web前端看不出換行,源代碼處換行,web換行用</br>

 120、引用

//變量引用
$a = 1;
$b = &$a;
$c = &$b;
$c = 2;
echo $a;//2
//引用傳遞
//一、函數的引用傳遞
function a(&$a){
    $a++;
}
$d = 3;
a($d);
echo $d;//4
//二、對象的引用傳遞,對象的實例化經過引用實現
class A{
    var $a = '123';
}
$e = new a();
$f = $e;
$f->a = '456';
echo $e->a;//456
//global 至關於引用全局變量,只在函數內部有效
//把 global $var; 當成是 $var =& $GLOBALS['var'],從而將其它引用賦給 $var 只改變了本地變量的引用
$a = 123;
$b = 456;
function c(){
    global $a,$b;
    $a = &$b;//或$GLOBALS["a"] = &$b;
    echo $a;
}
c();//456 或123
echo $a;//123 或456
//引用返回
function &b(){
    static $b = 0;//static 靜態變量僅在局部函數域中存在,只執行一次
    $b++;
    echo $b;
    return $b;
}
$g = &b();//1
$g = 5;
b();//6

 12一、函數

用戶自定義函數

函數名和 PHP 中的其它標識符命名規則相同。有效的函數名以字母或下劃線打頭,後面跟字母,數字或下劃線

任何有效的 PHP 代碼都有可能出如今函數內部,甚至包括其它函數和定義

a();//可全局搜索a func
b();//當fun a 運行後,fun b已定義,因此此時能夠調用
function a(){        
    function b(){
        echo 123;
    }
    b();//只能放在定義後面,放在前面則找不到函數
}

條件式

$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 中的全部函數和類都具備全局做用域,能夠定義在一個函數以內而在以外調用,反之亦然

PHP 不支持函數重載,也不可能取消定義或者重定義已聲明的函數

函數的參數

傳參的三種方式

一、按值傳遞參數

二、經過引用傳遞參數

默認狀況下,函數參數經過值傳遞(於是即便在函數內部改變參數的值,它並不會改變函數外部的值)。若是但願容許函數修改它的參數值,必須經過引用傳遞參數

三、默認參數

默認值必須是常量表達式,不能是諸如變量,類成員,或者函數調用等

function a($c, $b = 'abc', $a = 'hij'){//默認要放在最右邊
    echo $c.$b.$a;
}
a('123');//123abchij
a('123', 'efg');//123efghij

參數的類型申明(類型提示)

類型聲明容許函數在調用時要求參數爲特定類型。 若是給出的值類型不對,那麼將會產生一個錯誤: 在PHP 5中,這將是一個可恢復的致命錯誤,而在PHP 7中將會拋出一個TypeError異常

 

Class/interface name The parameter must be an instanceof the given class or interface name.//類或接口  PHP 5.0.0
self The parameter must be an instanceof the same class as the one the method is defined on. This can only be used on class and instance methods. PHP 5.0.0
array The parameter must be an array. PHP 5.1.0
callable The parameter must be a valid callable. PHP 5.4.0
bool The parameter must be a boolean value. PHP 7.0.0
float The parameter must be a floating point number. PHP 7.0.0
int The parameter must be an integer. PHP 7.0.0
string The parameter must be a string. PHP 7.0.0

不是正確的類型都將看做爲類或接口,因此要寫正確的bool,而boolean將視爲類

function a($a, $b){
     return $a<=>$b;
 }
 function test(callable $param, int $a, int $b = 2) {
     return $param($a, $b);
 }
 echo test("a", 1);//-1

類繼承

class C {}
class D extends C {}//繼承於C

// 沒有繼承C
class E {}

function f(C $c) {
    echo get_class($c)."\n";
}

f(new C);//C
f(new D);//D
f(new E);//報錯

接口實現

interface I { public function f(); }
class C implements I { public function f() {} }//實現接口I

//未實現接口I
class E {}

function f(I $i) {
    echo get_class($i)."\n";
}

f(new C);//C
f(new E);//報錯

容許傳遞null,設置默認值爲null便可

class C {}

function f(C $c = null) {
    var_dump($c);
}

f(new C);
f(null);

默認狀況下,若是能作到的話,PHP將會強迫錯誤類型的值轉爲函數指望的標量類型

function b(string $a){//強迫自動轉爲string
    echo $a;
}
b(123);//123

嚴格模式

declare(strict_types = 1);//開啓嚴格模式
function a(float $a){//惟一的一個例外是能夠將integer傳給一個指望float的函數。
    echo $a;
}
a(123);//123

function b(string $a){
    echo $a;
}
b(123);//報錯

 可變數量的參數

php5.5以前,經過func_num_args()func_get_arg(),和 func_get_args() 

php5.6+,由由 ... 語法實現

經過...獲取可變參數

function a(&...$a){
    foreach($a as &$val){
        $val += 1;
    }
}
$a = 1;
$b = 2;
a($a, $b);
echo $a,$b;//23

經過...提供可變參數

function a($a, $b){
    return $a+$b;
}
echo a(...[1,2]);//3
$a = [1,2];
echo a(...$a);//3

結合類型申明

function a($a = 1, int ...$b){
    foreach($b as $val){
        $a += $val;
    }
    return $a;
}
echo a(2,2,2);//6

返回值

參見return,如無return,則返回值爲null

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

不要問爲何,這是規定

function &returns_reference()
{
    return $someref;
}

$newref =& returns_reference();

返回值的類型聲明 php7+

支持類型與參數的相同,嚴格類型也一樣影響

function sum($a, $b): float{
    return $a + $b;
}
var_dump(sum(1, 2));//float(3)

返回一個對象

class C{}
function get_C(): C{
    return new C;
}
var_dump(get_C());

可變函數

變量名後有圓括號,可變函數能夠用來實現包括回調函數,函數表在內的一些用途,只能用於用戶自定義函數

function a(){
    echo 123;
}
$a = 'a';
$a();//123

調用一個對象的方法

class A{
    function c(){
        $name = 'b';
        $this->$name();
    }
    function b(){
        echo 'I am here!';
    }
}
$a = new A();
$name = 'c';
$a->$name();//I am here!

複雜的callables

class Foo
{
    static function bar()
    {
        echo "bar\n";
    }
    function baz()
    {
        echo "baz\n";
    }
}

$func = ["Foo", "bar"];
$func();
["Foo", "bar"]();//不要問爲何,規定這樣
$func = [new Foo, "baz"];
$func(); //"baz"
[new Foo, "baz"]();//不要問爲何,規定這樣
//php7.0+
$func = "Foo::bar";
$func();
"Foo::bar"();//不要問爲何,規定這樣

內置函數

判斷函數是否存在

function_exists() — 若是給定的函數已經被定義就返回 TRUE

匿名函數 

 Anonymous function 也叫閉包函數(Closures)

容許 臨時建立一個沒有指定名稱的函數。最常常用做回調函數(callback)參數的值 

匿名函數目前是經過Closure類實現的

$a =  function ($b){
    echo $b;
};
$a('xx');//xx
var_dump($a);//object(Closure)#1 (1) { ["parameter"]=> array(1) { ["$b"]=> string(10) "" } }

閉包函數也能夠做爲變量的值來使用。PHP 會自動把此種表達式轉換成內置類 Closure 的對象實例。把一個 closure 對象賦值給一個變量的方式與普通變量賦值的語法是同樣的,最後也要加上分號

$a = 'xx';
function ($b){
    echo $b;
}($a);//報錯,沒有這種寫法
function call_back($b, $c, $func){
    return $func($b, $c);
};
echo call_back(3, 2, function($b, $c){
    return $b*$c;
});//6

 閉包能夠從父做用域中繼承變量。任何此類變量均可以用use語言結構傳遞進去。

超全局變量或$this和參數重名,這些穿不進去 php7.1+

 閉包的父做用域是定義該閉包的函數時的做用域

$msg1 = 'hello';
$msg2 = 'world';
$a = function()use($msg1, $msg2){//定義的時候已經傳入
    echo $msg1.$msg2;
};
$a();//helloworld
$msg1 = '額';
$a();//helloworld
$b = function()use(&$msg1,&$msg2){//傳引入
    echo $msg1.$msg2;
};
$b();//額world
$msg1 = 'hello';
$b();//helloworld
//array_walk(array, function, arg..),爲數組的每個成員執行function,並傳入參數
function getStr($value, $key, $arg){
    echo $value.' got a id of '.$key.' in '.$arg;
}
$arr = ['a'=>'tony', 'b'=>'kevin'];
array_walk($arr, 'getStr', '2019');//tony got a id of a in 2019kevin got a id of b in 2019


// 一個基本的購物車,包括一些已經添加的商品和每種商品的數量。
// 其中有一個方法用來計算購物車中全部商品的總價格,該方法使
// 用了一個 closure 做爲回調函數。
class Cart
{
    const PRICE_BUTTER  = 1.00;
    const PRICE_MILK    = 3.00;
    const PRICE_EGGS    = 6.95;

    protected   $products = array();
    
    public function add($product, $quantity)
    {
        $this->products[$product] = $quantity;
    }
    
    public function getQuantity($product)
    {
        return isset($this->products[$product]) ? $this->products[$product] :
               FALSE;
    }
    
    public function getTotal($tax)
    {
        $total = 0.00;
        
        $callback =
            function ($quantity, $product) use ($tax, &$total)
            {
                $pricePerItem = constant(__CLASS__ . "::PRICE_" .
                    strtoupper($product));//__CLASS__獲取當前類名,contant()返回一個常量的值
                $total += ($pricePerItem * $quantity) * ($tax + 1.0);
            };//父做用域在getTotal函數內,$tax和&total有效
        
        array_walk($this->products, $callback);
        return round($total, 2);;
    }
}
//加入購物車
$my_cart = new Cart;
$my_cart->add('butter', 2);
$my_cart->add('milk', 4);
$my_cart->add('eggs', 6);
//打出總價格,加上5%的稅
echo $my_cart->getTotal(0.05);//58.49

當類內的函數中有匿名函數,其中的$this,將會自動綁定到類上 php5.4+ 

如不須要綁定,則使用靜態的匿名函數

class Foo
{
    function __construct()
    {
        $func = static function() {
            var_dump($this);//Using $this when not in object context 
            //不在對象做用域中使用$this
        };
        $func();
    }
};
new Foo();

補充信息:Closure類

/*Closure對象
 有三個函數
 一、__construct 用於禁止實例化的構造函數
 二、bind複製一個閉包,綁定到制定的$this對象和類做用域,這個是bingTo的靜態版本
 三、bingTo複製當前閉包對象,綁定指定的$this對象和類做用域
 public Closure::bindTo ( object $newthis [, mixed $newscope = 'static' ] ) : Closure
 $newthis //新的this
 newscope 關聯到匿名函數的類做用域,或者 'static' 保持當前狀態。若是是一個對象,則使用這個對象的類型爲心得類做用域。 這會決定綁定的對象的 保護、私有成員 方法的可見性
 靜態閉包不能有綁定的對象( newthis 參數的值應該設爲 NULL)不過仍然能夠用 bindTo 方法來改變它們的類做用域
*/
class Student {
    public $name, $age;
    static $school = 'shuozhong';
    function __construct($name, $age) {
        $this->name = $name;
        $this->age = $age;
    }
    function getClosure($isStatic) {
        if($isStatic)
            return static function() { return __CLASS__; };
        return function() { return $this->val; };
    }
    
}
class Student1 {
    public $name, $age;
    static $school = 'guizhong';
    function __construct($name, $age) {
        $this->name = $name;
        $this->age = $age;
    }
    function getClosure($isStatic) {
        if($isStatic)
            return static function() { return __CLASS__; };
        return function() { return $this->val; };
    }
    
}

$func = function(){
    echo "My name is {$this->name} from ".static::$school." and I am {$this->age} </br>";
};

$sd1 = new Student('張三', 14);
$sd2 = new Student1('李四', 13);
//綁定$this和做用域
$newFunc = $func->bindTo($sd1);
$newFunc();//My name is 張三 from shuozhong and I am 14 
$newFunc = $func->bindTo($sd2);
$newFunc();//My name is 李四 from guizhong and I am 13 
//只綁定做用域
$func = function(){
    echo "My school is ".static::$school."</br>";
};
$newFunc = $func->bindTo(null, $sd1);
$newFunc();//My school is shuozhong
$newFunc = $func->bindTo(null, 'Student1');
$newFunc();//My school is guizhong
//爲了與靜態匿名函數比較
$newFunc = $func->bindTo($sd1);
$newFunc();//My school is shuozhong
//靜態匿名函數
$func = static function(){
    echo "My school is ".static::$school."</br>";
};
//$newFunc = $func->bindTo($sd1);//Cannot bind an instance to a static closure
$newFunc = $func->bindTo(null, $sd1);
$newFunc();//My school is shuozhong
//若是你只是想要複製一個匿名函數,能夠用 cloning 代替

 120、var_export()函數

$a = [1,23,4];
var_export($a);//array ( 0 => 1, 1 => 23, 2 => 4, ) 返回null
$b = var_export($a, true);//返回值
var_dump($b);//string(40) "array ( 0 => 1, 1 => 23, 2 => 4, )"

class B
{
    public $a = 123;
    public function c ()
    {
        echo 123;
    }
}

var_export(new B);//B::__set_state(array( 'a' => 123, )

12二、平方**

$a = 42;
echo $a**2;//1764

 12三、PHP中__FUNCTION__與__METHOD__的區別,主要在如下二點:
使用__FUNCTION__僅傳回函數名稱
使用__METHOD__傳回類名稱與函數名稱

12四、如何開啓log_error

log_errors = on

error_log = "路徑"

12五、compact(string[變量的名字])建立一個包含變量名和它們的值的數組

$firstname = "Peter";
$lastname = "Griffin";
$age = "41";

$result = compact("firstname", "lastname", "age");

print_r($result);
相關文章
相關標籤/搜索