常见的PHP面试问题及其解法

  1. 写一个函数,接受一个字符串参数,并返回反转的字符串。
	function reverseString($string) {
    	return strrev($string);
	}
  1. 写一个函数,接受一个数组参数,并返回数组中最大值和最小值的差。
	function maxMinDifference($array) {
	    sort($array);
	    return end($array) - reset($array);
	}
  1. 写一个函数,接受一个数组参数,并检查该数组是否是二维的。
	function is2DArray($array) {
    	return is_array($array[0]);
	}
  1. 写一个函数,接受一个字符串参数,并返回该字符串的长度,不考虑多字节字符。
	function lengthWithoutMultibyte($string) {
    	return strlen($string);
	}
  1. 写一个函数,接受一个数组参数,并返回数组中的所有键。
	function getArrayKeys($array) {
    	return array_keys($array);
	}
  1. 写一个函数,接受一个数字参数,并返回该数字的平方。
	function squareNumber($number) {
    	return $number * $number;
	}
  1. 写一个函数,接受一个字符串参数,并返回字符串中字符的所有不同排列。
	function permuteString($string) {
	    if (strlen($string) <= 1) {
	        return array($string);
	    }
	    $result = array();
	    for ($i = 0; $i < strlen($string); $i++) {
	        $char = $string[$i];
	        $remainingString = substr($string, 0, $i) . substr($string, $i + 1);
	        $newPermutations = permuteString($remainingString);
	        foreach ($newPermutations as $permute) {
	            $result[] = $char . $permute;
	        }
	    }
	    return $result;
	}
  1. 写一个函数,接受一个数组参数,并返回数组中所有的奇数。
	function getOddNumbers($array) {
	    return array_filter($array, function($value) {
	        return $value % 2 !== 0;
	    });
	}
  1. 如何在PHP中强制转换类型?

    输出类型的名称必须在要强制转换的变量前的括号中指定,如下所示:

    (int), (integer) - 强制转换为整型

    (bool), (boolean) - 强制转换为布尔值

    (float), (double), (real) - 强制转换为浮点型

    (string) - 强制转换为字符串

    (array) - 强制转换为数组

    (object) - 强制转换为对象

  2. MyISAM和 InnoDB 的基本区别?索引结构如何实现?

    A、MyISAM类型不支持事务,表锁,易产生碎片,要经常优化,读写速度较快,
    适合用于频繁查询的应用;
    B、InnoDB类型支持事务,行锁,有崩溃恢复能力,读写速度比MyISAM慢,
    适合于插入和更新操作比较多的应用,空间占用大,不支持全文索引等。
    创建索引:alert table tablename add index 索引名 (字段名)

  3. 在程序的开发中,如何提高程序的运行效率?

    A、优化SQL语句,查询语句中尽量不使用select *,用哪个字段查哪个字段;
    少用子查询可用表连接代替;少用模糊查询;
    B、数据表中创建索引;
    C、对程序中经常用到的数据生成缓存。

  4. 对于大流量的网站,您采用什么样的方法来解决访问量问题?

    A、有效使用缓存,增加缓存命中率
    B、使用负载均衡
    C、对静态文件使用cdn进行存储和加速
    D、想法减少数据库的使用
    E、查看出现统计的瓶颈在哪里
    F、反向代理

  5. 简述php的垃圾收集机制。

    php中的变量存储在变量容器zval中,zval中除了存储变量类型和值外,还有is_ref和refcount字段。

    refcount表示指向变量的元素个数,is_ref表示变量是否有别名。

    如果refcount为0时,就回收该变量容器。

    如果一个zval的refcount减1之后大于0,它就会进入垃圾缓冲区。

    当缓冲区达到最大值后,回收算法会循环遍历zval,判断其是否为垃圾,并进行释放处理。

  6. 如何把一个GB2312格式的字符串装换成UTF-8格式?

    iconv(‘GB2312’,‘UTF-8’,‘js代码(https://www.csdn.net/)学习平台。’);?>

  7. 什么是 CSRF 攻击 ?XSS 攻击?如何防范?

    CSRF,跨站请求伪造,攻击方伪装用户身份发送请求从而窃取信息或者破坏系统。讲述基本原理:用户访问A网站登陆并生成了cookie,再访问B网站,如果A网站存在CSRF漏洞,此时B网站给A网站的请求(此时相当于是用户访问),A网站会认为是用户发的请求,从而B网站就成功伪装了你的身份,因此叫跨站脚本攻击。
    CSRF防范:A、合理规范api请求方式,GET,POSTB、对POST请求加token令牌验证,生成一个随机码并存入session,表单中带上这个随机码,提交的时候服务端进行验证随机码是否相同。

    XSS,跨站脚本攻击。

    防范:不相信任何输入,过滤输入。

  8. 安全对一套程序来说至关重要,请说说在开发中应该注意哪些安全机制?

    A、防远程提交;
    B、防SQL注入,对特殊代码进行过滤;
    C、防止注册机灌水,使用验证码。

  9. 常用的魔术方法有哪些?

    php规定以两个下划线(__)开头的方法都保留为魔术方法,所以建议大家函数名最好不用__开头,除非是为了重载已有的魔术方法。
    __construct() 实例化类时自动调用。
    __destruct() 类对象使用结束时自动调用。
    __set() 在给未定义的属性赋值的时候调用。
    __get() 调用未定义的属性时候调用。
    __isset() 使用isset()或empty()函数时候会调用。
    __unset() 使用unset()时候会调用。
    __sleep() 使用serialize序列化时候调用。
    __wakeup() 使用unserialize反序列化的时候调用。
    __call() 调用一个不存在的方法的时候调用。
    __callStatic()调用一个不存在的静态方法是调用。
    __toString() 把对象转换成字符串的时候会调用。比如 echo。
    __invoke() 当尝试把对象当方法调用时调用。
    __set_state() 当使用var_export()函数时候调用。接受一个数组参数。
    __clone() 当使用clone复制一个对象时候调用。

  10. $this和self、parent这三个关键词分别代表什么?在哪些场合下使用?

    $this 当前对象;self 当前类;parent 当前类的父类;
    $this在当前类中使用,使用->调用属性和方法self也在当前类中使用,不过需要使用::调用parent在类中使用

  11. __autoload()方法的工作原理是什么?

    答:使用这个魔术函数的基本条件是类文件的文件名要和类的名字保持一致。
    当程序执行到实例化某个类的时候,如果在实例化前没有引入这个类文件,那么就自动执行__autoload()函数。

    这个函数会根据实例化的类的名称来查找这个类文件的路径,当判断这个类文件路径下确实存在这个类文件后

    就执行include或者require来载入该类,然后程序继续执行,如果这个路径下不存在该文件时就提示错误。

    使用自动载入的魔术函数可以不必要写很多个include或者require函数。

  12. 简述高并发网站解决方案。

    A、前端优化(CND加速、建立独立图片服务器)
    B、服务端优化(页面静态化、并发处理[异步|多线程]、队列处理)
    C、数据库优化(数据库缓存[Memcachaed|Redis]、读写分离、分库分表、分区)
    D、Web服务器优化(负载均衡、反向代理)

  13. 如何解决异常处理?

    抛出异常:使用 try…catch,异常的代码放在 try 代码块内,如果没有触发异常,则代码继续执行,如果异常被触发,就会抛出一个异常。Catch 代码块捕获异常,并创建一个包含异常信息的对象。$e->getMessage(),输出异常的错误信息。 解决异常:使用 set_error_handler 函数获取异常(也可以使用 try()和 catch()函数),然后使用 set_exception_handler()函数设置默认的异常处理程序,register_shutdown_function()函数来执行,执行机制是,php 要把调入的函数调入到内存,当页面所有的 php 语句都执行完成时,再调用此函数

  14. TP权限管理(RBAC)的实现?

    1.首先创建一张用户表:id name auto(保存格式为:控制器-方法)
    2.然后在后台中创建一个基类控制器,控制器里封装一个构造方法,当用户登陆成功后,使用 TP 框架中封装好的 session 函数获取保存在服务器中的 session id,然后实例化模型,通过用户 id 获取保存在数据表中的 auth 数据,使用 explode 函数分割获取到的数据,并使用一个数组保存起来,然后使用 TP 框架中封装好的常量获取当前控制器和方法,然后把他们组装成字符串,使用 in_array 函数进行判断该数组中是否含有当前获取到的控制器和方法,如果没有,就提示该用户没有权限,如果有就进行下一步操作

  15. 怎么保证促销商品不会超卖

答:这个问题是我们当时开发时遇到的一个难点,超卖的原因主要是下的订单的数目和我们要促销的商品的数目不一致导致的,每次总是订单的数比我们的促销商品的数目要多,当时我们的小组讨论了好久,给出了好几个方案来实现: 第一种方案是:①在每次下订单前我们判断促销商品的数量够不够,不够不允许下订单,更改库存量时加上一个条件,只更改商品库存大于 0 的商品的库存,当时我们使用 ab 进行压力测试,当并发超过 500,访问量超过 2000 时,还是会出现超卖现象。所以被我们否定了。 第二种方案是:②使用 mysql 的事务加排他锁来解决,首先我们选择数据库的存储引擎为 innoDB,使用的是排他锁实现的,刚开始的时候我们测试了下共享锁,发现还是会出现超卖的现象。有个问题是,当我们进行高并发测试时,对数据库的性能影响很大,导致数据库的压力很大,最终也被我们否定了。 第三种方案是:③使用文件锁实现。当用户抢到一件促销商品后先触发文件锁,防止其他用户进入,该用户抢到促销品后再解开文件锁,放其他用户进行操作。这样可以解决超卖的问题,但是会导致文件得 I/O 开销很大。 最后我们使用了 redis 的队列来实现。将要促销的商品数量以队列的方式存入 redis 中,每当用户抢到一件促销商品则从队列中删除一个数据,确保商品不会超卖。这个操作起来很方便,而且效率极高,最终我们采取这种方式来实现

  1. 商城秒杀的实现

    答:抢购、秒杀是如今很常见的一个应用场景,主要需要解决的问题有两个: 1 高并发对数据库产生的压力 2 竞争状态下如何解决库存的正确减少(”超卖”问题) 对于第一个问题,已经很容易想到用缓存来处理抢购,避免直接操作数据库,例如使用 Redis。 第二个问题,我们可以使用 redis 队列来完成,把要秒杀的商品放入到队列中,因为 pop 操作是原子的,即使有很多用户同时到达,也是依次执行,文件锁和事务在高并发下性能下降很快,当然还要考虑其他方面的东西,比如抢购页面做成静态的,通过 ajax 调用接口,其中也可能会出现一个用户抢多次的情况,这时候需要再加上一个排队队列和抢购结果队列及库存队列。高并发情况下,将用户进入排队队列,用一个线程循环处理从排队队列取出一个用户,判断用户是否已在抢购结果队列,如果在,则已抢购,否则未抢购,库存减 1,写数据库,将用户入结果队列。

  2. 接口安全方面是怎么处理的

    使用 HTTP 的 POST 方式,对固定参数+附加参数进行数字签名,使用的是 md5 加密
    比如:我想通过标题获取一个信息,在客户端使用 信息标题+日期+双方约定好的一个 key 通过 md5 加密生成一个签名(sign),然后作为参数传递到服务器端,服务器端使用同样的方法进行校验,如何接受过来的 sign 和我们通过算法算的值相同,证明是一个正常的接口请求,我们才会返回相应的接口数据。

  3. 支付宝流程怎么实现的
    首先要有一个支付宝账号,接下来向支付宝申请在线支付业务,签署协议。
    协议生效后有支付宝一方会给网站方一个合作伙伴 ID,和安全校验码,有了这两样东西就可以按照支付宝接口文档开发支付宝接口了,中间主要涉及到一个安全问题。
    整个流程是这样的:我们的网站通过 post 传递相应的参数(如订单总金额,订单号)到支付页面,支付页面把一系列的参数经过处理,以 post 的方式提交给支付宝服务器,支付宝服务器进行验证,并对接收的数据进行处理,把处理后的结果返回给我们网站设置的异步和同步回调地址,通过相应的返回参数,来处理相应的业务逻辑,比如返回的参数代表支付成功,更改订单状态。

  4. 如何处理负载、高并发?(好好看看,经常问到,能回答到主要的东西即可)

    从低成本、高性能和高扩张性的角度来说有如下处理方案:
    1、HTML 静态化其实大家都知道,效率最高、消耗最小的就是纯静态化的 html 页面,所以我们尽可能使我们的 网站上的页面采用静态页面来实现,这个最简单的方法其实也是最有效的方法。
    2、图片服务器分离把图片单独存储,尽量减少图片等大流量的开销,可以放在一些相关的平台上,如七牛等
    3、数据库集群和库表散列及缓存数据库的并发连接为 100,一台数据库远远不够,可以从读写分离、主从复制,数据库集群方面来着手。另外尽量减少数据库的访问,可以使用缓存数据库如 memcache、redis。
    4、镜像:尽量减少下载,可以把不同的请求分发到多个镜像端。
    5、数据库优化6、负载均衡:Apache 的最大并发连接为 1500,只能增加服务器,可以从硬件上着手,如 F5 服务器。当然硬件的成本比较高,我们往往从软件方面着手。负载均衡 (Load Balancing) 建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展网络设备和服务器的带宽、增加吞吐量、加强网络数据处理能力,同时能够提高网络的灵活性和可用性。
    目前使用最为广泛的负载均衡软件是 Nginx、LVS、HAProxy。

  5. 了解大部分数组处理函数

    strlen():返回字符串的长度

    strpos():查找字符串中某个子串首次出现的位置

    substr():返回字符串的一个子串

    str_replace():替换字符串中的一部分内容

    strtoupper():将字符串转换为大写

    strtolower():将字符串转换为小写

    trim():去除字符串两端的空白字符(或其他指定字符)

    字符串处理函数 区别 mb_ 系列函数

    mb_系列函数对适用于中文字符

    & 引用,结合案例分析

    引用修改变量值的时候会改变原变量的值

    == 与 === 区别

    == 会进行类型转换来使比较成立,而 === 要求值和类型都必须完全匹配

    isset() 与 empty() 区别

    isset()是测试变量是否被赋值;empty()是测试一个已经被赋值的变量是否为空;isset()能传入多个变量;empty()只能传入一个变量

  6. 给定二维数组,根据某个字段排序

    在 PHP 中,你可以使用 usort() 函数来对二维数组进行排序。usort() 函数允许你自定义排序算法。以下是一个示例,展示了如何根据二维数组中的某个字段进行排序:

<?php

// 示例二维数组
$students = [
    ['name' => 'John', 'age' => 20],
    ['name' => 'Jane', 'age' => 22],
    ['name' => 'Bob', 'age' => 19],
    ['name' => 'Alice', 'age' => 21],
];

// 根据 'age' 字段进行排序
usort($students, function($a, $b) {
    return $a['age'] - $b['age'];
});

// 打印排序后的结果
foreach ($students as $student) {
    echo $student['name'] . ' - ' . $student['age'] . "\n";
}

?>

  1. 快速排序


function quickSort($arr) {
    $length = count($arr);
    
    // 如果数组为空或只有一个元素,则无需排序
    if ($length <= 1) {
        return $arr;
    }
    
    // 选择一个基准值(这里选择第一个元素作为基准值)
    $pivot = $arr[0];
    
    // 初始化两个数组,分别用于存储小于和大于基准值的元素
    $less = [];
    $greater = [];
    
    // 遍历数组,将元素分配到小于和大于基准值的数组中
    for ($i = 1; $i < $length; $i++) {
        if ($arr[$i] < $pivot) {
            $less[] = $arr[$i];
        } else {
            $greater[] = $arr[$i];
        }
    }
    
    // 递归对小于和大于基准值的数组进行排序,并将结果与基准值合并
    return array_merge(quickSort($less), [$pivot], quickSort($greater));
}

// 示例用法
$arr = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5];
$sortedArr = quickSort($arr);
print_r($sortedArr);

  1. . 冒泡排序


function bubbleSort($array){
    $count = count($array);
    for ($i=0;$i<$count-1;$i++){
        for ($j=0;$j<$count-$i-1;$j++) {
            if($array[$j] > $array[$j+1]) {
                $t = $array[$j];
                $array[$j] = $array[$j+1];
                $array[$j+1] = $t;
            }
        }
    }
    return $array;
}

  1. 乘法表


for($i=1;$i<=9;$i++)  //控制行数
{
    for ($k=1; $k <=$i; $k++) { //控制列数
        echo $k."*".$i."=".$k*$i.'\t';
    }
    echo '\n';
}

  1. 正则匹配邮箱与手机号

	//正则匹配邮箱
	$mail = '11aaa@qq.com';  //邮箱地址
	$pattern = "/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,})$/";
	preg_match($pattern, $mail, $matches);
	var_dump($matches);  //输出匹配结果

	$str = '13012345678';
	preg_match_all("/^1[34578]\d{9}$/", $str, $mobiles);//[3456789]
	var_dump($mobiles); //输出匹配结果


  1. 网站基本概念

    1. 服务器概念
      服务器是为电脑提供服务的电脑,本地电脑如果有公网IP,那也能当作服务器工作
      服务器是计算机的一种,它比普通计算机运行更快,负载更高、价格更贵。 服务器在网络中为其它客户机(如PC机、智能手机、ATM等终端)提供计算或者应用设备。 服务器具有高速的CPU运算能力、长时间的可靠运行、强大的I/O外部数据吞吐能力以及更好的扩展性。 根据服务器所提供的服务,一般来说服务器都具备承担响应服务请求、承担服务、保障服务的能力。 服务器作为电子设备,其内部的结构与普通的计算机内部结构相差不大,如:CPU、硬盘、内存,系统、系统总线等。
      服务器:是能够提供服务的机器,取决于机器上所安装的软件

    2. IP概念
      IP指网际互连协议,Internet Protocol的缩写,是TCP/IP体系中的网络层协议。设计IP的目的是提高网络的可扩展性:一是解决互联网问题,实现大规模、异构网络的互联互通;二是分割顶层网络应用和底层网络技术之间的耦合关系,以利于两者的独立发展。根据端到端的设计原则,IP只为主机提供一种无连接、不可靠的、尽力而为的数据包传输服务。IP具有唯一性(每台电脑都有其唯一的IP)。

    3. 域名
      域名,又称网域,是由一串用点分隔的名字组成的互联网上某一台计算机或计算机组的名称,用于在数据传输时对计算机的定位标识(有时也指地理位置)

      特殊IP:127.0.0.1(代表本机)

      特殊域名:localhost

    4. DNS
      DNS(域名系统),因特网上作为域名和IP地址互相映射的一个分布式数据库,能够使用户更方便的访问互联网,而不用去记住能够被机器直接读取的IP数串。通过主机名,最终得到该主机对应的IP地址的过程叫做域名解析(或主机名解析)。

      用户输入域名localhost --> DNS(localhost 127.0.0.1) --> 服务器电脑

    5. 端口
      端口是英文port的意译,可以认为是设备与外界通讯交流的出口。端口可分为虚拟端口和物理端口,其中虚拟端口指计算机内部或交换机路由器内的端口,不可见。例如计算机中的80端口、21端口、23端口等。物理端口又称为接口,是可见端口,计算机背板的RJ45网口,交换机路由器集线器等RJ45端口。电话使用RJ11插口也属于物理端口的范畴。

  2. 预防SQL注入攻击的最佳实践

  • 永远不要相信用户输入的数据。验证用户输入数据的类型、长度、格式等,以避免攻击者使用非法字符或恶意代码来攻击您的应用程序。

  • 使用PDO或mysqli扩展库中提供的预处理语句和绑定变量来执行SQL查询。

  • 不要在数据库查询中使用拼接字符串的方式来构造SQL查询语句,这样很容易被攻击者利用。

  • 对于PHP应用程序中的用户输入,可以通过使用filter_input()函数来过滤和验证数据。

  • 禁用PHP的magic_quotes_gpc配置选项,以避免自动添加反斜杠导致的问题。

  • 如果您不需要在SQL查询中使用通配符,请避免使用LIKE操作符。LIKE操作符在模式匹配时容易被攻击者利用。

  • 34
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

①菜鸟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值