PHP面试题2019|权威整理 · 实战导向 · 持续更新 www.kaoacca.cn 蜀ICP备2026017620号-5

PHP面试题2019|2019最新PHP开发岗位技术面试真题汇总与深度解析

本页面系统梳理2019年PHP开发岗位主流技术面试高频考点,覆盖PHP基础语法、面向对象机制、MySQL数据库、主流框架(Laravel/ThinkPHP)、安全防护、性能调优、工程化实践等核心模块。每道题均附参考答案、答题思路、代码示例与常见陷阱提示,结合真实企业面试反馈整理而成,助你高效备战2019 PHP技术面试。

⚡ PHP基础与语法|核心考点精析

php面试题2019中,PHP基础题占比约30%,是考察程序员基本功的关键环节。以下精选高频真题,涵盖变量、数据类型、函数、面向过程等核心内容。

⑴ 请说明PHP中“==”与“===”的区别,并各举一例说明其结果。

参考答案:
== 是“值相等”比较(自动类型转换),=== 是“全等”比较(值+类型均相同,不转换)。

<?php
var_dump(0 == "0");    // true:字符串"0"转为整型0
var_dump(0 === "0");   // false:整型 vs 字符串
var_dump(null == false);   // true:都为“假值”
var_dump(null === false);  // false:类型不同
var_dump("123" == 123);   // true:字符串转为整型123
var_dump("123abc" == 123); // true:从"123"开始解析,忽略"abc"
?>

⚠️ 注意:“123abc”==123为true是PHP的弱类型陷阱,常导致逻辑漏洞!建议用===严格比较。

⑵ 请解释“变量引用”与“变量赋值”的区别,并写出以下代码输出结果:

$a = 10;
$b = $a;
$c = &$a;
$a = 20;
echo $b, ",", $c;

参考答案:
输出:10,20
- $b = $a:值复制,修改$a不影响$b
- $c = &$a:引用赋值,$c与$a共享同一内存地址,修改$a同步影响$c

⑶ PHP支持哪些预定义变量?请列举5个并说明用途。

参考答案:

变量名 用途 示例场景
$_GET 接收URL查询参数(GET请求) ?id=5&name=Tom → $_GET['id']
$_POST 接收表单提交数据(POST请求) 登录表单 → $_POST['username']
$_SESSION 会话变量,跨页面持久化数据 用户登录状态 → $_SESSION['user_id']
$_COOKIE 客户端Cookie数据 记住密码 → $_COOKIE['token']
$_SERVER 服务器与执行环境信息 $_SERVER['REQUEST_METHOD'] 获取请求方式

⑷ 请说明PHP中函数参数传递的三种方式(值传递、引用传递、默认参数),并各写一例。


function addOne($n) {
  $n += 1;
  return $n;
}
$x = 5;
echo addOne($x); // 6
echo $x;       // 5(未变)

function addOneRef(&$n) {
  $n += 1;
}
$y = 10;
addOneRef($y);
echo $y;  // 11(已变)

function greet($name = 'Guest') {
  echo "Hello, $name!";
}
greet();          // Hello, Guest!
greet('Alice'); // Hello, Alice!
  • php面试题2019中高频题:变量作用域(global vs static)、数组函数(array_map/array_filter)、字符串处理(explode/implode/substr)
  • 注意 empty() 对 0、'0'、""、null、false 均返回true
  • 理解 $_REQUEST = $_GET + $_POST + $_COOKIE(顺序由 variables_order 配置决定)
  • "0" == false 为 true,但 "0" === false 为 false → 避免用 == 判断布尔值
  • 字符串与数字比较时自动转换,如 "abc" + 1 = 1(非数字部分转为0)
  • 数组下标未定义时直接访问会触发 Notice: Undefined index
  • 始终使用 === 和 !== 进行比较(除非明确需要类型转换)
  • 函数参数使用类型声明(PHP7+):function sum(int $a, float $b): float
  • 用 isset() 检查数组下标是否存在:isset($arr['key'])

⚙️ 面向对象与设计模式|2019企业级考点

2019年PHP面试中,OOP与设计模式已成为中高级岗位的必考项。本模块聚焦真实面试题,涵盖类/对象机制、魔术方法、设计模式应用等。

⑴ 请写出PHP中8个常用魔术方法,并说明其触发时机。

参考答案:

魔术方法 触发时机 典型用途
__construct()对象创建时初始化属性(如数据库连接)
__destruct()对象销毁时释放资源(如关闭文件句柄)
__get($name)访问不可见属性动态属性代理(如延迟加载)
__set($name, $value)设置不可见属性属性赋值校验(如类型检查)
__isset($name)对不可见属性调用isset()自定义isset逻辑
__unset($name)对不可见属性调用unset()取消属性绑定
__call($name, $args)调用不可见方法实现动态方法(如API代理)
__toString()对象被当作字符串返回对象描述(如JSON序列化)

⑵ 请用单例模式实现一个数据库连接类(MySQLi),确保全局仅一个实例。

class DB {
  private static $instance = null;
  private $conn;
  // 私有化构造函数,禁止外部new
  private function __construct() {
    $this->conn = new MySQLi('localhost', 'root', 'pass', 'test');
    $this->conn->set_charset('utf8mb4');
  }
  // 私有化克隆,禁止clone
  private function __clone() {}
  // 获取唯一实例
  public static function getInstance() {
    if (self::$instance === null) {
      self::$instance = new self();
    }
    return self::$instance;
  }
  public function query($sql) {
    return $this->conn->query($sql);
  }
}
// 使用
$db = DB::getInstance();
$db->query("SELECT * FROM users");

⑶ 请简述工厂模式、观察者模式在PHP中的典型应用场景。

  • 工厂模式(Factory):解耦对象创建与使用。如Laravel的App::make()、ThinkPHP的Loader::factory(),避免硬编码new,便于替换实现(如从MySQL切换到Redis)。
  • 观察者模式(Observer):事件驱动架构。如Composer的事件监听器、ThinkPHP的钩子(Hook)机制。当用户注册时触发“send_welcome_email”事件,解耦业务逻辑。
  • 单例模式中必须私有化__construct、__clone,防止破坏唯一实例
  • 工厂模式需定义接口(Interface),实现类遵循契约
  • 观察者模式常用spl_*.register()或自定义事件总线
  • 滥用单例导致全局状态,难以测试与扩展(如数据库连接硬绑定)
  • 过度使用工厂增加代码复杂度,简单对象无需工厂
  • 观察者模式未注销监听者,导致内存泄漏(尤其在长生命周期对象中)

〔MySQL与SQL〕|数据库实战高频题

PHP与MySQL是黄金搭档,2019年面试中数据库题占比约25%。本模块聚焦索引优化、事务、慢查询等企业级考点。

⑴ 请解释InnoDB与MyISAM的核心区别,并说明在什么场景下应选择InnoDB。

参考答案:

特性 InnoDB MyISAM
事务支持✅ 支持ACID事务❌ 不支持
行级锁✅ 支持(高并发写入场景关键)❌ 表级锁(写入易阻塞)
外键约束✅ 支持❌ 不支持
崩溃恢复✅ 有自动恢复机制❌ 需手动修复
全文索引MySQL 5.6+ 支持原生支持

选择InnoDB场景:
• 高并发写入(如订单系统、日志表)
• 需要事务保证(如转账业务)
• 需外键约束(如用户-订单关联)
💡 提示:2019年MySQL默认引擎已全面转向InnoDB。

⑵ 请写出以下SQL的优化建议,并说明原因:

SELECT * FROM orders
WHERE user_id = 123
  AND status = 'pending'
  AND created_at > DATE_SUB(NOW(), INTERVAL 30 DAY);

参考答案:
1. 避免SELECT *:仅查询必要字段(如id, amount, created_at),减少I/O
2. 添加复合索引:INDEX idx_user_status_date (user_id, status, created_at)
3. 避免函数作用于索引列:created_at > DATE_SUB(...) 中DATE_SUB可改为常量:
created_at > '2019-06-15' -- 假设当前为2019-07-15
4. 分页优化:若用于分页,用WHERE id > last_id LIMIT 10替代LIMIT 1000000, 10(偏移过大时)

⑶ 请用EXPLAIN分析以下SQL,并指出索引使用情况:

EXPLAIN SELECT * FROM products
WHERE category_id = 5
  AND price > 100
ORDER BY created_at DESC
LIMIT 20;

参考答案:
关键字段解读:
• type:应为range(范围扫描),若为ALL则全表扫描需优化
• key:应显示使用了idx_category_price_date索引
• Extra:若含Using filesort,说明排序未走索引,需调整索引顺序为(category_id, price, created_at)

  • 最左前缀原则:复合索引(a,b,c)可命中a、a,b,但无法命中b,c
  • 避免在索引列上使用!=、LIKE '%xxx'(前缀模糊匹配可走索引)
  • 覆盖索引:查询字段全在索引中,无需回表(如SELECT id FROM t WHERE a=1)
  • InnoDB默认隔离级别为REPEATABLE READ,可能产生幻读(用next-key lock解决)
  • 长事务导致undo日志堆积,影响性能与主从同步
  • 避免在事务中执行SELECT ... FOR UPDATE后不提交/回滚

《Laravel框架》|2019主流框架深度考点

Laravel已成为PHP生态事实标准,2019年中高级岗位必考项。本模块聚焦服务容器、Eloquent ORM、事件系统等核心机制。

⑴ 请解释Laravel服务容器(Service Container)的绑定与解析过程,并写出三种绑定方式。

参考答案:
服务容器是Laravel的依赖注入(DI)核心,实现解耦与可测试性。
三种绑定方式:

// 1. 绑定接口到具体实现
$this->app->bind(UserRepositoryInterface::class, UserRepository::class);
// 2. 绑定单例(每次返回同一实例)
$this->app->singleton(CacheInterface::class, RedisCache::class);
// 3. 绑定闭包(自定义解析逻辑)
$this->app->bind(LoggerInterface::class, function ($app) {
  return new MonologLogger($app->make(LogManager::class));
});
💡 为什么用容器?
• 避免硬编码new,便于替换实现(如从MySQL切换到MongoDB)
• 自动注入依赖(构造函数自动解析)
• 支持延迟加载与测试替身(Mock)

⑵ 请写出Laravel中Eloquent ORM的以下操作代码:

  1. 查询用户及其关联的订单( eager loading )
  2. 按订单金额降序排列,取前10名用户
  3. 统计每个分类的商品数量
// 1. User模型关联 orders():hasMany
$users = User::with('orders')->get();
// 2. 按订单金额降序,取前10用户(需在User模型定义 orders_count
$users = User::withCount('orders')->orderBy('orders_count', 'desc')->take(10)->get();
// 3. 分类商品统计(Category模型关联 products():hasMany)
$categories = Category::withCount('products')->get();
// 或直接SQL聚合
$counts = DB::table('products')->select('category_id', DB::raw('COUNT(*) as product_count'))->groupBy('category_id')->get();

⑶ 请说明Laravel中Event、Listener与Broadcasting的协作机制。

参考答案:
1. Event:事件类,封装事件数据(如UserRegistered)
2. Listener:监听器,响应事件(如发送欢迎邮件)
3. Broadcasting:事件广播,将事件推送到前端(如WebSocket)

流程:
UserRegistered::dispatch($user) → UserRegisteredListener处理 → 若标记ShouldBroadcast,则通过Pusher/Beeper推送到前端

⚠️ 注意:广播需配置config/broadcasting.php,并启用Queue驱动(异步广播)。

  • 服务容器解析顺序:Concrete → Interface → Closure
  • 中间件(Middleware)在请求生命周期中位于路由匹配之后
  • Facade提供静态调用接口,本质是容器中服务的代理
  • 生产环境启用php artisan config:cache与route:cache
  • Eager loading避免N+1问题(用with())
  • 队列任务使用queue:work --queue=high,low区分优先级

『ThinkPHP框架』|国内主流框架实战题

ThinkPHP(TP5/TP6)在国内中小企业应用广泛,2019年面试中常考控制器、模型、路由等模块。

⑴ 请写出TP6中控制器接收POST数据的三种方式,并说明安全性差异。

// 1. Request对象(推荐)
$request = request();
$username = $request->post('username', '', FILTER_SANITIZE_STRING);
// 2. input()助手函数(简化版)
$username = input('post.username', '', FILTER_SANITIZE_STRING);
// 3. 直接$_POST(不推荐)
$username = $_POST['username']; // 未过滤,易XSS

安全建议:
• 总是使用filter_input()或框架封装方法
• 对输出进行转义(如htmlspecialchars())

⑵ 请用TP6模型实现“软删除”与“自动时间戳”。

use think\Model;
use think\model\concern\SoftDelete;
class Article extends Model
{
  use SoftDelete;
  // 自动时间戳(默认开启)
  protected $autoWriteTimestamp = true;
  // 字段类型自动转换
  protected $type = [
    'status' => 'integer',
    'created_at' => 'datetime',
  ];
}

💡 注意:软删除需在数据库添加delete_time字段(INT类型),删除时自动设置该值,查询时自动过滤delete_time IS NULL。

⑶ 请解释TP6路由中“路由分组”与“中间件绑定”的用法。

// routes/route.php
Route::group('api', function () {
  Route::get('users', 'api/User/index');
  Route::post('users', 'api/User/save');
})->middleware(AuthMiddleware::class);

所有/api/*路由均需通过AuthMiddleware验证,实现权限统一管理。

  • TP5:控制器需继承Controller,方法自动调用fetch()渲染模板
  • TP6:控制器无基类,返回View或Json对象
  • TP6支持composer原生PSR-4自动加载
  • TP6支持构造函数注入:public function __construct(UserService $userServ)
  • 使用app()解析服务:$service = app(UserService::class)

※ PHP安全与防御|2019最新漏洞防护要点

安全问题在2019年PHP面试中重要性显著提升。以下聚焦XSS、SQL注入、CSRF等高频漏洞。

⑴ 请说明SQL注入原理,并写出PHP中防止SQL注入的三种方法。

原理:攻击者通过拼接SQL语句注入恶意代码,如:
SELECT * FROM users WHERE username='admin' OR '1'='1'

防护方法:

  1. 预处理语句(Prepared Statements)(首选)
    $stmt = $mysqli->prepare("SELECT * FROM users WHERE email = ?");
    $stmt->bind_param('s', $email);
    $stmt->execute();
  2. 框架ORM(如Eloquent、ThinkPHP Query):自动使用预处理
  3. 转义函数(不推荐,仅备选):mysqli_real_escape_string()
⚠️ 警告:PHP 5.5+已废弃mysql_*系列函数,请使用mysqli或PDO。

⑵ 请写出XSS攻击的三种类型,并说明PHP中防御XSS的关键措施。

三种类型:
• 反射型XSS:恶意脚本通过URL参数反射回页面(如搜索结果页)
• 存储型XSS:脚本存入数据库(如评论内容)
• DOM型XSS:前端JS动态生成内容时未转义

防御措施:

  • 输出转义:htmlspecialchars($str, ENT_QUOTES, 'UTF-8')
  • 设置CSP头:Content-Security-Policy: default-src 'self'
  • 输入过滤:过滤<script>等危险标签(但转义更可靠)

⑶ 请说明CSRF攻击原理,并写出PHP中防御CSRF的两种方案。

原理:攻击者诱导用户访问恶意页面,利用用户已登录状态发起非法请求(如转账)。

防御方案:

  1. CSRF Token:
    • 表单中添加隐藏字段:
    • 后端验证:if ($_POST['token'] !== $_SESSION['token']) { ... }
  2. SameSite Cookie属性:
    Set-Cookie: sessionid=abc; SameSite=Strict
    (浏览器禁止跨站请求携带Cookie)

  • include($_GET['file']); → 文件包含漏洞
  • eval($_POST['code']); → 代码执行漏洞
  • move_uploaded_file($_FILES['f']['tmp_name'], 'uploads/'.$_FILES['f']['name']); → 文件上传漏洞
  • php -l file.php:语法检查
  • Snyk / SensioLabs:第三方依赖漏洞扫描
  • OWASP ZAP:安全测试工具

▲ 性能优化与工程化|2019高薪岗位加分项

2019年PHP高级岗位面试中,性能优化已成为区分初级与高级开发的关键分水岭。本模块聚焦缓存、数据库、JIT等实战技术。

⑴ 请列举5种PHP性能优化手段,并说明适用场景。

优化手段 原理 适用场景
OPcache 缓存预编译的字节码 所有生产环境(必开)
Redis缓存 内存级数据缓存 热点数据(如商品详情页)
数据库读写分离 主库写,从库读 读多写少场景(如博客系统)
异步任务队列 耗时操作走队列(如发送邮件) 非实时操作(提升响应速度)
CDN加速 静态资源分发 图片、JS、CSS等前端资源

⑵ 请解释PHP 7.4引入的JIT编译器,并说明其在2019年是否适合生产环境。

JIT(Just-In-Time)编译器:
将PHP字节码进一步编译为机器码,减少CPU解释开销。

2019年结论:
• PHP 7.4 JIT对纯计算型任务(如数学运算)有提升
• 但Web应用多为I/O密集型(数据库/网络),实际收益有限
• 官方明确建议:生产环境暂不启用JIT(2019年)

⑶ 请分析以下代码的性能问题,并给出优化方案:

for ($i = 0; $i < 1000000; $i++) {
  $data[] = get_user_data($i);
}

问题:
• 每次循环调用get_user_data(),触发数据库查询(N+1问题)
• 数组动态增长,频繁内存重分配

优化方案:

  1. 批量查询:
    $ids = range(1, 1000000);
    $users = User::whereIn('id', $ids)->get()-keyBy('id');
  2. 预分配数组:
    $data = array_fill(0, 1000000, null);
    foreach ($ids as $i =$value) {
      $data[$i] = get_user_data($i);
    }

  • Xdebug Profiler:生成调用图(如Webgrind可视化)
  • Blackfire:专业性能分析平台
  • microtime(true):简单计时
  • 微服务拆分:将高负载模块独立(如用户中心)
  • 服务网格(Service Mesh):Istio管理服务通信
  • Serverless:AWS Lambda处理突发流量

〖真实面试经验分享〗|2019 PHP开发岗面试复盘

我们收集了2019年7-12月国内主流互联网企业(BAT、TMD、独角兽)的PHP开发岗位面试反馈,整理出以下高频问题与优秀候选人回答策略。

⑴ 某大厂面试官原话:

“我们不会考死记硬背的语法题,但会问:
• ‘你最近项目中遇到的性能瓶颈是什么?如何定位和解决?’
• ‘如果线上服务突然变慢,你会从哪几个维度排查?’
• ‘你如何设计一个高并发的秒杀系统?’

希望候选人能结合真实项目经验,用‘问题-分析-解决-结果’结构作答。”
——某电商公司技术总监

⑵ 2019年面试趋势变化:

  • • 基础题占比下降:从2018年的45%降至30%
  • • 实战题上升:如“用Laravel实现一个带权限控制的API接口”
  • • 开源贡献加分:GitHub活跃、PR被合并者优先
  • • 软技能考察:沟通能力、团队协作、学习能力
2019年3月 · 某独角兽企业

3轮技术面 + 1轮HR面

• 一面:考察PHP基础与MySQL索引优化
• 二面:要求手写“分布式ID生成器”伪代码
• 三面:讨论缓存与数据库一致性方案
💡 建议:提前准备1-2个深度项目案例,突出技术决策过程。

2019年7月 · 某内容平台

现场编程 + 架构设计

• 编程题:实现“无限级分类”树形结构(递归/迭代)
• 架构题:如何设计一个支持千万级用户的评论系统?
💡 建议:画架构图辅助说明,强调可扩展性与容灾设计。

2019年11月 · 某金融科技公司

安全专项 + 现场调优

• 安全题:如何修复一个XSS漏洞?写出修复代码
• 调优题:给一段慢SQL,现场优化并解释原因
💡 建议:展示调试过程(如用EXPLAIN),而非仅给结论。

⑶ 面试官最反感的3种回答:

错误回答 问题 正确方向
“我只用过ThinkPHP,其他没接触过” 技术视野狭窄 “主要用TP6,但了解Laravel服务容器原理,可快速上手”
“SQL优化靠DBA,我不需要管” 缺乏工程意识 “会写EXPLAIN分析SQL,能与DBA协作优化索引”
“性能问题直接加机器” 缺乏技术深度 “先定位瓶颈点(CPU/IO/网络),再针对性优化”

▲ 2019年PHP生态大事记(面试加分背景知识)

2019年7月 · PHP 7.4发布

新增:Typed Properties(属性类型)、Null Coalescing Assignment Operator(??=)、Array Expansion(解包)

2019年11月 · Laravel 6.0发布

LTS版本,支持Symfony 5组件、自定义Artisan命令优化、邮件队列改进

2019年12月 · ThinkPHP 6.0正式版

全命名空间、PSR规范、依赖注入增强,告别“全家桶”旧模式

斌知网
蜀ICP备2026017620号-5