PHP 怎么面试准备

wen PHP项目 2

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) {
        // 处理不存在的静态方法
    }
}
?>

面试要点:

PHP 怎么面试准备

  • 面向对象三大特性(封装、继承、多态)
  • 魔术方法(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 基础类:

  1. PHP 中如何实现一个单例模式?
  2. 简述 PHP 垃圾回收机制?
  3. 什么是数组和对象的区别?
  4. 如何实现两个大数组求交集?
  5. PHP 中 session 的工作原理?

MVCC 与框架:

  1. Laravel 和 ThinkPHP 的区别?
  2. 什么是依赖注入?实现原理?
  3. Eloquent ORM 如何处理 N+1 问题?
  4. 如何处理路由冲突?

MySQL类:

  1. 索引为什么能提高查询速度?
  2. 什么情况下索引失效?
  3. 如何处理死锁?
  4. 分库分表有哪些策略?
  5. 主从复制原理?

Redis类:

  1. Redis 数据类型及使用场景?
  2. 什么是缓存穿透、击穿、雪崩?
  3. Redis 的持久化策略?
  4. Redis 集群方案?

系统设计类:

  1. 设计一个短链接系统?
  2. 如何设计消息队列?
  3. 高并发下如何设计秒杀系统?

答题技巧

STAR法则:

  • Situation(情景):描述背景
  • Task(任务):说明任务
  • Action(行动):具体行动
  • Result(结果):展示成果

实例:

Q: 你如何优化一个慢接口?

A:

  • Situation: 用户反馈订单列表接口耗时3秒
  • Task: 需要降至500ms以内
  • Action:
    1. 使用 Xdebug 性能分析定位瓶颈在数据库查询
    2. 添加组合索引 idx_status_created_at
    3. 引入 Redis 缓存列表
    4. 使用分页游标优化
  • Result: 接口耗时降至120ms,QPS提升10倍

简历准备建议

技术亮点描述技巧

❌ 平淡描述:

  • 熟悉 PHP
  • 会使用 MySQL
  • 了解 Redis

✅ 亮点描述:

  • 基于 PHP 原生实现高可用分布式任务调度系统,日均处理 2000万+ 任务
  • 利用 Redis 队列 + 多进程模式,将订单处理效率提升 300%
  • 设计并实现统一缓存策略,缓存命中率达 95%,请求响应时间降低 60%
  • 通过代码生成器 + 自动化测试,将开发效率提升 2 倍

面试前最后准备

技术环境

  • 本机搭建一个可演示的项目
  • 准备几个性能对比的截图
  • 准备架构设计图

模拟练习

  • 找朋友进行模拟面试
  • 录制自己的回答并复盘改进
  • 练习手写算法(冒泡排序、二分查找、链表反转等)

心态调整

  • 提前一天休息好
  • 面试时自信而不自大
  • 不知道的问题坦诚说明,展示学习能力

每日复习计划:

  • 早晨30分钟:复习基础知识
  • 下午30分钟:学习新技术
  • 晚上1小时:实战编码(刷 LeetCode)
  • 每周1次:模拟面试

面试不是考死记硬背,而是考察解决问题的能力和学习潜力,把面试当作一次技术交流,分享你真实的经验和思考过程,加油!💪

抱歉,评论功能暂时关闭!