2020年PHP面试题整理(附带答案)
1.请问一下你使用过swoole吗,使用过,怎么设置心跳?
$this->serv->set([
'heartbeat_check_interval' => 5,
'heartbeat_idle_time' => 10
]);
//上面的设置就是每5秒侦测一次心跳,一个TCP连接如果在10秒内未向服务器端发送数据,将会被切断。
2.如果一个访问量达到100万,选择缓存,你会选择redis还memchache?
我会选择memchache,因为它只有一种类型,key-value,而redis的类型比memchache多,导致它的并发没有memchache好。
3.psr2和psr4的区别?
意思:psr指的是php standards recommendatiion,意思PHP标准建议。psr2:编码风格向导
use FooClass;use BarClass as Bar;use OtherVendor\OtherPackage\BazClass;// ... additional PHP code ...
psr4:自动加载。
psr4:#完整的类名为\a\b\c\Log#命名空间前缀前缀为:a\b#前缀对应的基础目录为:./vendor#文件实际目录为:./vendor/c/Log.php#注:即把去掉最前面的命名空间分隔符后的a\b\c\Log中的命名空间前缀替换成基础目录,然后把命名空间分隔符替换成目录分隔符,并把文件名补上后缀 .php 。
4.mb_strlen和str_len的区别?
$a = '中国';
echo strlen($a)."\n";//6
echo mb_strlen($a);//
5.下面会输出什么?
$str = 'abc';
$res = strpos($str,'a');
if ($res){
echo '找到了';
}
else {
echo '未找到';
}
//答案是:未找到未找到,因为strpos是查找首字母出现的位置,并且索引是从0开始的,并且PHPs是弱类型的,所以会输出:未找到
6.使用二分法查找50出现的位置?
//第一种方法
$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.将上面的数组进行翻转,不使用内置函数?
$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负载均衡的算法?怎么检查配置用没有问题,如果有问题,怎么查看出现是问题,修改了配置文件,怎么生效?
1.round robin(默认)
解释:轮询方式,依次将请求分配到各个后台服务器中,默认的负载均衡方式,是否机器性能一致的情况下。
2.weight(权重)`
upstream bakend {
server 192.168.0.14 weight=10;
server 192.168.0.15 weight=10;
}
解释:根据权重来分发请求到不同的机器中,指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。
3.IP_hash
解释:根据请求者ip的hash值将请求发送到后台服务器中,可以保证来自同一ip的请求被打到固定的机器上,可以解决session问题。
upstream bakend {
ip_hash;
server 192.168.0.14:88;
server 192.168.0.15:80;
}
4.url_hash
解释:根据请求的url的hash值将请求分到不同的机器中,当后台服务器为缓存的时候效率高。
upstream backend {
server squid1:3128;
server squid2:3128;
hash $request_uri;
hash_method crc32;
}
5.fair(第三方)
解释:根据后台响应时间来分发请求,响应时间短的分发的请求多。
upstream backend {
server server1;
server server2;
fair;
}
upstream bakend{#定义负载均衡设备的Ip及设备状态
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;
}
//每个设备的状态设置为:
1.down 表示单前的server暂时不参与负载
2.weight 默认为1.weight越大,负载的权重就越大。
3.max_fails :允许请求失败的次数默认为1.当超过最大次数时,返回proxy_next_upstream 模块定义的错误
4.fail_timeout:max_fails次失败后,暂停的时间。
5.backup: 其它所有的非backup机器down或者忙的时候,请求backup机器。所以这台机器压力会最轻。
nginx支持同时设置多组的负载均衡,用来给不用的server来使用。
client_body_in_file_only 设置为On 可以讲client post过来的数据记录到文件中用来做debug
client_body_temp_path 设置记录文件的目录 可以设置最多3层目录
location 对URL进行匹配.可以进行重定向或者进行新的代理 负载均衡
9.优化下面的代码?
$arr = [1,2,3,...n+1];
$userName = [];
foreach ($arr as $v){
$userName = $this->getUserNameFromyDb($v);
}
//优化代码如下:
$arr = [1,2,3,...n+1];
$userName = [];
$userName = this->getUserNameFromyDb(implode(',',$arr))
10.请实现一个单列模式。
class Singleton
{
//1.创建私有变量保存该对象
private static $interface;
//2.禁止使用new
public 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();
//实现单列模式的意义,减少资源的占用
11.请简述一下观察者模式?
简单的一句话就是,多个不同类去执行方法名相同的代码。
实现:1.定义一个观察接口,第二实现该接口里的方法。
生活中的例子:
小明观察者),狗(被观察者),猫(被观察者),牛(被观察者)
当小明看见狗,就知道它喜欢吃骨头。
当小明看见猫,就知道它喜欢吃鱼。
当小明看见牛,就知道它喜欢吃青草。
代码如下:
?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();
//结果:
狗吃骨头
猫吃鱼
猪吃了睡,睡了吃
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.高访问量的网站怎么优化?
软件
将不经常变化的数据,直接静态化。
使用redis和memcha,减少数据库的访问。
控制大文件的下载。
图片、视频服务器分离。
禁止外部的盗链。(可以通过refer去实现)
统计流量的使用情况。
硬件
不考虑成本,服务器可以考虑负载均衡,mysql主从复制、读写分离。
15.请说一下websoket原理?
https://link.zhihu.com/?target=https%3A//www.cnblogs.com/nnngu/p/9347635.html
16.redis默认有多少个库?
16个库
17.linux进程之间怎么通信?
1.管道
ls -al /etc |less
2.信号量(没有使用过)
3.消息队列(没有使用过)
4.信号(没有使用过)
5.共享内容(没有使用过)
6.套接字(unix socket)
18.如果用户git,请问一下git怎么合并分支?
git checkout master
git merche 分支名
19.laravel外面引入路由.
1.在route文件夹中添php文件,并且设置路由。
2.在app/Providers/RouteServiceProvider中对应的文件路径。
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 '执行list1的代码';
}
if($value === 'list2'){
echo '执行list2的代码';
}
}else{
echo "出队完成";
}
//执行两次
#第一次
执行list1的代码
#第二次
执行list2的代码
//rabbitmq
#等不忙的时候再写
21.怎么防止商品不会超卖?
采用redis的队列,去实现。
22.单引号和双引号的区别?
1.单引号比双引号执行速度快。
2.双引号会解析变量、换行,而单引号不会。
23.微信支付、支付宝回调,如果在回调区间服务器崩溃了,有没有解决办法?
1.确定那些单是没有收到回调。
2.通过订单号,去查询支付宝和微信的订单状态,确定是否支付成功。
24.在浏览器输入网址,点回车,经历了什么,才能将数据显示在浏览器上?
25.请说一下php常见的字符串处理函数和数组?
字符串函数
mb_substr()//截取字符串(中文的)
substr()//·········(英文)
ucfirst()//将字符串首字母变为大写
str_replace()//替换字符串
#这里参数就不做详细的说明(自行去百度哈)
复制代码数组:array_chunk(array $array , int $size [, bool $preserve_keys = false ])//将一个数组分割成多个
/*
array
操作的数组
size
每个数组的单元数目
preserve_keys
设为 TRUE,可以使 PHP 保留输入数组中原来的键名。如果你指定了 FALSE,那每个结果数组将用从零开始的新数字索引。默认值是 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#使用键名比较计算数组的差集
/**
array1
从这个数组进行比较
array2
针对此数组进行比较
...
更多比较数组
*/
//代码如下:
$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# 计算数组的差集
/**
rray1
要被对比的数组
array2
和这个数组进行比较
...
更多相比较的数组
*/
$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#使用用户自定义函数对数组中的每个元素做回调处理
/**
array
输入的数组。
callback
典型情况下 callback 接受两个参数。array 参数的值作为第一个,键名作为第二个。
userdata
如果提供了可选参数 userdata,将被作为第三个参数传递给 callback funcname。
*/
//代码如下:
$fruits = array('a' => 'lemon', 'b' => 'orange');
function testPrint(string $k,string $v){
echo $k.$v."\n";
}
print_r(array_walk($fruits,'testPrint'));
/**
lemona
orangeb
1
*/
//1是返回值哦
compact ( mixed $varname1 [, mixed $... ] ) : array# 建立一个数组,包括变量名和它们的值
/*
对每个参数,compact() 在当前的符号表中查找该变量名并将它添加到输出的数组中,变量名成为键名而变量的内容成为该键的值
**/
//代码如下:
$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#检查数组里是否有指定的键名或索引
//代码如下
$searchArray = array('TEST1' => 1);
var_dump(array_key_exists('test1', $searchArray));
/**
bool(false)
*/
//区分大小写
//更多数组函数:https://www.php.net/manual/zh/function.array-change-key-case.php
26.为什么要减少数据库的访问次数?
因为方法数据库,会有大量io、事务、网络传输操作,所有要减少数据库的访问次数。
27.require和include的区别?
include在引入不存文件时产生一个警告且脚本还会继续执行,
require则会导致一个致命性错误且脚本停止执行。
28.php7和php5的区别?
php7新特性:
1.支持标量和返回类型。
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,内部进行了转换
3.太空船运算符号。
$var = $i??1;//判断变量是否存在,存在将该值给$var,不存在,将1给$var
echo $var;
//1
4.可以使用一个 use 从同一个 namespace 中导入类、函数和常量.
5.可以通过 define() 来定义数组。
define('test',['12',23]);
echo test[1];
//23
6.可用使用new class来实现一个匿名类。
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.数据库优化策略?
1.合理的表设计。
1).依据三范式,设计表.
三范式:1.原子性,每个字段都是不可在分的。
2.在1方式的基础上,表中每一列必须有唯一性,其他字段依赖主键。
3.在2方式的基础上,表中的每一列只与主键直接相关,而不是间接相关。
2).选择合适的字段。
I.尽量使用TYPEINT、SMALLINT、MEDIUM_INT代替INT的使用,一般索引,并且是字段递增,可以考虑设置为UNSIGNED.
II.使用枚举代替字符串类型。
III.将少null的使用,null很难优化,并且还占用额外的空间。
iv.varchar长度分配给真正需要的空间。
v.建立合适的索引。
3)选择合适的引擎。
2.sql优化
1).减少*的使用,只查询需要的字段。
2).使用关联查询,代替子查询。
3).like使用后匹配。
4).合理使用索引。
5)减少对null字段的判断、否则引擎放弃索引,对全表进行扫描。
6)减少!=,<>的使用。
7)减少where 条件中使用or来连接条件
select id from t where num=10 or Name = ‘admin’
#可以这样查询:
select id from t where num = 10
union
select id from t where Name = ‘admin’
3.减少数据库访问的次数。
1).将不经常变化的数据,进行缓存(分类、权限等),可以使用redis和mememcha,我个人建议,不要使用文件缓存,它也是对iO进行操作。
4.硬件方面。
1).可以考虑分库、分表。
2)可以采用主从复制,读写分离.(mysql服务器根据sql,去判断是读还是写)。
30.laravel保存session。
$request->session()->put('admin',$res);
$request->session()->save();//要加这一句,如果不加,不会保存session
//如果要保存session,都要调用save方法
转载请注明来源https://juejin.cn/post/6844904186350583821