PHP作为常用的后端开发语言,在Web开发领域应用广泛,面试中常围绕基础特性、核心功能、实践场景等方向出题。掌握高频面试题的答题思路,能有效提升面试竞争力。

PHP基础语法类面试题
1. PHP中单引号和双引号字符串有什么区别?
单引号字符串不会解析变量和转义字符(除了'和\),双引号字符串会解析变量和大部分转义字符。性能上单引号字符串处理更快,因为不需要解析变量内容。
示例代码如下:
<?php $name = "张三"; // 单引号不会解析变量 echo '我的名字是$name'; // 输出:我的名字是$name // 双引号会解析变量 echo "我的名字是$name"; // 输出:我的名字是张三 ?>
2. 如何定义一个常量,和变量有什么区别?
定义常量使用define()函数或者const关键字,常量一旦定义不能修改和销毁,不需要加$符号,作用域是全局的。变量用$符号开头,可随时修改销毁,有作用域限制。
代码示例:
<?php
// define定义常量
define("SITE_NAME", "测试站点");
// const定义常量
const VERSION = "1.0.0";
echo SITE_NAME; // 输出:测试站点
echo VERSION; // 输出:1.0.0
?>
数组与函数类面试题
3. PHP中数组有哪几种类型,如何区分?
PHP数组分为索引数组和关联数组,索引数组的键是整数,默认从0开始递增;关联数组的键是字符串,由用户自定义。也可以使用array_keys()函数判断键的类型来区分。
<?php // 索引数组 $index_arr = [1, 2, 3]; // 关联数组 $assoc_arr = ["name" => "李四", "age" => 20]; print_r($index_arr); print_r($assoc_arr); ?>
4. 写出至少三个常用的数组排序函数,说明它们的区别?
常用排序函数有sort()、asort()、ksort()。sort()对索引数组按值升序排序,会重置索引;asort()对关联数组按值升序排序,保留键名;ksort()对关联数组按键名升序排序。
<?php $arr = ["b" => 3, "a" => 1, "c" => 2]; sort($arr); // 索引数组升序,结果:[1,2,3] asort($arr); // 按值升序保留键名,结果:a=>1,c=>2,b=>3 ksort($arr); // 按键名升序,结果:a=>1,b=>3,c=>2 ?>
面向对象类面试题
5. PHP中public、protected、private访问修饰符有什么区别?
public修饰的成员可以在类内部、子类、类外部访问;protected修饰的成员可以在类内部、子类访问,不能在类外部访问;private修饰的成员只能在类内部访问,子类和类外部都无法访问。
<?php
class Test {
public $public_var = "公开属性";
protected $protected_var = "受保护属性";
private $private_var = "私有属性";
public function show() {
echo $this->public_var;
echo $this->protected_var;
echo $this->private_var;
}
}
$obj = new Test();
echo $obj->public_var; // 可以访问
// echo $obj->protected_var; // 报错,无法访问
// echo $obj->private_var; // 报错,无法访问
?>
6. 什么是构造函数和析构函数,作用是什么?
构造函数是__construct(),在对象实例化时自动调用,用于初始化对象的属性;析构函数是__destruct(),在对象被销毁时自动调用,用于释放资源、执行收尾操作。
<?php
class User {
public $name;
// 构造函数
public function __construct($name) {
$this->name = $name;
echo "对象初始化,name是{$this->name}";
}
// 析构函数
public function __destruct() {
echo "对象被销毁";
}
}
$user = new User("王五"); // 输出初始化信息
unset($user); // 输出销毁信息
?>
数据库交互类面试题
7. 如何用PHP连接MySQL数据库,写出基本流程?
使用mysqli扩展连接MySQL的基本流程:创建连接、判断连接是否成功、执行SQL、处理结果、关闭连接。也可以使用PDO扩展实现,PDO支持多种数据库,兼容性更好。
<?php
// mysqli连接示例
$host = "127.0.0.1";
$user = "root";
$pass = "123456";
$db = "test";
// 创建连接
$conn = new mysqli($host, $user, $pass, $db);
// 判断连接
if ($conn->connect_error) {
die("连接失败:" . $conn->connect_error);
}
echo "数据库连接成功";
// 关闭连接
$conn->close();
?>
8. 如何防止SQL注入,有哪些常用方法?
常用防止SQL注入的方法:使用预处理语句(mysqli的prepare或者PDO的prepare),对用户输入的内容进行转义(使用mysqli_real_escape_string()),使用ORM框架自带的安全机制,避免直接拼接SQL语句。
<?php
// 预处理防止注入示例
$conn = new mysqli("127.0.0.1", "root", "123456", "test");
$username = $_POST['username'];
$password = $_POST['password'];
// 准备预处理语句
$stmt = $conn->prepare("SELECT * FROM user WHERE username = ? AND password = ?");
// 绑定参数
$stmt->bind_param("ss", $username, $password);
// 执行查询
$stmt->execute();
$result = $stmt->get_result();
?>
其他高频面试题
9. PHP中include和require有什么区别?
include引入文件时,如果文件不存在会抛出警告,脚本继续执行;require引入文件时,如果文件不存在会抛出致命错误,脚本终止执行。通常核心文件用require,可选文件用include。
10. 如何获取客户端的IP地址?
可以通过$_SERVER['REMOTE_ADDR']获取直连客户端的IP,如果经过代理,可能需要获取$_SERVER['HTTP_X_FORWARDED_FOR']或者$_SERVER['HTTP_CLIENT_IP'],需要做合法性校验避免伪造。
代码示例:
<?php
function get_client_ip() {
$ip = "";
if (isset($_SERVER['HTTP_CLIENT_IP'])) {
$ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
$ip = $_SERVER['REMOTE_ADDR'];
}
return $ip;
}
echo get_client_ip();
?>
11. session和cookie有什么区别?
session存储在服务器端,安全性更高,存储容量大,默认生命周期是浏览器关闭前;cookie存储在客户端,安全性较低,存储容量小(一般4KB以内),可以设置过期时间。session通常依赖cookie传递session_id。
12. 写出遍历目录的所有文件的方法?
可以使用opendir()、readdir()、closedir()函数组合,或者使用glob()函数,也可以使用RecursiveDirectoryIterator迭代器实现。
<?php
// 使用glob遍历目录下所有php文件
$files = glob("./test_dir/*.php");
foreach ($files as $file) {
echo $file . "<br>";
}
?>
13. PHP中如何实现页面跳转?
可以使用header()函数发送Location头实现跳转,注意header()函数前不能有任何输出;也可以使用meta标签或者JavaScript实现跳转。
<?php
// header跳转,要确保在输出前调用
header("Location: https://ipipp.com");
exit; // 跳转后建议加exit终止后续代码执行
?>
14. 什么是魔术方法,列举至少三个常见的魔术方法?
魔术方法是PHP中特殊命名的方法,在满足特定条件时自动调用,命名规则是前后各两个下划线。常见的有__construct()(构造函数)、__destruct()(析构函数)、__get()(访问不存在或不可访问的属性时调用)、__set()(给不存在或不可访问的属性赋值时调用)。
15. 如何判断一个变量是否为空?
可以使用empty()函数,变量为0、空字符串、null、false、空数组、未定义的变量时empty()都返回true;使用is_null()判断变量是否为null;使用isset()判断变量是否已设置且不为null。
<?php $var1 = ""; $var2 = null; $var3 = 0; echo empty($var1) ? "为空" : "不为空"; // 输出:为空 echo is_null($var2) ? "是null" : "不是null"; // 输出:是null echo isset($var3) ? "已设置" : "未设置"; // 输出:已设置 ?>
16. PHP中如何上传文件,基本流程是什么?
上传文件流程:前端表单设置enctype为multipart/form-data,method为post;后端通过$_FILES超全局数组获取文件信息;判断文件大小、类型是否合法;使用move_uploaded_file()函数将临时文件移动到目标目录。
<?php
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$file = $_FILES['upload_file'];
// 判断是否有错误
if ($file['error'] == 0) {
$target_dir = "./uploads/";
$target_file = $target_dir . basename($file['name']);
// 移动文件
if (move_uploaded_file($file['tmp_name'], $target_file)) {
echo "文件上传成功";
} else {
echo "文件移动失败";
}
}
}
?>
17. 写出实现斐波那契数列的递归和非递归方法?
递归方法逻辑简单但性能差,非递归方法用循环实现性能更好。
<?php
// 递归实现斐波那契数列
function fib_recursive($n) {
if ($n <= 1) return $n;
return fib_recursive($n-1) + fib_recursive($n-2);
}
// 非递归实现
function fib_loop($n) {
if ($n <= 1) return $n;
$a = 0;
$b = 1;
for ($i=2; $i<=$n; $i++) {
$c = $a + $b;
$a = $b;
$b = $c;
}
return $b;
}
echo fib_recursive(10); // 输出55
echo fib_loop(10); // 输出55
?>
18. PHP中如何操作JSON数据?
使用json_encode()将数组或对象转为JSON字符串,使用json_decode()将JSON字符串转为数组或对象,第二个参数设为true时返回数组,默认返回对象。
<?php
$arr = ["name" => "赵六", "age" => 25];
$json_str = json_encode($arr); // 转为JSON字符串
echo $json_str; // 输出:{"name":"赵六","age":25}
$new_arr = json_decode($json_str, true); // 转为数组
print_r($new_arr);
?>
19. 什么是依赖注入,有什么好处?
依赖注入是将对象的依赖关系由外部传入,而不是在对象内部自行创建。好处是降低代码耦合度,提升代码的可测试性和可维护性,方便替换依赖的实现。
20. 如何优化PHP代码的性能?
常见优化方法:减少不必要的变量和函数调用;使用单引号代替双引号;循环前先计算循环次数,避免每次循环都计算;使用合适的数据结构;开启OPcache缓存编译后的脚本;避免重复连接数据库,使用连接池。
21. PHP中如何处理异常?
使用try-catch块捕获异常,try块中放可能抛出异常的代码,catch块中处理异常,也可以自定义异常类继承Exception类。使用throw关键字抛出异常。
<?php
class MyException extends Exception {}
try {
$num = 0;
if ($num == 0) {
throw new MyException("除数不能为0");
}
} catch (MyException $e) {
echo "捕获到异常:" . $e->getMessage();
}
?>
22. 写出获取当前时间戳的三种方法?
方法一:time()函数,返回当前时间的Unix时间戳;方法二:$_SERVER['REQUEST_TIME'],获取请求开始的时间戳;方法三:strtotime('now'),解析当前时间返回时间戳。
<?php
echo time() . "<br>";
echo $_SERVER['REQUEST_TIME'] . "<br>";
echo strtotime("now") . "<br>";
?>
23. PHP中如何发送邮件?
可以使用mail()函数发送邮件,但需要服务器配置邮件服务;更常用的是使用第三方库如PHPMailer,支持SMTP协议,配置简单,功能更完善。
24. 什么是命名空间,作用是什么?
命名空间是PHP用来解决同名类、函数、常量冲突问题的机制,通过namespace关键字定义,使用use关键字引入其他命名空间的内容,避免不同库之间的名称冲突,也方便代码的组织管理。
<?php
namespace AppUtils;
function test() {
echo "工具类的test函数";
}
namespace AppService;
function test() {
echo "服务类的test函数";
}
// 调用不同命名空间的函数
AppUtilstest();
AppServicetest();
?>