1.字符串的使用
可將字符串當(dāng)作一個(gè)字符的集合來使用提完,可獨(dú)立訪問每個(gè)字符。僅適用于單字節(jié)字符(字母哗蜈、數(shù)字、半角標(biāo)點(diǎn)符號(hào)),像中文等不可用(utf8下奕坟,中文3字節(jié)表示)
$str = "abcd";
echo $str[3]; // d
echo $str{0}; // a
//另一種方式
也可以使用str_split把所有字符分割成數(shù)組祥款。
$strArr = str_spilt($str); //同樣不適合中文
Array
(
[0] => a
[1] => b
[2] => c
[3] => d
)
function mb_str_split($str){
return preg_split('/(?<!^)(?!$)/u', $str ); //反向預(yù)搜索
}
$str='博客';
mb_str_split($str);
打印結(jié)果如下:
Array
(
[0] => 博
[1] => 客
)
2.轉(zhuǎn)換類型
平時(shí) 我們知道在變量前,加上(int), (string), (float) 之類的即可進(jìn)行顯示轉(zhuǎn)換月杉,下面介紹一種刃跛,可直接轉(zhuǎn)換為null的 轉(zhuǎn)換,苛萎。
(unset) //轉(zhuǎn)換為NULL
$a = 'a';
$a = (unset)$a; //此時(shí)$a 為 NULL
//換種方式
$a = 'a';
unset($a);
dd($a);
//報(bào)錯(cuò)
PHP Notice: Undefined variable: a in test.php on line 39
Notice: Undefined variable: a in test.php on line 39
3.isset 和 empty, is_null 對(duì)變量的檢測
3.1 isset 要檢測變量不存在則桨昙, 返回 false; 但需要注意腌歉,變量是否本身為 Null值蛙酪, 如果是,也返回 false翘盖; 都不滿足則返回true了 桂塞。
為了更方便檢測變量是否存在,可使用
建議用array_key_exists判斷
$a = null;
$varExists = array_key_exists('a', get_defined_vars());
if($varExists){
echo '變量a是存在的';
}
3.2 empty馍驯, 檢測變量不存在阁危,與各個(gè)空值,0值都為true泥彤, 否則為 false
3.3 is_null
當(dāng)參數(shù)滿足下面三種情況時(shí)欲芹,is_null()將返回TRUE,其它的情況就是FALSE
1吟吝、它被賦值為NULL
2菱父、它還沒有賦值
3、它未定義剑逃,相當(dāng)于unset(),將一個(gè)變量unset()后浙宜,不就是沒有定義嗎
4.static 的部分用法
我們都知道 static 可以直接定義靜態(tài)變量和 靜態(tài)方法, 無論是調(diào)用靜態(tài)變量和靜態(tài)方法蛹磺, 用 :: 即可調(diào)用粟瞬, 如果是本類,則使用self 調(diào)用萤捆, 如果是在類
外部裙品,則使用類名進(jìn)行調(diào)用, 但這里對(duì)其不進(jìn)行過多贅述俗或,這些都是比較常用市怎。下面講下不常用的。
static在類中的延遲靜態(tài)綁定辛慰;
延遲靜態(tài)綁定是指允許在一個(gè)靜態(tài)繼承的上下文中引用被調(diào)用類区匠。
延遲綁定的意思為:static::不再為定義當(dāng)前方法所在的類,而是實(shí)際運(yùn)行時(shí)所在的類帅腌。
(總的意思就是子類繼承了父類后驰弄,父類中使用了一個(gè)靜態(tài)方法或變量麻汰,如static::A(), 但方法A不存在于父類中戚篙,
存在于子類中五鲫,這樣寫是正確的,不會(huì)因?yàn)榉椒ú淮嬖诙鴪?bào)錯(cuò)已球,因?yàn)閟tatic 修飾的A 會(huì)在執(zhí)行過程中,綁定到具體的子類
上智亮,只要保證子類有此方法即可)
注:它可以用于(但不限于)靜態(tài)方法的調(diào)用忆某。
self::弃舒,代表本類(當(dāng)前代碼所在類)
永遠(yuǎn)代表本類聋呢,因?yàn)樵陬惥幾g時(shí)已經(jīng)被確定。
即颠区,子類調(diào)用父類方法削锰,self卻不代表調(diào)用的子類。
parent:: 代表父類
static::毕莱,代表本類(調(diào)用該方法的類)
用于在繼承范圍內(nèi)引用靜態(tài)調(diào)用的類器贩。
運(yùn)行時(shí),才確定代表的類朋截。
static::不再被解析為定義當(dāng)前方法所在的類蛹稍,而是在實(shí)際運(yùn)行時(shí)計(jì)算的。
除了簡單的static延遲綁定的用法部服,還有一種轉(zhuǎn)發(fā)調(diào)用唆姐,
forward_static_call_array()(該函數(shù)只能在方法中調(diào)用)將轉(zhuǎn)發(fā)調(diào)用信息(不過多贅述,類似于本節(jié)的第8點(diǎn)廓八,PHP反射)奉芦,
概括實(shí)例如下:
class A {
public static function fooStatic() {
static::who();
}
public static function who() {
echo __CLASS__."aaa\n";
}
}
class B extends A {
public static function testStatic() {
A::fooStatic();
B::fooStatic();
C::fooStatic();
parent::fooStatic();
self::fooStatic();
}
public static function who() {
echo __CLASS__."bbb\n";
}
}
class C extends B {
public static function who() {
echo __CLASS__."ccc\n";
}
}
C::testStatic();
大家一起來得到答案:
5. array_merge 和 + , 合并數(shù)組
5.1 array_merge 合并兩個(gè)或多個(gè)數(shù)組的時(shí)候剧蹂, 如果鍵名是非數(shù)字声功,則會(huì)自動(dòng)合并到一起,但若出現(xiàn)重復(fù)的鍵名国夜,后面的會(huì)覆蓋前面的减噪。若鍵名為數(shù)字短绸,其會(huì)根據(jù)前一個(gè)數(shù)組的索引值车吹,自動(dòng)給后面的更改索引值為前面的遞增筹裕,也就是說會(huì)改變原有的鍵名。
5.2 + 合并數(shù)組窄驹, 使用+ 號(hào) 合并數(shù)組朝卒,鍵名相同的情況下,最先出現(xiàn)的鍵名會(huì)被保留乐埠, 并且即使鍵名是數(shù)字抗斤,也不會(huì)被重新編排,這個(gè)特性對(duì)部分業(yè)務(wù)場景會(huì)非常有用丈咐。
5.3 array_push, 僅僅是把對(duì)應(yīng)值完全放到數(shù)組末尾瑞眼, 原來的結(jié)構(gòu)會(huì)被保留,整個(gè)作為一個(gè)新的值棵逊, 鍵名跟著前一個(gè)遞增伤疙。這與array_merge 有所區(qū)別
5.4 array_combine, 兩個(gè)參數(shù)辆影, 第一個(gè)參數(shù)徒像,作為新數(shù)組的鍵, 第二個(gè)參數(shù)作為新數(shù)組的值蛙讥。 并不是給原有數(shù)組增添新值锯蛀。所以其實(shí)他不同于 上面三個(gè)的作用。 光從名字上看容易混淆次慢。
$a = ['a', 'b', 'c'];
$b = ['5' => 'test'];
$c = [1, 2, 3];
$arrayMerge = array_merge($a, $b);
$arrayPlus = $a + $b;
$arrayCombine = array_combine($a, $c);
array_push($a, $b);
// $arrayMerge
Array
(
[0] => a
[1] => b
[2] => c
[3] => test
)
// $arrayPlus
Array
(
[0] => a
[1] => b
[2] => c
[5] => test
)
// $arrayCombine
Array
(
[a] => 1
[b] => 2
[c] => 3
)
// array_push
Array
(
[0] => a
[1] => b
[2] => c
[3] => Array
(
[5] => test
)
)
6. 指針
數(shù)組的內(nèi)部指針:
current/pos 返回當(dāng)前被內(nèi)部指針指向的數(shù)組單元的值旁涤,并不移動(dòng)指針。
key 返回?cái)?shù)組中當(dāng)前單元的鍵名经备,并不移動(dòng)指針
next 將數(shù)組中的內(nèi)部指針向前移動(dòng)一位拭抬,并返回移動(dòng)后當(dāng)前單元的值。先移動(dòng)侵蒙,再取值造虎。
prev 將數(shù)組的內(nèi)部指針倒回一位,并返回移動(dòng)后當(dāng)前單元的值先移動(dòng)纷闺,再取值算凿。
end 將數(shù)組的內(nèi)部指針指向最后一個(gè)單元,并返回最后一個(gè)單元的值
reset 將數(shù)組的內(nèi)部指針指向第一個(gè)單元犁功,并返回第一個(gè)數(shù)組單元的值
each 返回?cái)?shù)組中當(dāng)前的鍵/值對(duì)并將數(shù)組指針向前移動(dòng)一步氓轰。
返回的是一個(gè)由鍵和值組成的長度為4的數(shù)組,下標(biāo)0和key表示鍵浸卦,下標(biāo)1和value表示值
在執(zhí)行each()之后署鸡,數(shù)組指針將停留在數(shù)組中的下一個(gè)單元或者當(dāng)碰到數(shù)組結(jié)尾時(shí)停留在最后一個(gè)單元。如果要再用 each 遍歷數(shù)組,必須使用 reset()靴庆。
1. 以上指針操作函數(shù)时捌,除了key(),若指針移出數(shù)組炉抒,則返回false奢讨。而key()移出則返回null。
2. 若指針非法焰薄,不能進(jìn)行next/prev操作拿诸,能進(jìn)行reset/end操作
3. current/next/prev 若遇到包含空單元(0或"")也會(huì)返回false。而each不會(huì)塞茅!
list 把數(shù)組中的值賦給一些變量亩码。list()是語言結(jié)構(gòu),不是函數(shù)野瘦。
僅能用于數(shù)字索引的數(shù)組并假定數(shù)字索引從0開始
/* 可用于交換多個(gè)變量的值 */
list($a, $b) = array($b, $a);
例:list($drink, , $power) = array('coffee', 'brown', 'caffeine');
1. 復(fù)制數(shù)組蟀伸,其指針位置也會(huì)被復(fù)制。
特例:如果數(shù)組指針非法缅刽,則拷貝的數(shù)組指針會(huì)重置啊掏,而原數(shù)組的指針不變。
【指針問題】
誰第一個(gè)進(jìn)行寫操作衰猛,就會(huì)開辟一個(gè)新的值空間迟蜜。與變量(數(shù)組變量)值傳遞給誰無關(guān)。
數(shù)組函數(shù)current()被定義為寫操作啡省,故會(huì)出現(xiàn)問題娜睛。
foreach遍歷的是數(shù)組的拷貝,當(dāng)被寫時(shí)卦睹,才會(huì)開辟一個(gè)新的值空間畦戒。
即,foreach循環(huán)體對(duì)原數(shù)組進(jìn)行寫操作時(shí)结序,才會(huì)出現(xiàn)指針問題障斋。
如果開辟新空間時(shí)指針非法,則會(huì)初始化指針徐鹤。
2. 如果指針位置出現(xiàn)問題垃环,則reset()初始化一下就可解決。
7. 序列化(串行化)
# 數(shù)據(jù)傳輸均是字符串類型
# 除了資源類型返敬,均可序列化
# 序列化在存放數(shù)據(jù)時(shí)遂庄,會(huì)存放數(shù)據(jù)本身,也會(huì)存放數(shù)據(jù)類型
作用:1.在網(wǎng)絡(luò)傳輸數(shù)據(jù)時(shí)劲赠;2.為了將數(shù)組或?qū)ο蠓旁诖疟P時(shí)
# 序列化
serialize 產(chǎn)生一個(gè)可存儲(chǔ)的值的表示
string serialize ( mixed $value )
- 返回字符串涛目,此字符串包含了表示value的字節(jié)流秸谢,可以存儲(chǔ)于任何地方。
- 有利于存儲(chǔ)或傳遞 PHP 的值霹肝,同時(shí)不丟失其類型和結(jié)構(gòu)钮追。
# 反序列化
unserialize 從已存儲(chǔ)的表示中創(chuàng)建PHP的值
mixed unserialize ( string $str [, string $callback ] )
- 對(duì)單一的已序列化的變量進(jìn)行操作,將其轉(zhuǎn)換回PHP的值阿迈。
8.PHP反射
有時(shí)候我們我們?yōu)榱四芙⒏玫拇a結(jié)構(gòu),并能復(fù)用代碼轧叽,就需要用到一些語言的特性來幫助我們完成任務(wù)苗沧,比如我們這次新建的倉庫 trinity_middle_service, 我們需要利用PHP自帶函數(shù)炭晒, 如call_user_func_array待逞, 即可簡單實(shí)現(xiàn)分發(fā)。使用方式如下:
class Order{
public function getBasicInfo($orderId, $write = false)
{
}
}
$detailServiceInstance = new Order();
$functionName = 'getBasicInfo';
$params[0] = 1000001; //或 $params['orderId'] = 1000001
$params[1] = true; //或 $params['write'] = true
call_user_func_array([$detailServiceInstance, $functionName], $params);
從以上代碼可看出网严, call_user_func_array 第一個(gè)參數(shù)是個(gè)數(shù)組识樱, 該數(shù)組中0下標(biāo)的值 為 一個(gè)類的實(shí)例, 1下標(biāo)的 是這個(gè)實(shí)例中存在的方法震束; 第二個(gè)參數(shù)即 對(duì)應(yīng)函數(shù)需要的參數(shù)了怜庸,該參數(shù)為數(shù)組形式,call_user_func_array 會(huì)自動(dòng) 按順序?qū)?yīng)每一個(gè)參數(shù)垢村,所以在這里割疾,參數(shù)的順序很重要,無論是使用數(shù)字鍵名或字符鍵名嘉栓,都必須一一對(duì)應(yīng)函數(shù)具體的參數(shù)宏榕,這樣才能正確實(shí)現(xiàn)函數(shù)的分發(fā)。
8.1 反射的應(yīng)用
使用call_user_func_array侵佃,我們可以簡單的實(shí)現(xiàn)分發(fā)麻昼,并且各個(gè)參數(shù),也都很清晰馋辈。但是如果需要更加靈活的運(yùn)用這個(gè)函數(shù)抚芦,我們還需要引入PHP的反射機(jī)制,如 PHP自帶的 ReflectionMethod 類迈螟,
我們可以通過這個(gè)類燕垃,來直接獲取到某個(gè)類中具體方法的各類信息,如參數(shù)個(gè)數(shù)井联,參數(shù)名卜壕,是否有默認(rèn)值等等。代碼如下:
$object = new Order();
$functionName = 'getBasicInfo';
$reflectionObj = new \ReflectionMethod($object, $functionName);
//通過以上的代碼后烙常,就可以直接通過$reflectionObj獲取相關(guān)信息了轴捎,如下
$reflectionObj->isPublic(); //可判斷該方法是否為公有方法鹤盒, 還有isPrivate, isProtected, isStatic等等
$reflectionObj->getParameters(); //可獲取該方法所有參數(shù),是個(gè)數(shù)組侦副,可 foreach獲取具體的參數(shù)
foreach($reflectionObj->getParameters() as $arg) {
if(array_key_exists($arg->name, $params)) {
$callParams[$arg->name] = $params[$arg->name];
} else {
$paramVal = null;
if ($arg->isOptional()) { // 或使用isDefaultValueAvailable侦锯, 檢測是否有可用的默認(rèn)值
$paramVal = $arg->getDefaultValue();
}
$callParams[$arg->name] = $paramVal;
}
}
具體參數(shù): https://www.php.net/manual/zh/class.reflectionmethod.php
還有 ReflectionClass 可以獲取一些類的信息,用法都是類似的秦驯。
8.2 調(diào)用不存在的方法
__call & __callStatic (魔術(shù)方法)
當(dāng)調(diào)用類中一個(gè)不存在或者沒有權(quán)限訪問的方法的時(shí)候尺碰,就會(huì)自動(dòng)調(diào)用__call()方法。和__call對(duì)應(yīng)靜態(tài)方法的調(diào)用是__callStatic译隘, 配合PHP反射亲桥,對(duì)代碼進(jìn)行優(yōu)化,可對(duì)一些特殊的基礎(chǔ)業(yè)務(wù)功能做到固耘,
如工單, trinity 內(nèi)部都是用了類似方法题篷。
9. move_uploaded_file
該函數(shù)是前端文件上傳文件到后臺(tái)后可能用到的函數(shù),上傳后厅目,我們會(huì)通過$_FILES['file']'tmp_name'番枚, 使用
move_uploaded_file($tmp_name, $savePath);
會(huì)把臨時(shí)存到數(shù)據(jù)庫的 如: /tmp/phpwTJzUw 文件給移動(dòng)走,導(dǎo)致如果后面的代碼還要用到$_FILES全局變量的時(shí)候损敷,會(huì)出現(xiàn)找不到文件的問題葫笼。
10.引用傳遞
在使用array_pop等函數(shù)時(shí), array_pop的參數(shù) 是引用傳遞拗馒,在編碼過程中有時(shí)候會(huì)把 參數(shù)直接寫成函數(shù)返回值渔欢,這樣在 5.3以后是不允許的, 會(huì)報(bào)出致命錯(cuò)誤(嚴(yán)格模式下)瘟忱。
You will see:
PHP Strict Standards: Only variables should be passed by reference in - on line 3
Strict Standards: Only variables should be passed by reference in - on line 3
d
以上來自于: https://www.php.net/manual/zh/function.array-pop.php
按引用傳遞參數(shù)的函數(shù)在被按值傳遞調(diào)用時(shí)行為發(fā)生改變. 此前函數(shù)將接受按值傳遞的參數(shù), 現(xiàn)在將拋出致命錯(cuò)誤. 之前任何期待傳遞引用但是在調(diào)用時(shí)傳遞了常量或者字面值 的函數(shù), 需要在調(diào)用前改為將該值賦給一個(gè)變量奥额。
以上來自于:PHP手冊附錄從PHP 5.2.x 移植到 PHP 5.3.x 部分
https://www.php.net/manual/zh/migration53.incompatible.php
而實(shí)際上看起來沒有錯(cuò), 只需要把那個(gè)函數(shù)返回值賦值給一個(gè)變量访诱,再把變量當(dāng)做參數(shù)傳入就可以了垫挨。
如,在代碼中經(jīng)常會(huì)寫到:
error_reporting(E_STRICT);
$testArr = ['a','b','c','c','d'];
$popValue = array_pop(array_unique($testArr));
// 以上代碼會(huì)報(bào)錯(cuò)触菜,必須使用
$testArr = ['a','b','c','c','d'];
$testArr = array_unique($testArr)
$popValue = array_pop($testArr);