电话:13485538018
关闭
您当前的位置:首页 > 职场资讯 > 面试秘籍

2025年PHP常见面试题整理!含答案及代码示例,还有啥变化?

来源:网络整理 时间:2025-09-25 作者:佚名 浏览量:

2025 年 PHP 常见面试题整理以及对应答案和代码示例

PHP 岗位面试一般会关注基本概念,比如数组运用、面向对象编程、异常管理等方面,此外也会涉及 PHP 新版本引入的一些先进功能,例如类型声明、类属性、枚举类型等。重点在于体现应聘者具备编写精简且行为稳定的代码能力,并且对 PHP 8 及之后版本中的革新有所掌握。

我梳理了部分 PHP 常见面试题,每道题都配有精炼的答案和可执行的代码片段,你可以直接拿去测试。

2025年关于PHP的基础知识问答汇总,包含正确解答和相关代码演示

PHP 8+ 中有哪些面试官关心的变化?

类型系统包含多种类型,如并集类型,由 int 和 float 组成,还有 mixed 类型,代表不确定类型,never 类型表示不存在的值,true|false|null 类型用于表示布尔值或空值,交集类型将多个类型合并,以及可空类型,在 T 后加问号 ? 表示该类型允许为空值。

面向对象编程的优化包括,构造函数中的属性初始化,只读的成员变量和类属性,枚举类型的使用,以及私有成员的限定

Override

属性。

流程管理:匹配语句,无递归;安全空值处理,采用问号箭头符号

提升开发感受:采用命名参数,增强属性/注解功能,运用JIT技术以改善性能,实现array_is_list()功能。

异常管理更加得当:对字符串与数值的比对逻辑进行了优化,例如 0 与 "foo" 进行对比时,系统现在会判定为不等。

如果你能清楚地解释这些特性,面试就会顺利很多。

PHP 中 == 和 === 的区别是什么?

== 执行类型转换;=== 要求相同类型和相同值。

检查数字四十二和字符串四十二是否相等,结果为真,因为在宽松模式下比较时会忽略类型差异
变量42与字符串"42"进行严格对比,结果为不成立,因为类型不同
// 从 PHP 8 开始:
0与"foo"比较结果为假,因为在旧版本中该值曾经为真

要点:默认使用 ===,除非有非常具体的理由不这样做。

联合类型、可空类型和交集类型如何工作?

定义一个名为area的函数,接收两个参数w和h,这两个参数可以是整数也可以是浮点数,函数返回值为浮点数类型,计算并返回结果
    return $w * $h;
}
这个函数用来打招呼,参数是一个可能为空的字符串,返回值是字符串类型。
返回"你好," . ($name === null ? "访客");
}
有一种约定俗成的规则,其中包含一个方法,这个方法不返回任何值,而且这个规则有一个名字,这个规则叫做A,这个方法叫做foo
一种约定性框架设有公开方法,该方法不返回任何值,且名为bar
class C implements A, B {
这个方法什么也不做,直接返回空值,没有任何操作,纯粹是空壳,不包含任何功能实现,只是声明了一个没有实际用途的函数,它不处理任何数据,也不产生任何输出,完全是形式上的存在,用来满足语法要求而已。
这个方法叫作bar,它不返回任何值,执行完毕后直接结束。
}
定义一个函数处理A和B的联合体,参数为类型为A与B的并集,返回值为空类型,该函数用于获取交集类型

nullsafe 操作符是什么,何时应该使用?

当左侧为 null 时,它会自动停止后续的方法/属性访问。

$user = null;
输出用户资料中的公司名称,如果没有则显示默认文本,具体做法是先查询用户信息,再查找个人资料,然后获取所在企业,若不存在该企业,则返回提示语

无需嵌套 if——简洁且安全。

什么时候应该使用 match 而不是 switch?

match 是一种表达式,能够产生值,它必须应对各种情形,不会像 switch 那样无差别地执行所有分支。

$status = 404;
$message = match ($status) {
    200, 201 => 'OK',
错误页面显示为不存在,内容为无法定位,信息提示为无此资源。
出现重大故障,系统无法响应,请稍后再试。
预设值转为未知,
};

这减少了因遗忘 break; 引起的错误。

在六十秒内说明 Composer 的自动加载机制,以及如何通过在 composer.json 文件中设置命名空间,将相应文件放置于恰当目录,以便 Composer 能够构建出自动加载文件

{
  "autoload": {
    "psr-4": {
      "App\": "src/"
    }
  }
}

// src/Service/Pinger.php
namespace AppService;
class Pinger {
这个方法叫做ping, 它执行后返回一个字符串, 内容是pong
}

// index.php
加载这个目录下的 vendor 自动加载文件,完成依赖项的初始化,确保后续代码能够正常运行,使用户无需手动引入各个库文件
use AppServicePinger;
执行新创建的Pinger对象的ping方法后,会得到响应"pong"

修改后运行 composer dump-autoload。

包含与加载的不同之处(以及 _once 变体)是什么?

必要的文件通过 require 引入,比如 bootstrap,而可选组件则用 include 处理

PHP 引用实际如何工作?

赋值操作具有写时复制的特性。通常情况下,没有必要使用引用。只有在应用程序需要更改参数值时,才需要借助引用。

定义一个名为bump的函数,接收一个引用类型的整型参数,该函数不做任何返回值,其作用是使传入的整型参数的值增加一。
$x = 5;
bump($x);
echo $x; // 6

避免为"微优化"使用引用。它们往往损害清晰度。

解释异常与错误(Throwable)

所有能被抛出的异常都继承自 Throwable 类。Exception 和 Error 是同源类别。

try {
引发一个运行时异常,消息内容为哎呀
在出现异常时进行捕获,针对所有类型的异常情况
    error_log($e->getMessage());
} finally {
    // 清理工作
}

在应用的外围部分,例如控制器那里,捕捉到可抛出异常很轻松,但在库的核心部分,应当针对更精细的异常种类进行捕获。

PDO 预处理语句防止 SQL 注入

这个数据库连接对象被初始化了,它依赖一个数据源名称,一个用户名,一个密码,以及一个配置数组,
设置错误模式为异常模式,捕捉异常信息并抛出异常,以便于处理数据库操作中的错误情况,增强代码的健壮性和可维护性。
]);
数据库查询语句已构建完成,用于检索用户信息,依据提供的电子邮箱地址进行筛选,查询范围涵盖全部用户字段,参数值通过命名占位符传递,具体为邮箱字段绑定标识符email。
该语句通过参数绑定执行查询,参数值为邮箱地址,使用数组形式传递,键名为email,值为变量email,确保了数据的安全性和有效性
变量赋值,通过执行语句获取结果,以关联数组形式返回,将内容存入指定标识符中,整个过程仅涉及单次数据提取操作,不包含循环或复杂逻辑,执行效率较高,适用于简单查询场景,结果直接赋值给变量,便于后续使用,无需额外处理步骤,完成数据传递与存储功能。

经验法则:始终使用预处理语句;永不插入不可信输入。

如何正确存储密码?

采用密码散列函数和密码验证函数,无需自行挑选散列方法——由 PHP 自动决定使用的默认算法。

这个变量赋值为密码经过加密后的结果,加密方式为默认算法,原始密码是用户输入的那条信息
当登录密码与存储的哈希值相匹配时,
    // 通过验证
}

PASSWORD_DEFAULT 会不断更新以适应 PHP 版本的演进,当 password_needs_rehash() 函数返回值为真时,就需要进行重新哈希处理。

属性(Attributes)是什么,如何读取?

属性是原生注解。你可以装饰类、方法等,并通过反射读取。

针对方法类型进行属性标记,属于特定目标范围
class Route {
这个函数在创建时会接收一个字符串参数,该参数指定了路径信息,并将其作为成员变量保存下来,路径信息以公开方式提供访问
}
class BlogController {
    #[Route('/posts')]
    public function index() {}
}
// 读取:
ReflectionMethod类的实例被创建,目标为BlogController类中的index方法
获取引用对象中关于路由类的所有属性,将它们存储在变量attrs里
路径赋值为第一个属性的实例化对象的路径属性,即斜杠加上posts

框架会用属性来处理路由、验证、依赖注入等功能。

枚举是什么,为什么有用?

枚举用真正的类型替换"字符串化"的常量。

enum Status: string {
    case Draft = 'draft';
情况是已发布等价于'pub'
}
定义一个名为发布的状态函数,参数为一个状态对象,返回值是一个布尔值
返回值等于状态已发布
}
发布草稿状态,结果为否定

枚举类型赋予具体数值后,可以确保比较操作的可靠性,同时还能让开发工具的智能补全功能更加高效。

readonly 属性和不可变对象

用来创建值对象或 DTO 非常合适。

final class Money {
    public function __construct(
        public readonly int $cents,
那个属于公开且只读的类型是货币,它的名称为货币,不可更改
    ) {}
}
创建一个金额对象,单位为美元,具体数额是一百,实例化后赋值给变量m
// $m->cents = 200; // 错误

PHP面试题2025_PHP8新特性面试题_php面试常问问题

也可以用 readonly 类来让全部属性都变成只读。

Trait vs 抽象类 vs 接口

trait LoggerTrait {
这个方法用来记录信息,参数是内容,它会显示这个内容,内容就是传入的信息。
}
interface Reportable {
这个方法公开调用后,会返回一个字符串类型的结果,用于汇报相关情况。
}
abstract class BaseReport {
公开方法获取数据,返回数组类型结果
}
这个类名为SalesReport, 它继承自BaseReport类, 同时实现了Reportable接口
    use LoggerTrait;
这个方法叫做data, 它返回一个数组, 数组里面包含三个整数, 分别是1, 2, 3.
这个方法叫做报告,它返回一个字符串,内容是将数据对象编码为JSON格式
}

延迟静态绑定(static:: vs self::)

自身限定作用于编程时的那个类别,静态限定则是在执行阶段才确定所属的类别。

class A {
这个方法以静态形式存在,它的作用是返回当前类名,通过调用特殊常量获取,整体过程非常直接,结果就是输出类标识符。
这个方法公开调用,返回一个字符串结果,该结果由另一个静态方法生成,这个方法确定当前的实体身份,整体过程比较直接,没有复杂逻辑,调用一次就能得到需要的信息,代码实现上非常简洁明了。
}
class B extends A {
    public static function who(): string { return __CLASS__; }
}
调用B类中的call方法后输出"B"字样,这个过程涉及到延迟静态方法绑定

基类如果要被继承的话,应该用 static::。

生成器(yield)处理大数据集

生成器采用懒加载——特别适合处理大量数据流。

创建一个函数,接收一个文件名作为参数,返回一个可迭代的对象,其中包含文件中的所有行。
文件以只读方式被打开,赋值给变量fh
    try {
当读取文件行不等于假时继续执行
            yield rtrim($line, "n");
        }
    } finally {
        fclose($fh);
    }
}
遍历文件内容,逐行获取,每次处理一个片段,文件名为huge.txt,按照顺序依次读取,直到全部完成。
    // 处理而不加载所有内容到内存
}

闭包、"use" 和箭头函数

$total = 0;
定义一个名为 add 的匿名函数,接受一个整数参数 n, 引用一个名为 total 的变量, 将 total 的值与 n 相加后赋值给 total。
array_map($add, [1,2,3]);
echo $total; // 6
这个函数通过箭头操作符定义,参数为变量x,返回值是x的两倍,这种方式能让函数自动获取参数值,无需显式声明

箭头表达式编写起来很精炼,常规函数式结构能够帮你严密限定参数获取情况。

会话和 Cookie:安全默认检查清单

session_set_cookie_params([
    'httponly' => true,
同站标识调整为宽松模式,
检查是否启用了安全连接,通过判断服务器变量中是否存在HTTPS键值,来确定当前是否处于加密通信状态
]);
session_start();
赋值给用户标识符变量,其内容为数字一百二十三,将此值存入会话数据存储区,以用户身份识别码作为索引键,确保后续操作能追踪到当前用户

处理日期:优先使用 DateTimeImmutable

创建一个不可变日期时间对象,设定时间为2025年3月1日9时,时区采用协调世界时
会议时间调整到开始时间之后一个小时,新的会议时间确定为这个值
输出开始时间的完整格式,包含年月日时分秒,使用特定格式化符号,结果直接显示在屏幕上
调用会议格式方法,参数为 c,得到新实例的日期显示

固定日期能够避免误操作更改,应当清楚设定时区,或者初始时应用 default_timezone_set 进行配置。

OPcache 和性能基础PHP 的垃圾收集器如何工作

PHP 依靠引用计数配合循环回收机制来处理内存分配问题。通常情况下无需特别关注这个环节。然而针对持续运行的程序体(例如 worker 或 daemon 类进程),当其中涉及众多数据结构或存在对象间的相互关联关系时,就必须主动清除相关引用并中断这些关联,从而可以更及时地回收内存资源。

常见数组陷阱和高级技巧

数组a包含两个元素, 其中元素x的值为1, 元素y的值为2
$b包含两个键值对, 第一个键是字母y, 值是数字3, 第二个键是字母z, 值是数字4
合并操作是两个集合相加的结果,其中元素按照键值排序,例如,键为x的元素值为1,键为y的元素值为2,键为z的元素值为4
合并这两个数组,得到的新数组包含所有元素,键值对形式为x对应1,y对应3,z对应4
列表中包含三个元素,分别是字母a,字母b,字母c。
从列表中删除位于第二位的一个元素,结果为['a','c']。
数组是列表类型(['a','b']),键值是连续的整数,结果为真
检查数组是否为列表结构,结果为不是;具体表现为输入参数为数组,其元素为键值对,其中键为字符串'1',值为字符串'a';经过判断,该数组不符合列表的定义;

了解何时要连接,何时要合并数组元素。

如何快速测试代码?

当 PHP_SAPI 等于 cli 时,
    assert(area(3, 4) === 12.0);
    echo "All goodn";
}

CLI断言有助于迅速核实程序的正确运作,即便是针对简短代码片段也非常实用。

关于 PHP 中的异步

PHP 自身采用同步的请求-响应架构,不过 Fiber(PHP 8.1版本新增功能)使 AMPHP 或 ReactPHP 等框架得以在用户层面完成并发处理。面试时无需实际编写异步代码,关键在于能阐述应用场景,例如 worker进程涉及密集的输入输出任务时,就需要采用异步方式。

快速问答

$_POST 和 php://input 有什么不同?$_POST 用于解析通过表单提交的编码数据,而 php://input 适合获取未处理的原始请求内容,特别是处理 JSON 数据时。

获取与设置?** 控制属性存取的隐藏函数——需慎重调用。

如何将对象转化为文本形式,需要确保输出结果为字符串类型。

这个函数执行效率不高吗,如果装了缓存模块,这个顾虑就不存在了;它讲究的是准确性,而不是快慢。

遍地都是静态函数? 它们对纯函数很实用;为了提升测试能力或配置灵活性,优先考虑依赖注入。

常量 vs 枚举? 枚举给你一个类型;常量只是值。

一个现代的 PHP 例子

role !== Role::Admin) {
引发运行时异常,信息为禁止访问。
        }
        // 假设我们在这里删除
返回删除用户编号{$userId}
    }
}
// 小型反射驱动的守卫:
ReflectionMethod类的实例被创建,目标为UserController类的delete方法
获取引用对象的属性值,以特定角色类为参数,取出第一个属性值,如果没有则返回空值,将结果赋值给变量
需要这个属性吗,如果存在就创建一个实例,然后获取它的角色,如果没有就返回空值
创建一个名为UserController的控制器实例,并将其赋值给变量$controller。
创建一个新用户实例,其ID为1,邮箱地址为a@ex.com,角色为管理员权限,并分配给变量admin
创建一个新用户实例,其标识为2,邮箱地址为g@ex.com,角色类型为普通用户
执行控制器删除操作针对管理员账号,参数为指定编号,输出结果后换行,显示已移除账号信息
try {
执行控制器删除操作,针对访客参数,指定编号为九十九,并输出结果
在出现运行时异常时进行捕获,并执行相应处理,
输出错误信息内容,换行显示,内容为禁止访问
}

这个简短内容呈现了:精确的类型定义、列举类型、只读特性、字段与常规异常——这些全部是“8.x时期”的亮点。

总结

如果你只记住一点:

考察的是思维逻辑性:需要阐述某个功能设置的原因,而并非仅仅介绍其操作方法。倘若你能为这些代码范例附上精炼的说明,论点将更具感染力。

微信扫一扫分享资讯
客服服务热线
13485538018
24小时服务
微信公众号
手机浏览

CopyrightC 2009-2025 All Rights Reserved 版权所有 芜湖人才网 本站内容仅供参考,不承担因使用信息、外部链接或服务中断导致的任何直接或间接责任,风险自担。如有侵权,请联系删除,联系邮箱:ysznh@foxmail.com 鄂ICP备2025097818号-15

地址: EMAIL:qlwl@foxmail.com

Powered by PHPYun.

用微信扫一扫