Bootstrap

2023PHP面经、面试题汇总——持续更新中

笔试部分

2023.7.9——中电金信PHP笔试部分内容

1、下面代码若是想要输出n,索引值应该是0,1,2,3中哪一个?答案:1
<?php
$arr = array(
    'a',
    'b' => 'c',
    'd' => 'g',
    'n'
);
echo $arr[?];
2、写一个排序[45,65,89,35,56]让数组从小到大排序
<?php

/**
 * 冒泡排序算法
 * @param array $arr 排序数组
 */
function bubbleSort(array $arr = [])
{
    for ($i = 0; $i < count($arr) - 1; $i++) {//比多少次
        for ($j = $i + 1; $j < count($arr); $j++) {//每一次比多少回
      	// 如果前者大于后者交换两个位置的值
            if ($arr[$i] > $arr[$j]) {
         	// 方案一
            // $temp = $arr[$i];
            // $arr[$i] = $arr[$j];
            // $arr[$j] = $temp;

         	// 方案二
                list($arr[$i], $arr[$j]) = [$arr[$j], $arr[$i]];
            
            //方案三
            //$arr[$i], $arr[$j] = $arr[$j],$arr[$i]
            }
        }
    }

   // 返回排序后的数组
    return $arr;
}

2023.7.17——24届百度秋招提前批一面

题目:给定一个数组(数组中只有一个重复值),找出数组中的重复值,数组:[1,3,4,2,2]

<?php
function SortData(array $arr){
    $length = count($arr);
    for ($i = 0;$i < $length - 1;$i++){
        for ($j = $i + 1;$j < $length;$j++){
            if ($arr[$i] == $arr[$j]){
                return $arr[$i];
            }
        }
    }
}
$arr = [1,3,4,2,2];
$res = SortData($arr);
var_dump($res);

算法部分

常见的几种排序方法

一、冒泡排序
<?php

function maopao(array $arr = []){
    
    for($i = 0;$i < count($arr) - 1;$i++){
        for($j = 0;$j < count($arr) - 1 -$i;$j++){

            if($arr[j] > $arr[j + 1]){
                $temp = $arr[j];
                $arr[j] = $arr[$j + 1];
                $arr[j + 1] = $temp;
            }
        }

    }
    return $arr;
}
二、快速排序

介绍:把一个序列分为较大和较小的序列,然后递归的排序两个序列,最后合并得到结果。

<?php

function Quicksort($arr = [5,64,10,8,2,33,34,55,65,25,1,7]){
    $len = count($arr);
    if($len <= 1){
        //当数据已经不可分了返回结果
        return $arr;
    }

    $left = [];
    $right = [];
    
    //分割数组
    for($i = 1;$i < $len;$i++){
        $middle[0] = $arr[0];
        if($arr[$i] < $middle[0]){
            $left[] = $arr[$i];
        }else{
            $right[] = $arr[$i];
        }
    }
    
    //重复调用,直到数据不能分割
    $this->Quicksort($left);
    $this->Quicksort($right);
    return array_merge($left,$middle,$right);
}

面试部分

面向对象编程和面向对象设计五个基本原则

单一职责原则:

介绍:一个类有且只有一个理由允许它的改变,一个类的边界和职责是比较狭窄且集中的;只做自己的事情,其余不管。

开放封闭原则:

介绍:又称为开闭原则,对外访问时开放的,对内修改是封闭的。

里氏替换原则:

介绍:规定对象可以被子类的实例替换,但也不影响程序的正确性。

接口隔离原则:

介绍:不应该强制接口的实现依赖于它不使用的方法。

依赖反转原则:

介绍:规定高层次的代码不应该依赖低层次的代码;也就是说高层次的代码应该依赖抽象接口,抽象接口负责连接高层次和低层次的代码。

秒杀——商品超卖、高并发、同一用户多次抢购

简介

redis队列实现(包含库存队列、排队队列、抢购结果队列)

大致流程

用户先进入排队队列,先进先出;然后判断是否已经在抢购结果队列,如果在,那就进行下一个,如果不在,那就将用户信息加入抢购结果队列;库存-1,等待数据库空闲时,将结果写入数据库。

接口安全问题

介绍:使用POST请求,对接口请求参数以必要参数和附加参数进行数字签名,常用md5加密;比如我要通过id获取数据,那么我就将id+md5对当前时间、id和双方约定好的特定值进行加密后传到服务器端,服务器端使用同样的方法先验证数字签名是否正确,然后再进行数据的获取和返回。

如何处理负载、高并发

一、静态化

消耗最小、效率最高的就是纯静态化的html页面,尽量采用静态网页,这是最简单、有效的方法。

二、图片服务器分离

将图片单独存储,减少图片等大流量的开销,可以放在一些相关的平台上,使用的时候调用就行。

三、数据库集群和库表散列及缓存

数据库的并发连接是100,一台数据库完全不够,可以从读写分离、主从复制、数据库集群方面着手;尽量减少数据库的访问;也可以使用缓存数据库,比如redis、memcache等。

四、负载均衡

介绍:Apache最大连接数是1500,只能增加服务器,也可以从硬件上着手,但是一般硬件成本比较高,所以都往软件方面下手。

负载均衡是建立在现有网络结构上的,它提供了一种廉价有效透明的方法扩展网络设备的带宽,增加吞吐量,加强网络数据处理能力,同时能提高网络的灵活性和可用性;目前最火热的负载均衡软件是nginx、LVS等。

修改会话的生存时间

php.ini中,session.gc_maxlifetime = 1400//默认时间

<?php
$session_time = 24 * 3600;
session_set_cookie_params($session_time);
session_start();

PHP的GC

简介

php的gc使用引用计数的回收机制,同时使用根缓存区机制。

根缓存区

当发现存在循环引用Zval(Zval是zend中另一个非常重要的数据结构,用来标识并实现PHP变量。包含了PHP中的变量值和类型的相关信息,Zend引擎是PHP的核心组件之一,它是PHP语言的解释器和执行引擎,负责将PHP代码转换为可执行的指令,并在运行时管理变量、内存和对象生命周期等方面提供支持。)时,就会把其投入到根缓存区,当根缓存区达到配置的数量后,就会对其进行回收释放,依次来解决循环引用导致的内存泄露问题。

引用计数

每个对象都包含一个引用计数起,每当其被调用的时候,计数器就+1,当引用它的对象离开生存空间或者被设置为null,办它的计数器就-1,当它的计数器为0的时候,php知道你不用这个对象了,就对其进行回收释放。

读取文件中的加锁和解锁操作

<?php

$flie = fopen('test.txt','r+');//读写方式打开
if(flock($file,LOCK_EX)){//取得独占锁,写入资源;LOCK_SH:取得共享锁;LOCK_UN:释放锁
    fwrite($file,"hello word!");
    //释放锁
    flock($file,LOCK_UN);
}
fclose($file);

array_merge()、array_merge_recursive()函数介绍和区别

介绍:

将一个或多个数组合并成一个数组;

区别:

array_merge:如果合并的数组中元素具有相同的键名,那么后面的元素会覆盖其它的元素;但是两个都是索引数组的话就不会覆盖,键名都是整数,会返回带有整数键名的新数组,其索引从0开始进行重新索引。

array_merge_recursive:不会进行索引覆盖,而是将键名相同的元素递归成一个数组。

对于大流量的网站采用哪些方式来解决访问量的问题

1、硬件设施优化;

2、数据库读写分离、优化数据表;

3、优化sql语句;

4、禁止外部盗链;

5、使用不同主机分流主要的流量;

6、加上负载均衡;

7、使用流量统计分析软件。

echo、print、print_r、var_dump的区别

echo

输出一个或多个字符串,中间以逗号隔开,没有返回值,只是语言结构不是一个函数,因此不能作为表达式的一部分使用;

print

有返回值,只能接收一个变量、打印一些简单类型的变量,返回true或者false;

print_r

可以打印复杂的变量类型,比如数组、对象以列表形式显示,并以array、object开头,但print_r输出布尔值和NULL的结果没有意义,因为都是打印"\n",因此var_dump()函数更适合调试;

var_dump

打印变量的相关信息。

扩展:

ob_start() - 打开输出控制缓冲

var_export() - 输出或返回变量的可解析字符串表示

超全局变量

$REQUEST:可以接收到post、get请求的数据;

$GET:获取get请求的数据;

$POST:获取post请求的数据;

$GLOBALS:所有的变量都在里面;

$_SESSION:会话控制;

$_COOKIE:会话控制;

$_SERVER:获取服务器相关信息;$_SERVER 是一个包含例如头信息(header)、路径(path)、以及脚本位置(script locations)等等信息的数组。这个数组中的项目由 Web 服务器创建。不能保证每一个服务器 都提供全部项目; 服务器可能会忽略一些,或者提供一些没有在这里列举出来的项目;

$FILES:上传文件的时候使用;

$_ENV : 获取服务器端环境变量的数组。

常见魔术常量

__LINE__文件中的当前行号。

__FILE__文件的完整路径和文件名。

__FUNCTION__函数名称

__CLASS__类的名称

__METHOD__类的方法名

__DIR__文件的目录(不包含当前文件名)

__NAMESPACE__命名空间名称

魔术方法

介绍

php在面向对象编程时有一些特殊的方法,会在特定的时机自动调用,我们将这类方法称为魔术方法

1.__construct,__destruct

__constuct构建对象的时被调用; __destruct明确销毁对象或脚本结束时被调用;

2.__get,__set

__set当给不可访问或不存在属性赋值时被调用 __get读取不可访问或不存在属性时被调用

3.__isset,__unset

__isset对不可访问或不存在的属性调用isset()或empty()时被调用 __unset对不可访问或不存在的属性进行unset时被调用

4.__call,__callStatic

__call调用不可访问或不存在的方法时被调用 __callStatic调用不可访问或不存在的静态方法时被调用

5.__sleep,__wakeup

__sleep当使用serialize时被调用,当你不需要保存大对象的所有数据时很有用 __wakeup当使用unserialize时被调用,可用于做些对象的初始化操作

6.__clone

进行对象clone时被调用,用来调整对象的克隆行为

7.__toString

当一个类被转换成字符串时被调用

8.__invoke

当以函数方式调用对象时被调用

9.__set_state

当调用var_export()导出类时,此静态方法被调用。用__set_state的返回值做为var_export的返回值。

10.__debuginfo

当调用var_dump()打印对象时被调用(当你不想打印所有属性)。

双引号和单引号的区别

双引号可以解释变量,单引号不解释变量;

如果双引号中插入单引号,单引号中有变量,那就进行变量解释;

双引号的变量名后面必须要有一个非数字、字母、下划线的特殊字符,或者用{}讲变量括起来,否则会将变量名后面的部分当做一个整体,引起语法错误;

双引号解释转义字符,单引号不解释转义字符,但是解释’\和\;

能使单引号字符尽量使用单引号,单引号的效率比双引号要高(因为双引号要先遍历一遍,判断里面有没有变量,然后再进行操作,而单引号则不需要判断)

isset、empty的区别

介绍:在PHP中isset()和empty()之间很容易混淆,它们都是用于测试变量的值,都返回一个布尔值。

isset

语法:bool isset ( mixed var [, mixed var [, ...]] )

1、传一个值时,如果值存在且不为空才返回true;

2、穿的值为空或者不存在都返回false;

3、传多个值也一样,每个值都必须保证存在且不为空才能返回true,否则返回false。

empty

语法:bool empty ( mixed $var )

当var存在,并且是一个非空非零的时候返回false,否则返回true。

1、变量存在,值为空,返回true;

2、变量不存在,返回true;

3、变量存在,值不为空,返回false。

以下的变量会被认为是空的:

"" (空字符串)

0 (作为整数的0)

0.0 (作为浮点数的0)

"0" (作为字符串的0)

NULL

FALSE

array() (一个空数组)

$var; (一个声明了,但是没有值的变量)

require、require_once、include、include_once区别

不带once

require引入文件,假如引入文件出错会直接报错并且终止程序;一般用于程序最开始读取文件。(因为文件导入失败会直接报错,比较严谨,建议使用,不建议使用括号,因为它们并不是真正的函数)

include引入文件出错会报出一个警告,程序继续执行;一般用于程序过程中读取文件的地方。

带once

1、如果该文件中已经被包含过,则不会再次包含。如同此语句名字暗示的那样,只会包含一次;

2、可以用于在脚本执行期间同一个文件有可能被包含超过一次的情况下,想确保它只被包含一次以避免函数重定义,变量重新赋值等问题。

session、cookie区别

1、session可以存储任意类型的数据,但cookie只能存储字符串;

2、cookie产生在服务器端、存储在客户端浏览器;session产生在服务器端、存储在服务器端;

3、cookie支持跨域名访问,session不支持跨域名访问;

4、cookie可以达到长期有效;session依赖于名为JSESSIONID的cookie,而cookie JSESSIONID的过期时间默认为-1,只需关闭窗口该session就会失效,因而session不能达到长期有效的效果。

5、cookie不安全,session在服务器端相对安全;

6、

6.1单个cookie保存的数据<=4KB,一个站点最多保存20个Cookie;

6.2对于session来说并没有上限,但出于对服务器端的性能考虑,session内不要存放过多的东西,并且设置session删除机制。

;