2020年P(guān)HP面試題整理(附帶答案)
1.請問一下你使用過swoole嗎,使用過,怎么設(shè)置心跳?
$this->serv->set(['heartbeat_check_interval' => 5,'heartbeat_idle_time' => 10]);//上面的設(shè)置就是每5秒偵測一次心跳,一個TCP連接如果在10秒內(nèi)未向服務(wù)器端發(fā)送數(shù)據(jù),將會被切斷。
2.如果一個訪問量達(dá)到100萬,選擇緩存,你會選擇redis還memchache?
我會選擇memchache,因為它只有一種類型,key-value,而redis的類型比memchache多,導(dǎo)致它的并發(fā)沒有memchache好。
3.psr2和psr4的區(qū)別?
意思:psr指的是php standards recommendatiion,意思PHP標(biāo)準(zhǔn)建議。psr2:編碼風(fēng)格向?qū)?/p>use?FooClass;use?BarClass?as?Bar;use?OtherVendor\OtherPackage\BazClass;//?...?additional?PHP?code?...
psr4:自動加載。
psr4:#完整的類名為\a\b\c\Log#命名空間前綴前綴為:a\b#前綴對應(yīng)的基礎(chǔ)目錄為:./vendor#文件實際目錄為:./vendor/c/Log.php#注:即把去掉最前面的命名空間分隔符后的a\b\c\Log中的命名空間前綴替換成基礎(chǔ)目錄,然后把命名空間分隔符替換成目錄分隔符,并把文件名補上后綴 .php 。4.mb_strlen和str_len的區(qū)別?
$a = '中國';echo strlen($a)."\n";//6echo mb_strlen($a);//
5.下面會輸出什么?
$str = 'abc';$res = strpos($str,'a');if ($res){echo '找到了';}else {echo '未找到';}//答案是:未找到未找到,因為strpos是查找首字母出現(xiàn)的位置,并且索引是從0開始的,并且PHPs是弱類型的,所以會輸出:未找到
6.使用二分法查找50出現(xiàn)的位置?
//第一種方法$arr = [1,3,5,12,34,45,50];function binary(array &$arr,int $low,int $top,int $target){while($low<=$top){$mid = floor(($low+$top)/2);if($arr[$mid] === $target){return $mid;} elseif($arr[$mid]>$target){$top= $mid-1;} else if($arr[$mid]<$target){$low= $mid+1;}}return -1;}$arr = [1,3,5,12,34,45,50];echo binary($arr,0,count($arr),50);//6//第二種方法function binaryRecursive(array &$arr,int $low,int $top,int $target){$mid = floor(($low+$top)/2);if ($arr[$mid]>$target){return binaryRecursive($arr,$low,$mid-1,$target);} elseif ($arr[$mid]<$target){return binaryRecursive($arr,$mid+1,$top,$target);} else if ($arr[$mid]===$target){return $mid;} else {return -1;}}$arr = [1,3,5,12,34,45,50];echo??binaryRecursive($arr,0,count($arr),50);//6
7.將上面的數(shù)組進(jìn)行翻轉(zhuǎn),不使用內(nèi)置函數(shù)?
$arr = [1,3,5,12,34,45,50];function overturn(array &$arr){$temp = [];for ($i = count($arr)-1;$i>=0;$i--){$temp[] = $arr[$i];}// print_r($temp);return $temp;}$arr = [1,3,5,12,34,45,50];//Array([0] => 50[1] => 45[2] => 34[3] => 12[4] => 5[5] => 3[6] => 1)
8.請寫出nginx負(fù)載均衡的算法?怎么檢查配置用沒有問題,如果有問題,怎么查看出現(xiàn)是問題,修改了配置文件,怎么生效?
1.round robin(默認(rèn))
解釋:輪詢方式,依次將請求分配到各個后臺服務(wù)器中,默認(rèn)的負(fù)載均衡方式,是否機器性能一致的情況下。
2.weight(權(quán)重)`
upstream bakend {server 192.168.0.14 weight=10;server 192.168.0.15 weight=10;}??
解釋:根據(jù)權(quán)重來分發(fā)請求到不同的機器中,指定輪詢幾率,weight和訪問比率成正比,用于后端服務(wù)器性能不均的情況。
3.IP_hash
解釋:根據(jù)請求者ip的hash值將請求發(fā)送到后臺服務(wù)器中,可以保證來自同一ip的請求被打到固定的機器上,可以解決session問題。
upstream bakend {ip_hash;server 192.168.0.14:88;server 192.168.0.15:80;}???
4.url_hash
解釋:根據(jù)請求的url的hash值將請求分到不同的機器中,當(dāng)后臺服務(wù)器為緩存的時候效率高。
upstream backend {server squid1:3128;server squid2:3128;hash $request_uri;hash_method crc32;}
5.fair(第三方)
解釋:根據(jù)后臺響應(yīng)時間來分發(fā)請求,響應(yīng)時間短的分發(fā)的請求多。
upstream backend {server server1;server server2;fair;}??
upstream bakend{#定義負(fù)載均衡設(shè)備的Ip及設(shè)備狀態(tài)ip_hash;server 127.0.0.1:9090 down;server 127.0.0.1:8080 weight=2;server 127.0.0.1:6060;server 127.0.0.1:7070 backup;}//每個設(shè)備的狀態(tài)設(shè)置為:1.down 表示單前的server暫時不參與負(fù)載2.weight 默認(rèn)為1.weight越大,負(fù)載的權(quán)重就越大。3.max_fails :允許請求失敗的次數(shù)默認(rèn)為1.當(dāng)超過最大次數(shù)時,返回proxy_next_upstream 模塊定義的錯誤4.fail_timeout:max_fails次失敗后,暫停的時間。5.backup: 其它所有的非backup機器down或者忙的時候,請求backup機器。所以這臺機器壓力會最輕。nginx支持同時設(shè)置多組的負(fù)載均衡,用來給不用的server來使用。client_body_in_file_only 設(shè)置為On 可以講client post過來的數(shù)據(jù)記錄到文件中用來做debugclient_body_temp_path 設(shè)置記錄文件的目錄 可以設(shè)置最多3層目錄location?對URL進(jìn)行匹配.可以進(jìn)行重定向或者進(jìn)行新的代理?負(fù)載均衡
9.優(yōu)化下面的代碼?
$arr = [1,2,3,...n+1];$userName = [];foreach ($arr as $v){$userName = $this->getUserNameFromyDb($v);}//優(yōu)化代碼如下:$arr = [1,2,3,...n+1];$userName = [];$userName?=?this->getUserNameFromyDb(implode(',',$arr))
10.請實現(xiàn)一個單列模式。
class Singleton{//1.創(chuàng)建私有變量保存該對象private static $interface;//2.禁止使用newpublic function __construct(){}//3.禁止克隆public function __clone(){// TODO: Implement __clone() method.}//4.判斷對象是否存在public static function getInstance(){if (!self::$interface instanceof self) {self::$interface = new self();}return self::$interface;}public function test(){echo '測試單列模式';}}$singleton = Singleton::getInstance();$singleton->test();//實現(xiàn)單列模式的意義,減少資源的占用
11.請簡述一下觀察者模式?
簡單的一句話就是,多個不同類去執(zhí)行方法名相同的代碼。
實現(xiàn):1.定義一個觀察接口,第二實現(xiàn)該接口里的方法。
生活中的例子:
小明觀察者),狗(被觀察者),貓(被觀察者),牛(被觀察者)
當(dāng)小明看見狗,就知道它喜歡吃骨頭。
當(dāng)小明看見貓,就知道它喜歡吃魚。
當(dāng)小明看見牛,就知道它喜歡吃青草。
代碼如下:
?php//觀察者接口interface ObjectTest {public function register(ObServerTest $obServerTest);//注冊觀察者對象public function detach(ObServerTest $obServerTest);//刪除觀察者對象public function notify();//通知所有的被觀察者}//被觀察者接口interface ObServerTest{public function eat();}class Action implements ObjectTest{private $_obServersTest = [];public function register(ObServerTest $obServerTest)//注冊對象{$this->_obServersTest[] = $obServerTest;}public function detach(ObServerTest $obServerTest){$index = array_search($obServerTest,$this->_obServersTest);if(false === $index || !array_key_exists($index,$this->_obServersTest)){throw new \Exception('該對象不存在');}unset($this->_obServersTest[$index]);}public function notify()//通知所有的對象{foreach ($this->_obServersTest as $k=>$v){$v->eat();}}}class Dog implements ObServerTest{public function eat(){echo '狗吃骨頭'."\n";}}class Cat implements ObServerTest{public function eat(){echo '貓吃魚'."\n";}}class Pink implements ObServerTest{public function eat(){echo '豬吃了睡,睡了吃'."\n";}}$action = new Action();$action->register(new Dog());$action->register(new Cat());$action->register(new Pink());$action->notify();//結(jié)果:狗吃骨頭貓吃魚豬吃了睡,睡了吃
12.請寫出怎么獲取請求頭的信息?
Apache:getallheaders();nginx:function nginxGetAllHeaders(){//獲取請求頭$headers = [];foreach ($_SERVER as $name => $value){if (substr($name, 0, 5) == 'HTTP_'){$headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value;}}return $headers;????}
14.高訪問量的網(wǎng)站怎么優(yōu)化?
軟件
將不經(jīng)常變化的數(shù)據(jù),直接靜態(tài)化。
使用redis和memcha,減少數(shù)據(jù)庫的訪問。
控制大文件的下載。
圖片、視頻服務(wù)器分離。
禁止外部的盜鏈。(可以通過refer去實現(xiàn))
統(tǒng)計流量的使用情況。
硬件
不考慮成本,服務(wù)器可以考慮負(fù)載均衡,mysql主從復(fù)制、讀寫分離。
15.請說一下websoket原理?
https://link.zhihu.com/?target=https%3A//www.cnblogs.com/nnngu/p/9347635.html
16.redis默認(rèn)有多少個庫?
16個庫
17.linux進(jìn)程之間怎么通信?
1.管道
ls -al /etc |less2.信號量(沒有使用過)
3.消息隊列(沒有使用過)
4.信號(沒有使用過)
5.共享內(nèi)容(沒有使用過)
6.套接字(unix socket)
18.如果用戶git,請問一下git怎么合并分支?
git checkout master
git merche 分支名
19.laravel外面引入路由.
1.在route文件夾中添php文件,并且設(shè)置路由。
2.在app/Providers/RouteServiceProvider中對應(yīng)的文件路徑。
3.然后laravel啟動就會加載該文件。
20.請求用沒有使用過隊列?
#redis的隊列//server.php$redis = new Redis();$redis->connect('127.0.0.1',6379);$password = '123456';$redis->auth($password);$arr = array('list1','list2');foreach($arr as $k=>$v){$redis->rpush("mylist",$v);}//client.php$redis = new Redis();$redis->connect('127.0.0.1',6379);$password = '123456';$redis->auth($password);//list類型出隊操作$value = $redis->lpop('mylist');if($value){if($value === 'list1'){echo '執(zhí)行l(wèi)ist1的代碼';}if($value === 'list2'){echo '執(zhí)行l(wèi)ist2的代碼';}}else{echo "出隊完成";}//執(zhí)行兩次#第一次執(zhí)行l(wèi)ist1的代碼#第二次執(zhí)行l(wèi)ist2的代碼//rabbitmq?#等不忙的時候再寫??
21.怎么防止商品不會超賣?
采用redis的隊列,去實現(xiàn)。
22.單引號和雙引號的區(qū)別?
1.單引號比雙引號執(zhí)行速度快。
2.雙引號會解析變量、換行,而單引號不會。
23.微信支付、支付寶回調(diào),如果在回調(diào)區(qū)間服務(wù)器崩潰了,有沒有解決辦法?
1.確定那些單是沒有收到回調(diào)。
2.通過訂單號,去查詢支付寶和微信的訂單狀態(tài),確定是否支付成功。
24.在瀏覽器輸入網(wǎng)址,點回車,經(jīng)歷了什么,才能將數(shù)據(jù)顯示在瀏覽器上?

25.請說一下php常見的字符串處理函數(shù)和數(shù)組?
字符串函數(shù)mb_substr()//截取字符串(中文的)substr()//·········(英文)ucfirst()//將字符串首字母變?yōu)榇髮?/span>str_replace()//替換字符串#這里參數(shù)就不做詳細(xì)的說明(自行去百度哈)復(fù)制代碼數(shù)組:array_chunk(array $array , int $size [, bool $preserve_keys = false ])//將一個數(shù)組分割成多個/*array操作的數(shù)組size每個數(shù)組的單元數(shù)目preserve_keys設(shè)為 TRUE,可以使 PHP 保留輸入數(shù)組中原來的鍵名。如果你指定了 FALSE,那每個結(jié)果數(shù)組將用從零開始的新數(shù)字索引。默認(rèn)值是 FALSE*///代碼如下$arr = [1,3,45,50];print_r(array_chunk($arr,1));/**Array([0] => Array([0] => 1)[1] => Array([0] => 3)[2] => Array([0] => 45)[3] => Array([0] => 50))*/array_diff_key ( array $array1 , array $array2 [, array $... ] ) : array#使用鍵名比較計算數(shù)組的差集/**array1從這個數(shù)組進(jìn)行比較array2針對此數(shù)組進(jìn)行比較...更多比較數(shù)組*///代碼如下:$array1 = ['blue' => 1, 'red' => 2, 'green' => 3, 'purple' => 4];$array2 = ['green' => 5, 'blue' => 6, 'yellow' => 7, 'cyan' => 8];print_r(array_diff_key($array1, $array2));/**Array([red] => 2[purple] => 4)*/array_diff ( array $array1 , array $array2 [, array $... ] ) : array# 計算數(shù)組的差集/**rray1要被對比的數(shù)組array2和這個數(shù)組進(jìn)行比較...更多相比較的數(shù)組*/$array1 = array("a" => "green", "red", "blue", "red");$array2 = array("b" => "green", "yellow", "red");$result = array_diff($array1, $array2);print_r($result);/**Array([1] => blue)*/array_walk ( array &$array , callable $callback [, mixed $userdata = NULL ] ) : bool#使用用戶自定義函數(shù)對數(shù)組中的每個元素做回調(diào)處理/**array輸入的數(shù)組。callback典型情況下 callback 接受兩個參數(shù)。array 參數(shù)的值作為第一個,鍵名作為第二個。userdata如果提供了可選參數(shù) userdata,將被作為第三個參數(shù)傳遞給 callback funcname。*///代碼如下:$fruits = array('a' => 'lemon', 'b' => 'orange');function testPrint(string $k,string $v){echo $k.$v."\n";}print_r(array_walk($fruits,'testPrint'));/**lemonaorangeb1*///1是返回值哦compact ( mixed $varname1 [, mixed $... ] ) : array# 建立一個數(shù)組,包括變量名和它們的值/*對每個參數(shù),compact() 在當(dāng)前的符號表中查找該變量名并將它添加到輸出的數(shù)組中,變量名成為鍵名而變量的內(nèi)容成為該鍵的值**///代碼如下:$city = "San Francisco";$state = "CA";$event = "SIGGRAPH";$location_vars = array("city", "state");$res = compact('event','xxx',$location_vars);print_r($res);/**Array([event] => SIGGRAPH[city] => San Francisco[state] => CA)*/array_key_exists ( mixed $key , array $array ) : bool#檢查數(shù)組里是否有指定的鍵名或索引//代碼如下$searchArray = array('TEST1' => 1);var_dump(array_key_exists('test1', $searchArray));/**bool(false)*///區(qū)分大小寫//更多數(shù)組函數(shù):https://www.php.net/manual/zh/function.array-change-key-case.php
26.為什么要減少數(shù)據(jù)庫的訪問次數(shù)?
因為方法數(shù)據(jù)庫,會有大量io、事務(wù)、網(wǎng)絡(luò)傳輸操作,所有要減少數(shù)據(jù)庫的訪問次數(shù)。
27.require和include的區(qū)別?
include在引入不存文件時產(chǎn)生一個警告且腳本還會繼續(xù)執(zhí)行,
require則會導(dǎo)致一個致命性錯誤且腳本停止執(zhí)行。
28.php7和php5的區(qū)別?
php7新特性:
1.支持標(biāo)量和返回類型。
class Test{private $age;/*** @return mixed*/public function getAge(){return $this->age;}/*** @param mixed $age*/public function setAge(int $age): void{$this->age = $age;}}$test = new Test();$test->setAge('1233ddsaf');echo $test->getAge();//1233,內(nèi)部進(jìn)行了轉(zhuǎn)換
3.太空船運算符號。
$var = $i??1;//判斷變量是否存在,存在將該值給$var,不存在,將1給$varecho $var;//1
4.可以使用一個 use 從同一個 namespace 中導(dǎo)入類、函數(shù)和常量.
5.可以通過 define() 來定義數(shù)組。
define('test',['12',23]);echo test[1];//23
6.可用使用new class來實現(xiàn)一個匿名類。
interface Logger{public function log(string $log);}class App {private $logger;/*** @return mixed*/public function getLogger(){return $this->logger;}/*** @param mixed $logger*/public function setLogger($logger): void{$this->logger = $logger;}}$app = new App();$app->setLogger(new class implements Logger{public function log(string $log){echo $log;}});$app->getLogger()->log('這是一條日志');//這是一條日志
29.數(shù)據(jù)庫優(yōu)化策略?
1.合理的表設(shè)計。
1).依據(jù)三范式,設(shè)計表.
三范式:1.原子性,每個字段都是不可在分的。
2.在1方式的基礎(chǔ)上,表中每一列必須有唯一性,其他字段依賴主鍵。
3.在2方式的基礎(chǔ)上,表中的每一列只與主鍵直接相關(guān),而不是間接相關(guān)。
2).選擇合適的字段。
I.盡量使用TYPEINT、SMALLINT、MEDIUM_INT代替INT的使用,一般索引,并且是字段遞增,可以考慮設(shè)置為UNSIGNED.
II.使用枚舉代替字符串類型。
III.將少null的使用,null很難優(yōu)化,并且還占用額外的空間。
iv.varchar長度分配給真正需要的空間。
v.建立合適的索引。
3)選擇合適的引擎。
2.sql優(yōu)化
1).減少*的使用,只查詢需要的字段。
2).使用關(guān)聯(lián)查詢,代替子查詢。
3).like使用后匹配。
4).合理使用索引。
5)減少對null字段的判斷、否則引擎放棄索引,對全表進(jìn)行掃描。
6)減少!=,<>的使用。
7)減少where 條件中使用or來連接條件
select id from t where num=10 or Name = ‘a(chǎn)dmin’#可以這樣查詢:select id from t where num = 10unionselect?id?from?t?where?Name?=?‘a(chǎn)dmin’
3.減少數(shù)據(jù)庫訪問的次數(shù)。
1).將不經(jīng)常變化的數(shù)據(jù),進(jìn)行緩存(分類、權(quán)限等),可以使用redis和mememcha,我個人建議,不要使用文件緩存,它也是對iO進(jìn)行操作。
4.硬件方面。
1).可以考慮分庫、分表。
2)可以采用主從復(fù)制,讀寫分離.(mysql服務(wù)器根據(jù)sql,去判斷是讀還是寫)。
30.laravel保存session。
$request->session()->put('admin',$res);$request->session()->save();//要加這一句,如果不加,不會保存session//如果要保存session,都要調(diào)用save方法
轉(zhuǎn)載請注明來源https://juejin.cn/post/6844904186350583821
