尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

欢聚时代PHP校招笔试题复盘:从基础到系统设计自测清单

欢聚时代PHP校招笔试题复盘:从基础到系统设计自测清单 先说明一下我为什么专门去复盘一套2017年的校招笔试。那几年欢聚时代在PHP圈的校招讨论度一直不低因为题目风格很“务实”——不考函数背诵也不算偏题怪题几乎所有题都长在日常开发最容易踩坑的位置。换句话说这份卷子答得顺手说明平时写代码的习惯是好的答得稀烂那简历上“精通PHP”的水分大概不小。正是因为这种风格哪怕放到现在它依然是很好的PHP工程师自测清单。这篇文章就把这份B卷拆开揉碎过一遍。适合准备校招的PHP方向同学、刚转PHP的初级工程师以及想拿这套题考察团队候选人的技术负责人参考。我的建议是边看边在本地把代码跑一遍因为“看得懂”和“答得出”之间差着不少距离。1. 试卷整体风格它到底想筛什么样的人1.1 从题型分布看命题意图这类B卷一般不会只考一门语言而是围绕PHP工程师的日常能力边界出题。大致可以分成几个模块PHP基础语法和运行机制、面向对象与设计思想、MySQL与缓存、Web安全、算法逻辑、综合系统设计。这个分布本身就是答案——它想找的不是“PHP语法背得最熟的人”而是“能独立把一个Web系统从接口写到存储、再安全扛住线上压力的人”。一个很典型的特征是整套题里几乎没有纯记忆题。比如不会直接问“PHP中array_map的参数顺序是什么”而是给你一小段代码让你写出输出结果或指出问题。这种方式筛掉的正是靠刷题背答案的候选人。真正写代码的人面对这些题会有很强的熟悉感因为他踩过类似的坑。1.2 校招笔试的淘汰逻辑这里要泼一盆冷水校招笔试的通过率通常不高因为它优先做的是“排除法”。面试官心里很清楚应届生很难有深度项目经验所以笔试要解决的核心问题是——把“完全没写过代码”和“只是看过教程”的人先筛掉。所以B卷的难度设计是阶梯式的前面30%是基础送分题中间40%需要真实项目经验才能答好最后30%是拉分题专门用来区分“能干活”和“能扛事”的候选人。后面我会把每个梯队的题拿出来单独讲。2. PHP基础语法题看着都会一写就错2.1 高频考点类型比较、数组函数与引用陷阱这一部分是B卷的送分题区域但也是翻车重灾区。先说类型比较。PHP是弱类型语言和的区别几乎是必考题而真正有区分度的是下面这类比较$a 0; if ($a abc) { echo equal; } else { echo not equal; }在PHP 7及更早版本里这段代码会输出equal因为字符串abc和数字比较时会被转成数字0。这是很多老系统漏洞的来源。PHP 8开始改了字符串转数字的规则这类比较会输出not equal但如果你维护的是老项目这个坑依然在。答这道题的时候最好把PHP版本差异也说清楚面试官会认为你关注语言演进。再比如数组函数。array_merge对字符串键是覆盖对数字键是重新索引而运算符合并数组时是左边优先且不覆盖已有键。这两个看起来一样实际结果完全不同$a [1, 2]; $b [3, 4]; print_r(array_merge($a, $b)); // [1, 2, 3, 4] print_r($a $b); // [1, 2] $c [name a, age 18]; $d [name b, gender male]; print_r(array_merge($c, $d)); // name会被覆盖为b print_r($c $d); // name保持agender被追加这类题考察的是对函数行为底层逻辑的理解而不是背手册。2.2 字符串处理与错误处理字符串函数也是必考区。substr、strpos、str_replace本身不难但笔试里通常会和“中文字符串截取”绑定。PHP的substr是按字节截取的中文在UTF-8下占3个字节直接用substr截取会出现半个字符的乱码。B卷如果出这类题一般会问你“如何安全截取中文字符串”答案是mb_substr同时需要确保服务器安装了mbstring扩展。这个知识点虽然基础但能筛掉没有处理过中文数据的人。错误处理方面PHP从PHP 5开始有完整的异常机制但实际项目里很多人还是习惯用error_reporting加die。一道常见题目是让你写出在生产环境中正确记录错误的方式。参考答案是开发环境开启display_errors生产环境关闭display_errors而开启log_errors错误日志单独存放。更进一步的加分回答是用set_error_handler和set_exception_handler做全局接管甚至接入Monolog这类日志库。这明显是区分“会写代码”和“会运维代码”的知识点。2.3 序列化、反序列化与伪协议PHP的serialize和unserialize是面试高频点尤其是在安全类题目里。B卷里通常会给一段代码让你指出其中的安全漏洞$data $_COOKIE[user]; $user unserialize($data);unserialize一个用户可控的输入等于把反序列化漏洞直接送给攻击者。PHP对象注入和POP链的利用方式在近几年被研究得很透所以这类代码在笔试里出现频率极高。回答时至少要说清楚为什么不能反序列化用户输入以及如何用json_encode/json_decode或安全的序列化格式替代。如果能提到__wakeup、__destruct这些魔术方法在反序列化时会被自动调用就会得分更多。和序列化紧密相关的是PHP伪协议比如php://input、php://filter。这类题一般会放在文件包含漏洞的背景下考察include($_GET[page])时攻击者可以通过php://filter/convert.base64-encode/resourceindex.php读出源码。笔试里如果出现这个点说明公司很看重代码审计能力。3. 面向对象与设计思想不只要会用还要讲出理由3.1 魔术方法、抽象类、接口与trait面向对象题在B卷中的占比通常在20%左右考察方式很多样。比如让你写一个单例类题面可能只有一句话“请用PHP写一个单例类并说明为什么要将构造函数设为private”。很多候选人能写出构造函数私有化但会漏掉__clone和__wakeup的私有化这两个魔术方法是防止对象被克隆和反序列化绕过的关键。完整写法是class Singleton { private static ?Singleton $instance null; private function __construct() {} private function __clone() {} public function __wakeup() { throw new \Exception(Cannot unserialize singleton); } public static function getInstance(): Singleton { if (self::$instance null) { self::$instance new self(); } return self::$instance; } }PHP 7.4以上还支持类型属性?Singleton这种写法能给候选人加分说明你关注现代PHP特性。抽象类和接口的区别也是一个经典问题。最简洁的表述是接口是能力的约定抽象类是模板的复用。一个类可以实现多个接口但只能继承一个抽象类。更深入的问法是“如果需要定义一个支付接口里面有pay()、refund()方法不同支付渠道实现不同你会用接口还是抽象类为什么”这类场景题考的是设计判断而不是概念复述。trait在PHP里是水平复用的机制笔试中常见考察点是trait和继承的优先级当前类的方法覆盖trait的方法trait的方法又覆盖基类的方法。如果两个trait里有同名方法可以用insteadof和as解决冲突。这个知识点平时写业务可能用不到但能答出来会让面试官觉得你的PHP基础很扎实。3.2 命名空间与自动加载机制命名空间的考察通常会配合use、别名以及自动加载一起出现。有一道经典题是让你解释PSR-4自动加载规范的原理并手动写一个简单的自动加载器。自动加载的核心逻辑并不复杂根据类名中的命名空间找到对应的文件路径然后require_once。PSR-4的关键点在于“前缀匹配”比如命名空间App\Controller对应目录./app/Controller类名中的剩余部分就是文件路径。手动实现一个最简单版本spl_autoload_register(function ($class) { $prefix App\\; $baseDir __DIR__ . /src/; if (strncmp($prefix, $class, strlen($prefix)) ! 0) { return; } $relativeClass substr($class, strlen($prefix)); $file $baseDir . str_replace(\\, /, $relativeClass) . .php; if (file_exists($file)) { require $file; } });这道题考察的不只是语法而是你是否理解Composer依赖管理的底层原理。如果你能提到composer dump-autoload生成了autoload_static.php做的就是把PSR-4映射关系提前编译成数组面试官会认为你不只停留在使用层面。3.3 设计模式最常考的三个设计模式题在PHP笔试中不会出太偏的最高频的是单例、工厂、观察者。工厂模式里简单工厂和抽象工厂的差异值得说清楚。简单工厂就是根据参数返回不同实例它不属于GoF 23种设计模式但日常最常用抽象工厂则是创建一组相关对象的方法场景更复杂。笔试中级一点的题目是写一个发送通知的类支持短信、邮件、站内信并且后续要能扩展新渠道。最优解是定义一个通知接口各个渠道实现它再用一个工厂来创建渠道实例。如果能加上容器注册的思路说明你已经看过了主流框架的源码。我在实际开发里也验证过这类设计在业务膨胀之后维护成本差异巨大。4. MySQL与Redis数据层是PHP工程师的硬通货4.1 SQL基本功索引、执行计划与慢查询PHP工程师绝大多数都是CRUD工程师所以数据库题是B卷的绝对大头。最基础的是索引相关主键索引、普通索引、唯一索引、联合索引的区别以及最左前缀原则。考题通常长这样SELECT * FROM user WHERE age 18 AND city 北京 ORDER BY created_at DESC;要求你设计索引。答案不是盲建。先看等值条件city再看排序字段created_at最合理的联合索引是(city, created_at)因为age 18是范围条件放在联合索引里会导致后面的索引失效。用手写SQL的方式把索引设计思路表达出来是这道题拿高分的关键。另外还要解释为什么用联合索引而不是两个单列索引MySQL在5.0之后有了索引合并优化但大多数情况下单列索引合并的效果不如联合索引。在多个单列索引中MySQL只能选择区分度最高的一个使用其余列的过滤是在回表之后进行的效率差很多。EXPLAIN命令也是必考。重点看type列从const、ref、range到index、ALL访问效率依次降低。如果出现ALL全表扫描或Using filesort基本就是慢查询的元凶。我一般要求候选人至少要能说出这两点因为大部分线上慢SQL都能归因到它们。4.2 事务、隔离级别与MVCC事务的ACID四个特性是送分题真正的分水岭在隔离级别。MySQL默认的隔离级别是REPEATABLE READ可重复读InnoDB通过MVCC实现了在这个级别下的一致读。考题会问在可重复读隔离级别下两个事务同时更新同一行会发生什么答案是行锁等待第二个事务会阻塞直到第一个事务提交或回滚。更深入的追问是间隙锁Gap Lock什么情况下触发答案是当前隔离级别为可重复读并且通过非唯一索引或范围条件更新时。间隙锁是很多死锁问题的根源但同时也是防止幻读的重要手段。如果候选人在这个点上能主动提到底层原理说明他看过innodb存储引擎相关的文档。事务题还经常和代码结合比如让你指出下面代码的问题try { Db::beginTransaction(); $user Db::table(user)-find($id); $user-balance - 100; $user-save(); Db::commit(); } catch (\Exception $e) { Db::rollBack(); }这里至少有俩问题第一余额扣减没有做条件校验负数也能扣第二并发场景下这种“读改写”会丢更新应该用原子更新UPDATE user SET balance balance - 100 WHERE id ? AND balance 100。如果写成这样连锁等待的问题都规避了这才是面试官想看到的答案。4.3 Redis使用场景与缓存三大坑Redis题一般放在综合题里单独出题的话大概率是“简述缓存穿透、缓存击穿、缓存雪崩及解决方案”。这三个概念是面试必背题但B卷难度会再高一点让写一段伪代码实现缓存不存在时的互斥重建。缓存穿透指的是查询一个不存在的key每次都会打到数据库。解决方案是布隆过滤器或在缓存层缓存空值。缓存击穿是某个热点key过期瞬间大量请求打到DB解决办法是互斥锁或逻辑过期。缓存雪崩是大量key同时失效解决办法是过期时间加随机值。这些概念不难但写出代码就要费点功夫了。一段典型的互斥重建伪代码$data Redis::get($key); if ($data false) { $lockKey $key . _lock; if (Redis::set($lockKey, 1, [nx, ex 10])) { $data Db::table(...)-first(); Redis::set($key, $data, 3600); Redis::del($lockKey); } else { // 短暂休眠后重试 usleep(50000); $data Redis::get($key); } }如果候选人能主动提到分布式锁的过期时间要大于业务执行时间或者提到Redisson看门狗机制我就知道他对分布式场景有实践认知而不只是背诵。4.4 一个容易忽略的加分项Redis持久化与内存淘汰持久化题考RDB和AOF的区别RDB是快照恢复快但可能丢最近的数据AOF是追加日志数据更安全但文件大、恢复慢。生产环境通常两者结合使用。内存淘汰策略则要重点讲allkeys-lru和volatile-lru的区别尤其是关于热点数据缓存失效后如何防止雪崩可以和前面提到的缓存击穿联动回答。这个联动往往是B卷的隐藏加分点因为阅卷人希望看到系统的知识网络。5. Web安全必考题PHP工程师的职业道德题5.1 SQL注入原理与防御Web安全在PHP工程师笔试题中占据的比重比很多语言岗都高。原因很简单PHP历史上SQL注入漏洞数量太多如果候选人没有安全意识代码上线就是事故。最基础的题目是问SQL注入原理。注入产生的原因是用户输入被拼接到SQL语句中改变了原有语义。防御手段第一选择一定是预处理语句PDO prepared statements。笔试中爱出的细节题是PDO的prepare到底做了什么答案是预处理将SQL语句模板化客户端先将SQL结构发送给MySQL服务端进行解析之后再发送数据。数据不会参与SQL编译所以无论输入什么它都只是数据。这个机制把“结构”和“数据”在协议层面分开了比简单的字符串转义可靠得多。但要注意如果代码里用PDO模拟预处理或者错误地拼接了表名、列名预处理也救不了你。表名、列名属于SQL结构的一部分必须用白名单校验。5.2 XSS与CSRF前端安全后端也要管XSS题经常和PHP函数绑定考htmlspecialchars和htmlentities的区别。答案要点是htmlspecialchars只转义、、、、这几个特殊字符htmlentities会把更多字符甚至是所有HTML实体都转义。输出场景不同选择不同但核心原则是输出到HTML上下文的变量必须转义。更难一点的题让你分析存储型XSS的危害路径。攻击者在评论区提交一段script后端未转义入库其他用户访问时浏览器直接执行脚本攻击者可以窃取cookie、篡改页面、甚至发起请求。这里要重点答出为什么HttpOnly cookie能缓解但无法根治XSS因为攻击者虽然拿不到cookie但可以模拟用户操作。CSRF的防御三板斧校验Referer、加CSRF Token、设置SameSite Cookie。B卷里要是出到了最好把Token的存取方式说清楚比如Token要放在独立Cookie里还是放在表单隐藏域随机Token如何和Session绑定以及为什么Token不能放在URL参数里容易通过日志和Referer泄露。能说出这些细节的人至少是踩过安全的坑。5.3 文件上传与文件包含PHP特色漏洞文件上传漏洞是PHP笔试题的保留节目。核心在于“校验文件类型”这个环节的绕过方式只校验Content-Type可被工具伪造只校验扩展名可以传php.jpg甚至在Apache多后缀解析的特性下传shell.php.jpg也能被执行。稳妥的方案是白名单后缀校验、服务端MIME检查、文件重命名去掉用户控制的后缀、文件存储到独立静态域名、禁止执行目录权限。文件包含漏洞和伪协议经常一起考。include($_GET[page])这类代码攻击者可以传入../../etc/passwd做目录穿越也可以传php://filter读取源码。修复方案也简单不要使用用户输入拼接文件路径要么用映射表要么用白名单。在B卷中这类题往往是综合题因为它同时考察了代码审计、漏洞原理和修复能力一道题能测出三个维度。6. 算法与逻辑题校招生分水岭6.1 手写代码的规范比答案更重要PHP岗位的算法题不会像后端算法岗那样变态常见的是手写快排、链表反转、括号匹配、斐波那契数列、字符串去重。但PHP的语法噪音少写起来相对快所以阅卷人会更关注代码规范。举个例子求斐波那契数列第n项很多候选人会用递归function fib($n) { if ($n 1) return $n; return fib($n - 1) fib($n - 2); }这个答案能得基础分但要拿高分必须指出时间复杂度是O(2^n)n稍大就卡死。然后给出迭代版本function fib($n) { if ($n 1) return $n; $a 0; $b 1; for ($i 2; $i $n; $i) { [$a, $b] [$b, $a $b]; } return $b; }这题考察的不只是算法本身而是“是否理解复杂度、是否能从暴力解进化到最优解”的思维过程。如果时间允许还可以提一嘴矩阵快速幂能做到O(log n)这属于锦上添花。6.2 经典面试题括号匹配括号匹配是栈的典型应用PHP里可以用数组模拟栈function isValid(string $s): bool { $stack []; $map [) (, ] [, } {]; for ($i 0; $i strlen($s); $i) { $char $s[$i]; if (isset($map[$char])) { $top array_pop($stack); if ($top ! $map[$char]) { return false; } } else { $stack[] $char; } } return empty($stack); }这题得分的重点是用isset来判断右括号是否在映射数组里而不是用in_array因为哈希查找是O(1)而in_array是O(n)。这种微观优化思路阅卷人一眼就能看出来你是不是常年写业务代码。6.3 时间与空间复杂度分析笔试中还常给一段代码让你分析复杂度。比如双重循环的朴素字符串匹配你要能说出最坏情况O(n*m)并给出KMP、Boyer-Moore这类优化思路。对PHP工程师来说实际业务中很少手写KMP但如果能在考点上说出“PHP的strpos用的是类Sunday算法效率高很多”会让人印象很深。这是一种“工程直觉”的体现比背算法模板有价值。7. 综合应用与系统设计题给候选人一个“在线工单”7.1 场景题如何设计一个秒杀系统B卷的压轴题往往是这类场景题其中最经典的就是秒杀。这种题没有标准答案但一定有几个必须答到的点避免超卖、避免数据库被打爆、保证系统高可用。避免超卖是核心。简单做法是数据库乐观锁UPDATE goods SET stock stock - 1 WHERE id ? AND stock 0;受影响行数为1才算扣减成功。更工程化的方案是Redis预减库存先decr如果结果为负就说明卖完了。但这里有个细节Redis的decr原子操作没问题从“扣完库存”到“创建订单”中间还需要防重。完整路线通常长这样Nginx/LVS做接入层负载 → 请求进入应用后先做限流令牌桶或消息队列削峰→ Redis预减库存 → 写消息队列做异步下单 → 数据库层面用原子更新兜底 → 返回“排队中”页面前端轮询结果。要是候选人能主动提到消息队列的“消息丢失”如何通过定时任务对账来补偿那我基本可以确认他有真实的高并发项目经验或者至少系统啃过相关资料。7.2 API接口设计幂等与参数校验接口设计题也经常出现。比如“请设计一个用户注册接口需要考虑哪些方面”。参考答案协议用HTTPS请求方式POST参数做格式校验邮箱、手机号、密码强度接口做限流防刷返回格式统一异常要有错误码敏感字段不该返回的绝对不返回还要考虑注册接口的幂等性——防止用户重复点击导致重复注册。幂等性这块往往被校招生忽略。实现方式可以用Redis存储请求唯一标识比如前端生成的UUID第一次请求时SETNX成功后续相同请求直接返回第一次的结果。能答出这一点这道题就从及格跳到优秀了。再进阶一点可以提如何在网关层做统一签名校验防止参数被篡改这又回到了Web安全的基本功。7.3 如何应对这类“开放性”题目开放题最怕的是“少而空”。哪怕答得不全也要把已写出来的部分展开讲透。比如上面说的秒杀系统你哪怕只懂“Redis预减库存数据库原子更新”这一条链路也要把每个步骤的异常情况盘一遍Redis挂了怎么办消息队列积压怎么办订单创建失败要不要回补库存这些追问能体现工程思维的深度比列出一堆名词但没有细节强得多。我的经验是在校招笔试开放题中“想得细”比“知道得多”更容易让人记住你。8. 备考建议与真实体会8.1 刷题不如跑代码笔试前一个月与其抱着面经背不如把高频考点的代码都手敲一遍。PHP的一个好处是环境便宜装个小皮面板或直接用Docker起一个PHP容器就能跑。我当时备考时给自己定了个规矩每个知识点必须配套一段能跑的代码跑出结果再整理成笔记。这样考试时才不会卡在“好像见过但写不出来”的尴尬状态。8.2 提前准备一个能“打”的项目B卷里的综合题其实是在给候选人机会——让你用一个真实项目展示自己的能力边界。所以我强烈建议准备一个自己从零写过的项目不一定是高并发大流量系统哪怕是学校里的图书管理系统或社团网站只要你能讲清楚架构设计、数据表关系、用到哪些Redis场景、遇到过什么坑、怎么排查和修复的都比你简历上写“熟悉高并发”要有说服力得多。笔试中的开放题往往是让你把项目经历浓缩成设计答案。8.3 技术视野题不要限制在PHP本身有些题目看着是PHP其实在考你的技术视野。比如“如何理解PHP-FPM的工作模式”“为什么Nginx比Apache更适合PHP高并发场景”“Composer在部署时--no-dev的作用是什么”。这些知识点不在语言本身而在你日常是否关心生产环境。备考这类题最直接的方法是把自己平时开发环境的底层层扒开看看PHP-FPM的pm.max_children配了多少、每个worker占多少内存、OPcache有没有开启、命中率是多少。哪怕只看一遍也比背十篇面试题有用。8.4 关于“安全”这个隐藏线如果你把这份B卷从头翻到尾会发现安全知识几乎贯穿每个章节基础语法里的类型比较可能造成逻辑漏洞反序列化是安全大坑MySQL题里的预处理和权限设计Redis题里的未授权访问再加上专门的安全章节。这说明命题人对PHP工程师的期望是能写代码的同时还写安全代码。备考时一定要把OWASP Top 10过一遍并对应到PHP代码里找例子这是耗时少、收益最高的备考动作。我自己后来也帮团队整理过一套PHP工程师笔试题出题的思路就是参考欢聚时代这类卷子基础筛选、工程素养、安全意识、逻辑表达四层递进。这里想给准备面试的朋友提个醒笔试只是第一关它考察的是“下限”而面试里关于项目深挖的问题才决定你的“上限”。所以不要只背题把每个知识点都当成一次小项目去理解这比任何应试技巧都管用。
返回列表