PHP 后端开发面试准备指南
核心知识体系
PHP 语言基础
// 面试高频考点示例
<?php
// 1. 变量作用域
$name = 'John';
function test() {
// global 关键字
global $name;
// 或 $GLOBALS['name'];
return $name;
}
// 2. 引用 vs 值传递
function addOne(&$num) {
$num++;
}
$count = 5;
addOne($count); // $count 变为 6
// 3. 魔术方法
class User {
private $data = [];
public function __get($name) {
return $this->data[$name] ?? null;
}
public function __set($name, $value) {
$this->data[$name] = $value;
}
public function __call($name, $arguments) {
// 处理不存在的静态方法
}
}
?>
面试要点:

- 面向对象三大特性(封装、继承、多态)
- 魔术方法(construct, destruct, get, set, __call)
- 命名空间和自动加载(PSR-4)
- Trait 的使用场景
- 设计模式(单例、工厂、观察者等)
框架知识
主流框架对比:
| 框架 | 特点 | 适用场景 |
|---|---|---|
| Laravel | 语法优雅,生态丰富 | 中大型项目 |
| ThinkPHP | 中文文档完善,上手快 | 中小型项目 |
| Symfony | 组件化,企业级 | 大型复杂系统 |
| Yii2 | 性能好,安全机制完善 | 高并发场景 |
Laravel 核心概念:
// 服务容器(依赖注入)
app()->bind('PaymentService', function() {
return new StripePayment();
});
// 门面模式(Facade)
use Illuminate\Support\Facades\Cache;
Cache::put('key', 'value', 600);
// 中间件
public function handle($request, Closure $next) {
if (!$request->user()->isAdmin()) {
return redirect('/');
}
return $next($request);
}
// Eloquent ORM
$users = User::where('age', '>', 18)
->with('posts')
->orderBy('created_at', 'desc')
->paginate(10);
MySQL 数据库
索引优化:
-- 创建组合索引 CREATE INDEX idx_user_age_name ON users(age, name); -- Explain 分析 EXPLAIN SELECT * FROM users WHERE age > 18; -- 慢查询优化 SET GLOBAL slow_query_log_file = '/var/log/mysql/slow.log'; SET GLOBAL slow_query_log = ON; SET GLOBAL long_query_time = 2;
事务隔离级别:
- READ UNCOMMITTED(读未提交)
- READ COMMITTED(读已提交)
- REPEATABLE READ(可重复读)- MySQL 默认
- SERIALIZABLE(串行化)
Redis/Cache
常见应用场景:
// 缓存用户信息
$user = Redis::get('user:' . $userId);
if (!$user) {
$user = DB::table('users')->find($userId);
Redis::setex('user:' . $userId, 3600, serialize($user));
}
// 分布式锁
$lock = Redis::setnx('lock:order:' . $orderId, 1);
if ($lock) {
Redis::expire('lock:order:' . $orderId, 30);
// 处理订单
Redis::del('lock:order:' . $orderId);
}
// 排行榜
Redis::zincrby('ranking:today', 1, $userId);
$top10 = Redis::zrevrange('ranking:today', 0, 9, 'WITHSCORES');
缓存策略:
- 缓存穿透:空值缓存、布隆过滤器
- 缓存击穿:互斥锁、逻辑过期
- 缓存雪崩:随机过期时间、分布式锁
实战项目准备
电商系统
技术架构:
前端(Vue/React) → Nginx → PHP-FPM(Laravel)
↓
业务逻辑层(Service)
↓
Redis缓存 ←→ MySQL主从
核心功能实现:
// 1. 商品列表缓存
class ProductService {
public function getProducts($categoryId, $page = 1) {
$cacheKey = "products:category:{$categoryId}:page:{$page}";
return Cache::remember($cacheKey, 3600, function() use ($categoryId, $page) {
return Product::where('category_id', $categoryId)
->paginate(20);
});
}
}
// 2. 订单创建(事务处理)
class OrderService {
public function createOrder($userId, $items) {
DB::transaction(function() use ($userId, $items) {
$order = Order::create([
'user_id' => $userId,
'order_no' => $this->generateOrderNo(),
'total_amount' => $this->calculateTotal($items)
]);
foreach ($items as $item) {
$order->items()->create($item);
// 扣减库存
Product::where('id', $item['product_id'])
->where('stock', '>=', $item['quantity'])
->decrement('stock', $item['quantity']);
}
// 发送消息到队列
event(new OrderCreated($order));
});
}
}
// 3. 秒杀功能
class SeckillService {
public function seckill($userId, $seckillId) {
// 原子操作获取商品
$product = Redis::eval("
local stock = tonumber(redis.call('get', KEYS[1]))
if stock > 0 then
redis.call('decr', KEYS[1])
return 1
end
return 0
", 1, "seckill:product:{$seckillId}");
if ($product) {
// 异步队列处理订单
dispatch(new SeckillOrderJob($userId, $seckillId));
}
}
}
面试追问点:
- 如何保证库存不超卖?
- 如何防止用户重复下单?
- 如何处理高并发?
- 缓存和数据库一致性问题?
技术深度准备
性能优化
// 1. 代码层面优化
class PerformanceOptimization {
// 使用预加载
public function getUsers() {
// 用 with() 避免 N+1 查询
return User::with('posts.author')
->limit(100)
->get();
}
// 手动缓存
private static $cache = [];
public function getSetting($key) {
if (isset(self::$cache[$key])) {
return self::$cache[$key];
}
self::$cache[$key] = DB::table('settings')
->where('key', $key)
->value('value');
return self::$cache[$key];
}
}
// 2. 使用连接池(Swoole)
$server = new Swoole\Server("0.0.0.0", 9501);
$server->on('WorkerStart', function ($server, $workerId) {
// 创建 MySQL 连接池
$mysql = new MysqlPool();
$server->mysql = $mysql;
});
高并发处理
// 1. 消息队列使用(RabbitMQ)
class MessageQueue {
public function publish($queue, $message) {
$connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');
$channel = $connection->channel();
$channel->queue_declare($queue, false, true, false, false);
$channel->basic_publish(
new AMQPMessage(json_encode($message)),
'',
$queue
);
}
}
// 2. 异步任务(Gearman)
$client = new GearmanClient();
$client->addServer('127.0.0.1', 4730);
$result = $client->doNormal(
'sendMail',
json_encode(['email' => 'user@example.com', 'content' => 'Hello'])
);
安全防护
// 1. SQL 注入防护
$query = "SELECT * FROM users WHERE username = :username";
$stmt = $db->prepare($query);
$stmt->bindValue(':username', $username);
$stmt->execute();
// 2. XSS 防护
$cleanData = htmlspecialchars($userInput, ENT_QUOTES, 'UTF-8');
// 3. CSRF 防护
echo csrf_field();
// 生成CSRF Token
$token = bin2hex(random_bytes(32));
// 4. JWT 认证
class JWTService {
public function generateToken($userId) {
$payload = [
'user_id' => $userId,
'exp' => time() + 3600
];
$token = JWT::encode($payload, config('jwt.secret'));
return $token;
}
}
面试模拟与技巧
高频面试题整理
PHP 基础类:
- PHP 中如何实现一个单例模式?
- 简述 PHP 垃圾回收机制?
- 什么是数组和对象的区别?
- 如何实现两个大数组求交集?
- PHP 中 session 的工作原理?
MVCC 与框架:
- Laravel 和 ThinkPHP 的区别?
- 什么是依赖注入?实现原理?
- Eloquent ORM 如何处理 N+1 问题?
- 如何处理路由冲突?
MySQL类:
- 索引为什么能提高查询速度?
- 什么情况下索引失效?
- 如何处理死锁?
- 分库分表有哪些策略?
- 主从复制原理?
Redis类:
- Redis 数据类型及使用场景?
- 什么是缓存穿透、击穿、雪崩?
- Redis 的持久化策略?
- Redis 集群方案?
系统设计类:
- 设计一个短链接系统?
- 如何设计消息队列?
- 高并发下如何设计秒杀系统?
答题技巧
STAR法则:
- Situation(情景):描述背景
- Task(任务):说明任务
- Action(行动):具体行动
- Result(结果):展示成果
实例:
Q: 你如何优化一个慢接口?
A:
- Situation: 用户反馈订单列表接口耗时3秒
- Task: 需要降至500ms以内
- Action:
- 使用 Xdebug 性能分析定位瓶颈在数据库查询
- 添加组合索引 idx_status_created_at
- 引入 Redis 缓存列表
- 使用分页游标优化
- Result: 接口耗时降至120ms,QPS提升10倍
简历准备建议
技术亮点描述技巧
❌ 平淡描述:
- 熟悉 PHP
- 会使用 MySQL
- 了解 Redis
✅ 亮点描述:
- 基于 PHP 原生实现高可用分布式任务调度系统,日均处理 2000万+ 任务
- 利用 Redis 队列 + 多进程模式,将订单处理效率提升 300%
- 设计并实现统一缓存策略,缓存命中率达 95%,请求响应时间降低 60%
- 通过代码生成器 + 自动化测试,将开发效率提升 2 倍
面试前最后准备
技术环境
- 本机搭建一个可演示的项目
- 准备几个性能对比的截图
- 准备架构设计图
模拟练习
- 找朋友进行模拟面试
- 录制自己的回答并复盘改进
- 练习手写算法(冒泡排序、二分查找、链表反转等)
心态调整
- 提前一天休息好
- 面试时自信而不自大
- 不知道的问题坦诚说明,展示学习能力
每日复习计划:
- 早晨30分钟:复习基础知识
- 下午30分钟:学习新技术
- 晚上1小时:实战编码(刷 LeetCode)
- 每周1次:模拟面试
面试不是考死记硬背,而是考察解决问题的能力和学习潜力,把面试当作一次技术交流,分享你真实的经验和思考过程,加油!💪