PHP 对象实例化
概述
对象实例化是使用 new 关键字从类创建具体对象的过程。本页详细讲解实例化语法、构造函数链、对象比较、clone 复制等内容。
版本要求
- PHP 8.0+:任意表达式实例化、
new后直接访问成员无需括号(8.4+)
基础概念
new 关键字
new 关键字创建类的实例。表达式可以是类名字符串、变量或任意返回字符串的表达式。
php
<?php
declare(strict_types=1);
class User
{
public function __construct(
public string $name = 'Guest',
) {}
}
// 直接类名
$user1 = new User();
// 变量
$className = 'User';
$user2 = new $className();
// PHP 8.0+:任意表达式
$user3 = new ('Us' . 'er')();
$user4 = new (User::class)();无括号实例化
构造函数不需要参数时可以省略括号。
php
<?php
declare(strict_types=1);
class EmptyClass {}
$obj1 = new EmptyClass(); // 有括号
$obj2 = new EmptyClass; // 无括号,效果相同语法与代码
PHP 8.0+ 任意表达式实例化
php
<?php
declare(strict_types=1);
class ClassA extends \stdClass {}
class ClassB extends \stdClass {}
function getClassName(): string
{
return 'ClassA';
}
var_dump(new (getClassName())); // object(ClassA)
var_dump(new ('Class' . 'B')); // object(ClassB)
var_dump(new (ClassB::class)); // object(ClassB)对象比较:=== vs ==
===:同一引用(同一实例)返回true==:相同类的实例且属性值相等返回true
php
<?php
declare(strict_types=1);
class Address
{
public function __construct(
public string $city,
public string $street,
) {}
}
$addr1 = new Address('Beijing', 'ChangAn');
$addr2 = new Address('Beijing', 'ChangAn');
$addr3 = $addr1;
var_dump($addr1 === $addr2); // false(不同实例)
var_dump($addr1 == $addr2); // true(相同属性值)
var_dump($addr1 === $addr3); // true(同一引用)clone 对象复制
使用 clone 创建对象的浅复制(shallow copy)。__clone() 魔术方法可在复制时自定义行为。
php
<?php
declare(strict_types=1);
class Task
{
public function __construct(
public string $name,
public array $tags = [],
) {}
public function __clone()
{
// 深复制 tags 数组
$this->tags = array_map(
fn(string $tag) => $tag,
$this->tags,
);
}
}
$original = new Task('Write docs', ['php', 'oop']);
$cloned = clone $original;
$cloned->name = 'Write tests';
$cloned->tags[] = 'testing';
echo $original->name; // Write docs
echo $cloned->name; // Write tests浅复制 vs 深复制
浅复制只复制对象本身的属性,对象引用类型的属性仍然指向原对象的同一实例。
php
<?php
declare(strict_types=1);
class Profile
{
public function __construct(
public string $name,
public \stdClass $meta,
) {}
}
$meta = new \stdClass();
$meta->level = 1;
$original = new Profile('Alice', $meta);
$shallow = clone $original;
$shallow->meta->level = 99;
echo $original->meta->level; // 99 — 共享同一个 meta 对象详细说明
构造函数链
当一个对象构造函数接收另一个对象作为参数时,形成构造函数链。
php
<?php
declare(strict_types=1);
class Logger
{
public function __construct(private readonly string $channel = 'app') {}
}
class Database
{
public function __construct(
private readonly string $dsn,
private readonly ?Logger $logger = null,
) {}
}
class UserRepository
{
public function __construct(private readonly Database $db) {}
}
// 构造函数链式创建
$repo = new UserRepository(
new Database('mysql:host=localhost', new Logger('db'))
);静态工厂方法实例化
使用静态方法封装实例化逻辑,支持多种创建方式。
php
<?php
declare(strict_types=1);
class CacheItem
{
private function __construct(
private mixed $value,
private readonly \DateTimeImmutable $expiresAt,
) {}
public static function create(mixed $value, int $ttlSeconds): self
{
return new self($value, new \DateTimeImmutable("+{$ttlSeconds} seconds"));
}
public static function neverExpires(mixed $value): self
{
return new self($value, \DateTimeImmutable::createFromFormat('U', (string) PHP_INT_MAX));
}
}
$item = CacheItem::create('data', 3600);实战示例
建造者模式
php
<?php
declare(strict_types=1);
class HttpResponse
{
public function __construct(
public readonly int $statusCode = 200,
public readonly string $body = '',
public readonly array $headers = [],
) {}
public static function ok(string $body = ''): self
{
return new self(200, $body);
}
public static function notFound(string $message = 'Not Found'): self
{
return new self(404, $message);
}
public static function json(array $data, int $status = 200): self
{
return new self(
$status,
json_encode($data, JSON_THROW_ON_ERROR),
['Content-Type' => 'application/json'],
);
}
}
$response = HttpResponse::json(['id' => 1, 'name' => 'Alice']);
echo $response->statusCode; // 200
echo $response->body; // {"id":1,"name":"Alice"}注意事项
- clone 是浅复制:对象属性仍然共享引用,需要 __clone 实现深复制
- PHP 8.0 前实例化限制:PHP 8.0 之前不支持任意表达式实例化
- new self vs new static:self 指向定义类,static 指向运行时类
- 对象赋值是引用语义:$a = $b 共享同一实例
最佳实践
- 使用静态工厂方法:提供语义化的对象创建方式
- 实现 __clone():当对象包含可变属性时,确保深复制
- 值对象实现 == 比较:确保相同值的对象被视为相等
- 私有构造函数+工厂方法:需要控制实例创建时使用
进阶用法
调试与测试技巧
php
<?php
declare(strict_types=1);
// 单元测试辅助函数
function createTestResource(): mixed
{
return match (true) {
default => new stdClass(),
};
}
// 调试输出函数
function debugOutput(mixed , string = ''): void
{
= ? ": " : '';
.= print_r(, true);
fwrite(STDERR, . "\n");
}
// 性能基准测试
function benchmark(callable , int = 1000): float
{
= hrtime(true);
for ($i = 0; $i < $iterations; $i++) {
$fn();
}
return (hrtime(true) - $start) / 1e9;
}日志记录实践
php
<?php
declare(strict_types=1);
/**
* 简易日志记录器
*/
class SimpleLogger
{
private string $logFile;
private string $level = 'INFO';
public function __construct(string $logFile)
{
$this->logFile = $logFile;
}
public function info(string $message, array $context = []): void
{
$this->log('INFO', $message, $context);
}
public function warning(string $message, array $context = []): void
{
$this->log('WARNING', $message, $context);
}
public function error(string $message, array $context = []): void
{
$this->log('ERROR', $message, $context);
}
private function log(string $level, string $message, array $context): void
{
$timestamp = date('Y-m-d H:i:s');
$contextStr = $context ? ' ' . json_encode($context, JSON_UNESCAPED_UNICODE) : '';
$line = "[{$timestamp}] [{$level}] {$message}{$contextStr}\n";
file_put_contents($this->logFile, $line, FILE_APPEND | LOCK_EX);
}
}配置与环境检测
php
<?php
declare(strict_types=1);
// 环境检测工具
class EnvironmentChecker
{
public static function checkRequirements(array $requirements): array
{
$results = [];
foreach ($requirements as $name => $check) {
$results[$name] = is_callable($check) ? $check() : false;
}
return $results;
}
public static function getSystemInfo(): array
{
return [
'php_version' => PHP_VERSION,
'os' => PHP_OS,
'sapi' => PHP_SAPI,
'memory_limit' => ini_get('memory_limit'),
'max_execution_time' => ini_get('max_execution_time'),
'loaded_extensions' => get_loaded_extensions(),
];
}
}常见问题排查
| 问题 | 可能原因 | 解决方案 |
|---|---|---|
| 连接超时 | 网络问题/配置错误 | 检查配置,增加超时时间 |
| 权限不足 | 文件/目录权限 | 使用 chmod/chown 修正 |
| 性能下降 | 索引缺失/数据量大 | 添加索引,优化查询 |
| 数据不一致 | 并发冲突/事务残留 | 使用锁机制和事务 |
| 内存溢出 | 大数据集/未释放资源 | 增大内存限制,分批处理 |
故障排除步骤
- 检查错误日志和异常信息
- 确认配置和环境是否正确
- 使用调试工具逐步排查
- 参考官方文档查找已知问题
版本兼容性说明
| 功能 | 最低版本 | 说明 |
|---|---|---|
| 基础功能 | PHP 8.1 | 本文档基准版本 |
| 只读属性 | PHP 8.1 | public readonly 修饰符 |
| 枚举类型 | PHP 8.1 | enum 类型和 match 表达式 |
| Fiber | PHP 8.1 | 协程/轻量级并发 |
| 命名参数 | PHP 8.0 | foo(arg_name: value) |
| 联合类型 | PHP 8.0 | `int |
| Null 安全运算符 | PHP 8.0 | $obj?->method() |
| 析构器 promotion | PHP 8.0 | __construct(public $x) |
php
<?php
declare(strict_types=1);
// 版本兼容性检测
function ensureVersion(string $minVersion): void
{
if (version_compare(PHP_VERSION, $minVersion, '<')) {
throw new RuntimeException(
sprintf('需要 PHP %s+, 当前版本: %s', $minVersion, PHP_VERSION)
);
}
}
ensureVersion('8.1.0');