Skip to content

PHP 类与对象基本概念

概述

PHP 是一门支持面向对象编程(OOP)的多范式语言。从 PHP 5 开始,OOP 支持逐渐成熟;PHP 7/8 更是大幅增强了类型系统和面向对象特性。本页介绍类定义、实例化、属性与方法、$this 引用,以及对象与类之间的关系。

版本要求

本教程以 PHP 8.1+ 为基准,部分特性标注引入版本。

基础概念

什么是类

类(Class)是对象的蓝图或模板,定义了对象的属性(数据)和方法(行为)。类本身不是具体的数据,而是用来创建具体实例的抽象描述。

php
<?php
declare(strict_types=1);

class User
{
    // 属性(状态)
    public string $name;
    public int $age;

    // 方法(行为)
    public function greet(): string
    {
        return "Hello, my name is {$this->name}.";
    }
}
  • 类名必须以字母或下划线开头,正则表达式为 ^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*$
  • 自 PHP 8.4.0 起,弃用使用单个下划线 _ 作为类名。
  • 类名可以是任何非 PHP 保留字 的有效标签。

什么是对象

对象(Object)是类的具体实例。一个类可以创建多个对象,每个对象拥有独立的属性值,但共享类中定义的方法。

php
<?php
declare(strict_types=1);

class User
{
    public function __construct(
        public string $name,
        public int $age,
    ) {}
}

$alice = new User('Alice', 30);
$bob   = new User('Bob', 25);

// 两个独立的对象,各自拥有不同状态
echo $alice->name; // Alice
echo $bob->name;   // Bob

类与对象的关系

概念对象
本质模板/蓝图具体实例
内存存在于类定义区每个实例独立内存
数量通常只有一个定义可以创建任意数量
关键字classnew

语法与代码

使用 new 实例化对象

使用 new 关键字创建类的实例。如果构造函数不需要参数,可以省略括号(PHP 8.4.0 起,括号始终可选)。

php
<?php
declare(strict_types=1);

class SimpleClass
{
    public string $var = 'a default value';

    public function displayVar(): void
    {
        echo $this->var;
    }
}

// 标准实例化
$instance = new SimpleClass();

// 变量中存储类名来实例化
$className = 'SimpleClass';
$instance  = new $className();

// PHP 8.0+:任意表达式实例化
$instance = new ('Simple' . 'Class')();

$this 伪变量

在类的方法内部,$this 是一个指向当前对象实例的引用。通过 $this->property 访问属性,通过 $this->method() 调用方法。

php
<?php
declare(strict_types=1);

class Person
{
    public string $name;

    public function __construct(string $name)
    {
        $this->name = $name;
    }

    public function introduce(): string
    {
        // $this 引用当前对象实例
        return "I am {$this->name}.";
    }
}

$person = new Person('Alice');
echo $person->introduce(); // I am Alice.

注意

以静态方式调用非静态方法在 PHP 8.0+ 会抛出 Error。在 PHP 8 之前会产生废弃通知,$this 将被声明为未定义。

对象赋值与引用

将一个对象赋值给新变量时,新变量指向同一个对象实例(对象句柄拷贝),而非副本。使用 clone 关键字可以创建真正的副本。

php
<?php
declare(strict_types=1);

class SimpleClass
{
    public string $var = 'default';
}

$instance  = new SimpleClass();
$assigned  = $instance;       // 指向同一个对象
$reference = &$instance;      // 引用赋值

$instance->var = 'changed';
$instance = null;              // $instance 和 $reference 变为 null

var_dump($instance);   // null
var_dump($reference);   // null
var_dump($assigned);    // object(SimpleClass) { var => "changed" }

::class 常量

ClassName::class 在编译时解析为完全限定的类名(FQCN),即使类不存在也不会报错。

php
<?php
declare(strict_types=1);

namespace App\Models;

class User
{
}

// 编译时解析
echo User::class;               // App\Models\User

// PHP 8.0+:也可用于对象实例
$user = new User();
echo $user::class;              // App\Models\User

// 即使类不存在也能解析名称
echo Does\Not\Exist::class;    // Does\Not\Exist

Nullsafe 操作符

PHP 8.0+ 引入了 ?-> nullsafe 操作符,当对象引用为 null 时不抛出异常,而是返回 null 并跳过后续链式调用。

php
<?php
declare(strict_types=1);

class UserRepository
{
    public function findUser(int $id): ?User
    {
        return null; // 模拟未找到用户
    }
}

class User
{
    public ?string $name = null;
}

$repository = new UserRepository();

// nullsafe 操作符链式调用
$result = $repository?->findUser(1)?->name;
var_dump($result); // null

详细说明

属性与方法的命名空间

类的属性和方法存在于不同的"命名空间"中,允许同名。访问时根据上下文决定是读取属性还是调用方法。

php
<?php
declare(strict_types=1);

class Foo
{
    public string $bar = 'property';

    public function bar(): string
    {
        return 'method';
    }
}

$obj = new Foo();
echo $obj->bar;   // property(读取属性)
echo $obj->bar();  // method(调用方法)

TIP

如果类属性被赋值为匿名函数,需要用括号包裹才能调用:($obj->bar)()

只读类(PHP 8.2+)

使用 readonly 修饰整个类,自动为所有声明的属性添加 readonly 修饰符,并禁止动态属性。

php
<?php
declare(strict_types=1);

readonly class ReadOnlyUser
{
    public function __construct(
        public string $name,
        public int $age,
    ) {}
}

$user = new ReadOnlyUser('Alice', 30);
echo $user->name; // Alice

// Fatal error: Cannot modify readonly property
// $user->name = 'Bob';

实战示例

实体类设计

php
<?php
declare(strict_types=1);

class Product
{
    public function __construct(
        public readonly int $id,
        public string $name,
        public float $price,
        public readonly \DateTimeImmutable $createdAt,
    ) {}

    public function applyDiscount(float $percentage): void
    {
        if ($percentage < 0 || $percentage > 100) {
            throw new \InvalidArgumentException(
                'Discount must be between 0 and 100'
            );
        }
        $this->price *= (1 - $percentage / 100);
    }

    public function formattedPrice(): string
    {
        return sprintf('$%.2f', $this->price);
    }
}

$product = new Product(
    id: 1,
    name: 'Laptop',
    price: 999.99,
    createdAt: new \DateTimeImmutable(),
);

echo $product->formattedPrice(); // $999.99
$product->applyDiscount(10);
echo $product->formattedPrice(); // $899.99

注意事项

  1. 类名大小写不敏感new simpleclass()new SimpleClass() 等价,但建议始终使用首字母大写。
  2. 对象是引用语义:赋值不会复制对象,需要用 clone 创建副本。
  3. 避免动态属性:PHP 8.2+ 已弃用动态属性,应显式声明所有属性。
  4. 类型声明:PHP 7.4+ 支持属性类型声明,PHP 8.1+ 支持 readonly,建议总是使用。

最佳实践

  • 使用构造器属性提升(PHP 8.0+)减少样板代码
  • 为所有属性添加类型声明,在构造函数中完成初始化
  • 不可变数据使用 readonly,确保对象创建后状态一致
  • 使用 declare(strict_types=1) 强制严格类型模式
  • 类名使用大驼峰(PascalCase),方法名使用小驼峰(camelCase)

进阶用法

调试与测试技巧

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 修正
性能下降索引缺失/数据量大添加索引,优化查询
数据不一致并发冲突/事务残留使用锁机制和事务
内存溢出大数据集/未释放资源增大内存限制,分批处理

故障排除步骤

  1. 检查错误日志和异常信息
  2. 确认配置和环境是否正确
  3. 使用调试工具逐步排查
  4. 参考官方文档查找已知问题

版本兼容性说明

功能最低版本说明
基础功能PHP 8.1本文档基准版本
只读属性PHP 8.1public readonly 修饰符
枚举类型PHP 8.1enum 类型和 match 表达式
FiberPHP 8.1协程/轻量级并发
命名参数PHP 8.0foo(arg_name: value)
联合类型PHP 8.0`int
Null 安全运算符PHP 8.0$obj?->method()
析构器 promotionPHP 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');

参考链接