1 函数定义
基本函数与类型声明
PHP 支持标量类型声明(int、float、string、bool)以及返回值类型,类似 TypeScript / Python type hints。
function add(int $a, int $b): int
{
return $a + $b;
}
// 联合类型(PHP 8.0+)
function format(int|float $value): string
{
return number_format($value, 2);
}
// 交叉类型(PHP 8.1+)
function process(Countable&Iterator $collection): void
{
// $collection 必须同时实现 Countable 和 Iterator
}
// 返回 never 类型(PHP 8.1+)— 函数永不正常返回
function abort(string $msg): never
{
throw new RuntimeException($msg);
}
默认值与命名参数
function createUser(
string $name,
string $role = 'member', // 默认值
bool $active = true
): array {
return compact('name', 'role', 'active');
}
// 命名参数(PHP 8.0+)— 可跳过中间参数、顺序无关
$user = createUser(name: '张三', active: false);
// ['name' => '张三', 'role' => 'member', 'active' => false]
可变参数与引用传递
// 可变参数(variadic)
function sum(int ...$numbers): int
{
return array_sum($numbers);
}
echo sum(1, 2, 3, 4); // 10
// 展开操作符传参
$nums = [10, 20, 30];
echo sum(...$nums); // 60
// 引用传递 — 函数内修改会影响外部变量
function increment(int &$value): void
{
$value++;
}
$count = 5;
increment($count);
echo $count; // 6
⚠️ PHP 8.4:隐式可空类型已弃用
在 PHP 8.4 中,当参数有类型声明且默认值为 null 时,必须显式使用 ?Type 或联合类型 Type|null,否则会产生弃用警告。
// ❌ PHP 8.4 弃用 — 隐式可空
function find(string $key, array $default = null): mixed { ... }
// ✅ 正确写法 — 显式可空
function find(string $key, ?array $default = null): mixed { ... }
// 或者
function find(string $key, array|null $default = null): mixed { ... }
2 匿名函数与箭头函数
匿名函数(闭包)
PHP 的匿名函数需要通过 use 关键字显式捕获外部变量(默认按值捕获)。
$greeting = '你好';
$sayHello = function (string $name) use ($greeting): string {
return "$greeting, $name!";
};
echo $sayHello('世界'); // 你好, 世界!
// 按引用捕获 — 可修改外部变量
$counter = 0;
$inc = function () use (&$counter): void {
$counter++;
};
$inc();
$inc();
echo $counter; // 2
// 作为回调使用
$numbers = [3, 1, 4, 1, 5];
usort($numbers, function (int $a, int $b): int {
return $a - $b;
});
箭头函数(PHP 7.4+)
箭头函数是单表达式的简写闭包,自动按值捕获外部变量,无需 use。
$multiplier = 3;
// 箭头函数 — 自动捕获 $multiplier
$triple = fn(int $x): int => $x * $multiplier;
echo $triple(5); // 15
// 在数组操作中非常好用
$prices = [100, 200, 300];
$withTax = array_map(fn($p) => $p * 1.13, $prices);
// [113.0, 226.0, 339.0]
// 箭头函数可嵌套
$addThenMultiply = fn($x) => fn($y) => ($x + $y) * 2;
🔄 跨语言对比:匿名函数
PHP
// 匿名函数
$fn = function($x) use ($y) {
return $x + $y;
};
// 箭头函数
$fn = fn($x) => $x + $y;
JavaScript
// 箭头函数自动捕获
// const fn = (x) => x + y;
// 普通函数也自动捕获
// const fn = function(x) {
// return x + y;
// };
Python
// lambda 仅限单表达式
// fn = lambda x: x + y
// def fn(x):
// return x + y
关键差异:JS/Python 的闭包自动捕获外部变量;PHP 匿名函数必须用 use 显式声明,箭头函数则自动捕获(只读)。
3 命名空间
命名空间用于组织代码、避免类名冲突,类似 Java 的 package 或 Python 的模块系统。
声明与使用
// 文件: src/Models/User.php
namespace App\Models;
class User
{
public function __construct(
public readonly string $name,
public readonly string $email,
) {}
}
// 文件: src/Services/UserService.php
namespace App\Services;
use App\Models\User; // 导入类
use App\Models\{User, Product}; // 分组导入
use function App\Helpers\format; // 导入函数
use const App\Config\VERSION; // 导入常量
class UserService
{
public function create(string $name, string $email): User
{
return new User($name, $email);
}
}
PSR-4 自动加载
配合 Composer 的 PSR-4 规范,命名空间与目录结构一一对应,无需手动 require。
// composer.json
{
"autoload": {
"psr-4": {
"App\\": "src/"
}
}
}
📁 目录结构对应关系
project/
├── composer.json
├── vendor/ # Composer 自动生成
│ └── autoload.php
└── src/ # 对应 App\ 命名空间
├── Models/
│ ├── User.php # App\Models\User
│ └── Product.php # App\Models\Product
├── Services/
│ └── UserService.php # App\Services\UserService
└── Helpers/
└── functions.php
// 入口文件 index.php
require __DIR__ . '/vendor/autoload.php';
use App\Models\User;
use App\Services\UserService;
$service = new UserService();
$user = $service->create('张三', 'zhang@example.com');
💡 提示:运行 composer dump-autoload 生成/更新自动加载映射。在生产环境使用 composer dump-autoload --optimize 生成类映射以提升性能。
4 类与对象
基本类定义
class Product
{
// 属性声明
public string $name;
protected float $price;
private int $stock;
// 静态属性
private static int $instanceCount = 0;
public function __construct(string $name, float $price, int $stock = 0)
{
$this->name = $name;
$this->price = $price;
$this->stock = $stock;
self::$instanceCount++;
}
// 方法
public function getTotal(int $qty): float
{
return $this->price * $qty;
}
// 静态方法
public static function getInstanceCount(): int
{
return self::$instanceCount;
}
// 魔术方法
public function __toString(): string
{
return "{$this->name} (¥{$this->price})";
}
}
构造函数提升(PHP 8.0+)
构造函数参数前加可见性修饰符,自动声明并赋值属性——大幅减少样板代码。
// ❌ 传统写法 — 大量重复
class User
{
private string $name;
private string $email;
private string $role;
public function __construct(string $name, string $email, string $role = 'member')
{
$this->name = $name;
$this->email = $email;
$this->role = $role;
}
}
// ✅ 构造函数提升 — 简洁等价
class User
{
public function __construct(
private string $name,
private string $email,
private string $role = 'member',
) {}
// 自动生成 $this->name, $this->email, $this->role
}
只读属性(PHP 8.1+)与只读类(PHP 8.2+)
// 只读属性 — 初始化后不可修改
class Coordinate
{
public function __construct(
public readonly float $lat,
public readonly float $lng,
) {}
}
$point = new Coordinate(39.9042, 116.4074);
echo $point->lat; // 39.9042
// $point->lat = 0; // ❌ Error: 只读属性不可修改
// 只读类(PHP 8.2+)— 所有属性自动 readonly
readonly class Money
{
public function __construct(
public float $amount,
public string $currency,
) {}
}
💡 可见性总结:
- •
public— 任何地方可访问(默认) - •
protected— 仅当前类和子类可访问 - •
private— 仅当前类可访问 - • PHP 8.4 新增
public(set)非对称可见性:读和写可设置不同级别
5 继承与接口
抽象类与继承
PHP 是单继承语言(与 Java 相同),使用 extends 继承,abstract 定义抽象类。
abstract class Shape
{
public function __construct(
protected string $color = 'red',
) {}
// 抽象方法 — 子类必须实现
abstract public function area(): float;
// 普通方法 — 可被继承
public function describe(): string
{
return "一个 {$this->color} 的 " . static::class;
}
}
class Circle extends Shape
{
public function __construct(
private float $radius,
string $color = 'blue',
) {
parent::__construct($color);
}
public function area(): float
{
return M_PI * $this->radius ** 2;
}
}
class Rectangle extends Shape
{
public function __construct(
private float $width,
private float $height,
string $color = 'green',
) {
parent::__construct($color);
}
public function area(): float
{
return $this->width * $this->height;
}
}
接口
接口定义契约,一个类可以实现多个接口。
interface Printable
{
public function toString(): string;
}
interface JsonSerializable
{
public function toJson(): string;
}
// 实现多个接口
class Invoice implements Printable, \JsonSerializable
{
public function __construct(
private string $id,
private float $total,
) {}
public function toString(): string
{
return "Invoice #{$this->id}: ¥{$this->total}";
}
// \JsonSerializable 接口要求的方法
public function jsonSerialize(): mixed
{
return ['id' => $this->id, 'total' => $this->total];
}
public function toJson(): string
{
return json_encode($this->jsonSerialize());
}
}
实战:策略模式
interface PaymentGateway
{
public function charge(float $amount): bool;
public function getName(): string;
}
class AlipayGateway implements PaymentGateway
{
public function charge(float $amount): bool
{
echo "支付宝收款 ¥{$amount}\n";
return true;
}
public function getName(): string { return '支付宝'; }
}
class WechatGateway implements PaymentGateway
{
public function charge(float $amount): bool
{
echo "微信支付收款 ¥{$amount}\n";
return true;
}
public function getName(): string { return '微信支付'; }
}
// 使用接口作为类型约束
class OrderService
{
public function checkout(PaymentGateway $gateway, float $amount): void
{
if ($gateway->charge($amount)) {
echo "通过 {$gateway->getName()} 支付成功\n";
}
}
}
$service = new OrderService();
$service->checkout(new AlipayGateway(), 99.9);
$service->checkout(new WechatGateway(), 199.0);
6 Trait(特征)
Trait 是 PHP 的代码复用机制,解决单继承限制。类似 "复制粘贴" 方法到类中,可理解为可组合的代码片段。
基本用法
trait HasTimestamps
{
public ?string $createdAt = null;
public ?string $updatedAt = null;
public function setCreatedAt(): void
{
$this->createdAt = date('Y-m-d H:i:s');
}
public function setUpdatedAt(): void
{
$this->updatedAt = date('Y-m-d H:i:s');
}
}
trait SoftDeletes
{
public ?string $deletedAt = null;
public function softDelete(): void
{
$this->deletedAt = date('Y-m-d H:i:s');
}
public function isDeleted(): bool
{
return $this->deletedAt !== null;
}
}
// 在类中使用多个 Trait
class Article
{
use HasTimestamps, SoftDeletes;
public function __construct(
public string $title,
public string $content,
) {
$this->setCreatedAt();
}
}
$article = new Article('PHP 教程', '内容...');
echo $article->createdAt; // 2026-03-31 12:00:00
$article->softDelete();
echo $article->isDeleted(); // true
冲突解决
当多个 Trait 含有同名方法时,使用 insteadof 和 as 解决冲突。
trait Logger
{
public function log(string $msg): void
{
echo "[LOG] $msg\n";
}
}
trait Debugger
{
public function log(string $msg): void
{
echo "[DEBUG] $msg\n";
}
}
class App
{
use Logger, Debugger {
Logger::log insteadof Debugger; // 优先使用 Logger 的 log
Debugger::log as debugLog; // 将 Debugger 的 log 重命名为 debugLog
}
}
$app = new App();
$app->log('启动'); // [LOG] 启动
$app->debugLog('详情'); // [DEBUG] 详情
🔄 跨语言对比:代码复用机制
PHP Trait
trait Cacheable {
public function cache(): void { }
}
class User {
use Cacheable;
}
Python Mixin
// class CacheMixin:
// def cache(self): ...
//
// class User(CacheMixin, Base):
// pass
// (通过多继承实现)
Java default 方法
// interface Cacheable {
// default void cache() { }
// }
// class User implements Cacheable
// { }
核心区别:PHP Trait 不是类也不是接口,不能实例化,不参与类型体系(instanceof 不识别 Trait)。Python 用多继承 + MRO 解决,Java 用接口默认方法。
7 枚举 Enum PHP 8.1+
PHP 8.1 引入原生枚举,告别常量模拟。枚举是一等公民,支持方法、接口实现,是类型安全的利器。
纯枚举(Unit Enum)
enum Suit
{
case Hearts;
case Diamonds;
case Clubs;
case Spades;
}
$card = Suit::Hearts;
echo $card->name; // "Hearts"
// 枚举用于类型约束
function playCard(Suit $suit): void
{
echo "打出 {$suit->name}\n";
}
playCard(Suit::Spades);
// 枚举比较
var_dump(Suit::Hearts === Suit::Hearts); // true
var_dump(Suit::Hearts === Suit::Diamonds); // false
回退枚举(Backed Enum)
每个枚举成员关联一个 string 或 int 值,适合数据库存储和 API 序列化。
enum Status: string
{
case Draft = 'draft';
case Published = 'published';
case Archived = 'archived';
// 枚举可以包含方法
public function label(): string
{
return match($this) {
self::Draft => '草稿',
self::Published => '已发布',
self::Archived => '已归档',
};
}
public function color(): string
{
return match($this) {
self::Draft => 'gray',
self::Published => 'green',
self::Archived => 'red',
};
}
}
$status = Status::Published;
echo $status->value; // "published"
echo $status->name; // "Published"
echo $status->label(); // "已发布"
// 从值构造枚举
$fromDb = Status::from('draft'); // Status::Draft
$maybe = Status::tryFrom('unknown'); // null(不会抛异常)
// 获取所有枚举成员
$all = Status::cases();
// [Status::Draft, Status::Published, Status::Archived]
枚举实现接口
interface HasDescription
{
public function description(): string;
}
enum Permission: int implements HasDescription
{
case Read = 1;
case Write = 2;
case Execute = 4;
public function description(): string
{
return match($this) {
self::Read => '读取权限',
self::Write => '写入权限',
self::Execute => '执行权限',
};
}
// 利用位运算检查权限组合
public static function check(int $mask, self $perm): bool
{
return ($mask & $perm->value) !== 0;
}
}
$userPerms = Permission::Read->value | Permission::Write->value; // 3
echo Permission::check($userPerms, Permission::Read); // true
echo Permission::check($userPerms, Permission::Execute); // false
📌 枚举的限制
- • 枚举不能有构造函数(无状态)
- • 枚举不能被继承,也不能继承其他类
- • 枚举可以实现接口、使用 Trait(但 Trait 不能含属性)
- • 枚举成员是单例,不可
new、不可clone
8 本章要点
🎯 函数
- • 参数和返回值类型声明
- • 命名参数跳过默认值
- •
...$args可变参数 - •
&$var引用传递 - • PHP 8.4 隐式可空已弃用
⚡ 闭包
- • 匿名函数需
use捕获变量 - • 箭头函数
fn() =>自动捕获 - • 箭头函数仅限单表达式
- • 常用于
array_map等回调
📦 命名空间
- •
namespace+use组织代码 - • PSR-4:命名空间映射目录
- • Composer 自动加载
- •
composer dump-autoload
🏗️ 类与对象
- • 构造函数参数提升(8.0+)
- •
readonly属性(8.1+) - •
readonly class(8.2+) - • 三级可见性 + 非对称可见性(8.4)
🔗 继承与接口
- • 单继承
extends - • 多接口
implements - •
abstract抽象类 - • Trait 弥补多继承缺失
🏷️ 枚举
- • 纯枚举 vs 回退枚举
- •
from()/tryFrom()构造 - • 枚举可含方法、实现接口
- • 类型安全替代魔术常量
掌握了函数与 OOP,你已经可以编写结构化的 PHP 应用了!
下一章我们将学习 数据库操作,使用 PDO 连接 MySQL 实现 CRUD。