PHP
標(biāo)簽(空格分隔): 面試
PHP的引用變量的概念及定義
延伸: PHP引用變量的原理
概念:
在 PHP 中 引用意味著用不同的名字訪問(wèn)同一個(gè)變量的內(nèi)容
定義方式:
使用&符號(hào)
PHP引用變量的工作原理
$a=range(0,1000);
//定義變量b,將a變量的值賦值給b
//COW機(jī)制 (Copy On Write)
$b=$a;
//對(duì)a進(jìn)行修改才會(huì)copy
$a=range(0,1000);
//驗(yàn)證COW機(jī)制可以使用函數(shù)memory_get_usage()
//在每個(gè)表達(dá)式后面讀取內(nèi)存量
//而引用賦值不遵從COW機(jī)制,永遠(yuǎn)指向一個(gè)內(nèi)存空間
zval結(jié)構(gòu)體
//zval變量容器
$a=range(0,3);
xdebug_debug_zval('a');
//定義變量b,把a(bǔ)的值賦值給b
$b= $a;
xdebug_debug_zval('a');
//修改a
$a=range(0,3);
xdebug_debug_zval('a');
unset 對(duì)引用變量的影響
unset只會(huì)取消引用,不會(huì)銷毀空間
$a=1;
$b=&$a;
unset($b);
echo $a."\n"; //此時(shí)$a還存在值,證明只是取消$b的引用
對(duì)象不會(huì)復(fù)制空間,不遵守COW
對(duì)象本身就是引用傳遞
class Person{
public $name='zhangsan';
}
$p1=new Person;
xdebug_debug_zval('p1');
$p2=$p1;
xdebug_debug_zval('p1');
$p2->name='lisi';
xdebug_debug_zval('p1'); //此時(shí)并沒(méi)有開(kāi)辟出一個(gè)新空間,clone對(duì)象才可以
真題
//真題
/**
* TODO 寫出如下程序的輸出結(jié)果
*
*/
$data=['a','b','c'];
foreach($data as $key => $val){
$val=&$data[$key];
var_dump($data);
}
var_dump($data);
/**
* TODO 程序運(yùn)行時(shí),每一次循環(huán)結(jié)束后變量$data的值是什么?請(qǐng)解釋
* TODO 程序執(zhí)行完成后,變量$data的值是什么?請(qǐng)解釋
*/
常量及數(shù)據(jù)類型考點(diǎn)
PHP中字符串可以使用哪三種定義方法以及各自的區(qū)別是什么?
- 定義方式: 單引號(hào),雙引號(hào),heredoc和nowdoc
heredoc 和 nowdoc (看看)
$a='sdsd';
$str="abcdsd '{$a}'"; //會(huì)被解析變量,并且單引號(hào)會(huì)原樣輸出
echo $str;
單引號(hào)比雙引號(hào)更快,建議寫單引號(hào)
- heredoc類似雙引號(hào)
- nowdoc類似雙引號(hào)
- 兩者都是用來(lái)處理大文本
知識(shí)點(diǎn)延伸
- 數(shù)據(jù)類型考點(diǎn)
- 8 大 3 類
- 標(biāo)量,復(fù)合,特殊
- 浮點(diǎn)類型
-
浮點(diǎn)類型不能運(yùn)用到比較運(yùn)算中[???],感覺(jué)是比較運(yùn)算當(dāng)做判斷條件
$a=0.1;
-
$b=0.5;
echo $a+$b.PHP_EOL;
$c=$a+$b == 0.6 ? true:false;
var_dump($c); //為true,不知道為什么
```
```php
$a=0.1;
$b=0.7;
if($a+$b == 0.8) { //用于條件判斷時(shí)出錯(cuò)
echo 'haha';
}else{
echo '5555';
}
```
比較浮點(diǎn)類型可以用php內(nèi)置函數(shù) bccomp()
-
布爾值
- false: 0,0.0,'','0',false,array(),null
-
數(shù)組類型:
- 超全局?jǐn)?shù)組:
$GLOBALS,$_GET, $_POST,$_REQUEST,$_SESSION,$_COOKIE,$_SERVER,$_FILES,$_ENV
- 超全局?jǐn)?shù)組:
-
NULL
- 三種情況: 直接賦值為null,未定義的變量,unset銷毀的變量
常量
-
預(yù)定義常量
- _FILE,_LINE,_DIR,_FUNCTION,_CLASS,_TRAIT,_METHOD,_NAMESPACE
定義方式
const,define
const更快,是語(yǔ)言結(jié)構(gòu)
define是函數(shù)
define不能用于類常量的定義,const可以
常量一經(jīng)定義,不能被修改,不能被刪除
真題
用PHP寫出顯示客戶端IP與服務(wù)器IP的代碼
FILE表示什么意思?
運(yùn)算符
foo()和@foo()之間區(qū)別
- 考點(diǎn):PHP的運(yùn)算符的錯(cuò)誤控制符@
- 延伸:
- PHP所有運(yùn)算符考點(diǎn)
- 運(yùn)算符的優(yōu)先級(jí)
- 比較運(yùn)算符
- 遞增遞減運(yùn)算符
- 邏輯運(yùn)算符
PHP的錯(cuò)誤運(yùn)算符
PHP 支持一個(gè)錯(cuò)誤運(yùn)算符: @.
當(dāng)將其放置在一個(gè)PHP表達(dá)式之前,該表達(dá)式可能產(chǎn)生的任何錯(cuò)誤信息都被忽略掉
延伸考點(diǎn): PHP運(yùn)算符優(yōu)先級(jí)
遞增/遞減 > ! > 算數(shù)運(yùn)算符 > 大小比較 > (不)相等比較 > 引用 > 位運(yùn)算符(^) > 位運(yùn)算符(|) > 邏輯與 > 邏輯或 > 三目 > 賦值 > and > xor > or
- 括號(hào)的使用可以增加代碼可讀性
延伸考點(diǎn): 比較運(yùn)算符
- == 和 === 的區(qū)別
- 等值判斷(FALSE的七種情況) ==> 前面說(shuō)過(guò)布爾值那里
延伸考點(diǎn): 遞增/遞減運(yùn)算符
- 遞增/遞減運(yùn)算符不影響布爾值 ==> ++/-- 不改變布爾值
- 遞減NULL值沒(méi)有效果
- 遞增NULL值為1
- 遞增和遞減在前就先運(yùn)算符后返回,反之就先返回,后運(yùn)算
延伸考點(diǎn): 邏輯運(yùn)算符
- 短路作用
- || 和 && 與 or和and 的優(yōu)先級(jí)不同
$a=true || $b === 3; //短路作用
$b=false && $a===1;
//比較運(yùn)算符 優(yōu)先級(jí)問(wèn)題
$a = false || true; //返回true
$b = false or true; //返回false
流程控制考點(diǎn)
真題: 請(qǐng)列出三種PHP數(shù)組循環(huán)操作的語(yǔ)法竿滨,并注明各個(gè)循環(huán)的區(qū)別
- for
- foreach
- while,list(),each()組合循環(huán)
for循環(huán)只能遍歷索引數(shù)組,foreach可以遍歷索引和關(guān)聯(lián)數(shù)組.
聯(lián)合使用list(),each()和while循環(huán)同樣可以遍歷索引和關(guān)聯(lián)數(shù)組
while,list(),each()組合不會(huì)reset(),即指針不會(huì)重置
foreach遍歷會(huì)對(duì)數(shù)組進(jìn)行reset()操作
延伸考點(diǎn): PHP分支結(jié)構(gòu)
- if ... else if
- 在elseif語(yǔ)句中只能有一個(gè)表達(dá)式為true,即在elseif語(yǔ)句中只能有一個(gè)語(yǔ)句塊被執(zhí)行,多個(gè)elseif從句是排斥關(guān)系
- 使用elseif 語(yǔ)句有一個(gè)基本原則,總把優(yōu)先范圍小的條件放在前面處理
- switch...case...
- 和if不同的是,switch后面的控制表達(dá)式的數(shù)據(jù)類型只能是整型,浮點(diǎn)類型或者字符串
- continue語(yǔ)句作用到switch的作用類似于break跳出switch外的循環(huán),可以使用continue 2
- switch ... case 會(huì)生成跳轉(zhuǎn)表,直接跳轉(zhuǎn)到對(duì)應(yīng)case
- 效率: 如果條件比一個(gè)簡(jiǎn)單的比較要復(fù)雜的多或者在一個(gè)很多次的循環(huán)中,那么用switch語(yǔ)句可能快一點(diǎn)
真題: PHP中如何優(yōu)化多個(gè)if...elseif語(yǔ)句的情況?
自定義函數(shù)及內(nèi)部函數(shù)
考點(diǎn):
- 變量的作用于和靜態(tài)變量
延伸: 函數(shù)的參數(shù)及參數(shù)的引用傳遞
: 函數(shù)的返回值及引用返回
: 外部文件的導(dǎo)入
變量的作用域
- 變量的作用域也稱變量的范圍,變量的范圍即它定義的上下文背景(也是它的生效范圍).
- 大部分的PHP變量只有一個(gè)單獨(dú)的范圍.
- 這個(gè)單獨(dú)的范圍跨度同樣包含了include和require引入的文件
//寫出如下程序的輸出結(jié)果
$count=5;
function get_count(){
static $count; //靜態(tài)變量 此時(shí)無(wú)賦值,則為null
return $count++; //null++ ==> 1
}
echo $count;
++$count;
echo get_count();
echo get_count();
考點(diǎn):
變量的作用域和靜態(tài)變量
- 延伸: 函數(shù)的參數(shù)及參數(shù)的引用傳遞
- 延伸: 函數(shù)的返回值及引用返回
- 延伸: 外部文件的導(dǎo)入
- 延伸: 系統(tǒng)內(nèi)置函數(shù)
$outer='str';
function mgfunc()
{
//全局變量引入到函數(shù)體內(nèi)部使用,用關(guān)鍵字global
global $outer;
//或者
$GLOBALS['outer'] //也可以
echo $outer;
}
靜態(tài)變量
靜態(tài)變量?jī)H在局部函數(shù)中存在,但當(dāng)程序執(zhí)行離開(kāi)此作用域時(shí),其值并不會(huì)消失
static關(guān)鍵字
- 僅初始化一次
- 初始化時(shí)需要賦值
- 每執(zhí)行函數(shù)該值會(huì)保留
- static修飾的變量是局部的,僅在函數(shù)內(nèi)部有效
- 可以記錄函數(shù)的調(diào)用次數(shù),從而可以在某些條件下終止遞歸
function get_count()
{
static $count; //只初始化一次
return $count++;
}
echo get_count(); //null
echo get_count(); //1
echo get_count(); //2
延伸考點(diǎn): 函數(shù)的返回值
- 值通過(guò)使用可選的返回語(yǔ)句(return)返回可以返回包括數(shù)組和對(duì)象的任意類型
- 返回語(yǔ)句會(huì)終止函數(shù)執(zhí)行,將控制權(quán)交回函數(shù)調(diào)用處
- 省略return,返回值為null,不可有多個(gè)返回值
延伸考點(diǎn): 函數(shù)的引用返回
從函數(shù)返回一個(gè)引用,必須在函數(shù)聲明和指派返回值給一個(gè)變量時(shí)都使用引用運(yùn)算符 &
function &myFunc()
{
static $b=10;
return $b;
}
$a=myFunc();
$a=&myFunc();
$a=100;
echo myFunc(); //100
延伸考點(diǎn): 外部文件的導(dǎo)入
- include/require 語(yǔ)句包含并運(yùn)行制定文件
- 如果給出路徑名按照路徑來(lái)找,否則從include_path中查找
- 如果include_path中也沒(méi)有,則從調(diào)用腳本文件所在目錄和當(dāng)前工作目錄下尋找
- 當(dāng)一個(gè)文件被包含時(shí),其中所包含的代碼繼承了include所在行的變量范圍
- 加載過(guò)程中未找到文件則include結(jié)構(gòu)會(huì)發(fā)出一個(gè)警告;這一點(diǎn)和require不同,后者會(huì)發(fā)出一個(gè)致命錯(cuò)誤
require在出錯(cuò)時(shí)會(huì)產(chǎn)生E_COMPILE_ERROR 級(jí)別錯(cuò)誤.
換句話講將導(dǎo)致腳本終止而include只會(huì)產(chǎn)生警告(E_WARNING),腳本會(huì)繼續(xù)運(yùn)行
require(include)/require_once(include_once)唯一區(qū)別是PHP會(huì)檢查該文件是否已經(jīng)被包含過(guò),如果是則不會(huì)再次包含
延伸考點(diǎn): 系統(tǒng)內(nèi)置函數(shù)
-
時(shí)間日期函數(shù):
date(),strtotime(),mktime(),time(),microtime(),date_default_timezone_set()
-
IP處理函數(shù):
ip2long(),long2ip()
-
打印處理:
print(),printf(),print_r(),echo,sprintf(),var_dump(),var_export()
-
序列化及反序列化函數(shù):
serialize(),unserialize()
-
字符串處理函數(shù):
implode(),explode(),join(),strrev(),trim(),ltrim(),rtrim(),strstr(),number_format()...
-
數(shù)組處理函數(shù):
array_keys(),array_values(),array_diff(),array_intersect(),array_merge(),array_shif(),
array_unshift(),array_pop(),array_push(),sort()...
解題方法:
著重記憶PHP函數(shù)的定義相關(guān)內(nèi)容,理解變量作用域,靜態(tài)變量,函數(shù)的參數(shù)和返回值的相關(guān)內(nèi)容,重點(diǎn)記憶我們總結(jié)的內(nèi)置函數(shù)
//真題
$var1=5;
$var2=10;
function foo(&$my_var)
{
global $var1;
$var1 +=2;
$var2 =4;
$my_var+=3;
return $var2;
}
$my_var=5;
echo foo($my_var)."\n";
echo $my_var."\n";
echo $var1;
echo $var2;
$bar='foo';
$my_var=10;
echo $bar($my_var)."\n";