面试题 / PHP

PHP类型、数组与语言机制

PHP 的数组和 C 语言的数组在结构上有什么区别?

核心区别是:

  • C 数组是连续内存,偏定长、偏底层。
  • PHP 数组本质更接近“有序 HashTable”,同时支持索引数组和关联数组。

因此 PHP 数组:

  • 可以混合字符串键和整数键。
  • 插入删除更灵活。
  • 内存开销通常更大。

$a += $b 对数组做了什么?

在 PHP 里,数组的 + 不是“追加”,而是“联合(union)”。

规则是:

  • 以左边数组为主。
  • 右边数组中键不存在的元素才会补进来。
  • 如果键已存在,保留左边,不覆盖。

foreach 引用遍历有哪些坑?

经典坑点是:

$a = [1, 2, 3];
foreach ($a as &$v) {}
foreach ($a as $v) {}

第一轮结束后,$v 仍然引用着数组最后一个元素。
如果第二轮前不 unset($v),后续赋值可能会意外改掉数组最后一个值。

PHP 的弱类型变量是怎么实现的?

PHP 变量底层可以理解为一个包含“类型信息 + 值 + 运行时状态”的结构,也就是常说的 zval 思想。

因此 PHP 能在运行时进行类型转换,比如:

  • 字符串转数字
  • 布尔值参与比较
  • == 下发生隐式转换

PHP 的内存管理机制与垃圾回收机制是什么?

PHP 的内存管理可以粗略理解为:预先申请空间存储变量,不够时继续申请新的空间。

垃圾回收方面:

  • 早期主要依赖引用计数。
  • 后续引入了对循环引用更友好的回收机制。

PHP 5.3 之后:

  1. refcount 归零可直接回收。
  2. 疑似垃圾对象会放入缓冲区。
  3. 达到阈值后统一扫描并回收。

PHP 7 的性能为什么提升明显?

核心原因不是某一个单点,而是底层整体优化:

  • zval 和变量存储结构更紧凑。
  • HashTable 做了优化。
  • 函数调用、对象处理、符号表等运行时路径更高效。
  • 减少了不必要的内存分配和复制。

rand()mt_rand() 有什么区别?

  • rand() 是较早的随机函数。
  • mt_rand() 基于 Mersenne Twister 算法,通常速度和随机性更好。

一般业务随机数需求,通常优先 mt_rand();安全场景则更推荐 random_int()

PECLPEAR 有什么区别?

  • PEAR 更偏纯 PHP 代码的扩展、类库和应用。
  • PECL 更偏底层扩展,很多是用 C 语言实现的。

可以简单理解为:

  • PEAR 偏上层复用
  • PECL 偏底层能力扩展

Trait 的优先级是什么?

优先级顺序通常是:

  1. 当前类中的方法
  2. Trait 中的方法
  3. 父类中的方法

也就是:

  • 类自身定义的方法会覆盖 Trait。
  • Trait 会覆盖父类方法。

selfstatic 的区别是什么?

  • self:在定义时绑定,指向定义该方法的类。
  • static:在运行时绑定,支持后期静态绑定(Late Static Binding)。

最关键的一句是:

  • static 支持后期静态绑定
  • self 不支持

如何实现一个支持回调的 PHP 函数?

支持回调的常见函数有:

  • array_map()
  • array_filter()
  • usort()
  • call_user_func()

自己实现支持回调,本质上就是把函数作为参数传入再内部调用:

function runCallback($value, callable $callback) {
    return $callback($value);
}

来源引用