00-PHP基础知识

8 阅读7分钟

PHP 基础知识(面向对象)

这部分内容是理解 Hyperf 框架的基础,建议先掌握这些概念再学习框架

1. 面向对象基础

1.1 类和对象

定义类

<?php
class User
{
    // 属性(成员变量)
    public $name;
    public $email;
    private $password;  // 私有属性
    
    // 构造函数(创建对象时自动调用)
    public function __construct($name, $email, $password)
    {
        $this->name = $name;
        $this->email = $email;
        $this->password = password_hash($password, PASSWORD_DEFAULT);
    }
    
    // 方法(成员函数)
    public function login($inputPassword)
    {
        return password_verify($inputPassword, $this->password);
    }
    
    // 获取器(访问私有属性)
    public function getPassword()
    {
        return $this->password;
    }
    
    // 设置器(修改私有属性)
    public function setPassword($newPassword)
    {
        $this->password = password_hash($newPassword, PASSWORD_DEFAULT);
    }
}

// 创建对象
$user = new User('张三', 'zhang@example.com', '123456');

// 访问属性
echo $user->name;  // 张三

// 调用方法
if ($user->login('123456')) {
    echo '登录成功';
}

1.2 访问修饰符

PHP 有三种访问修饰符:

修饰符说明访问范围
public公有任何地方都可以访问
protected受保护类内部和子类可以访问
private私有只有类内部可以访问

示例

<?php
class User
{
    public $name;           // 任何地方都可以访问
    protected $email;       // 类内部和子类可以访问
    private $password;      // 只有类内部可以访问
    
    public function __construct($name, $email, $password)
    {
        $this->name = $name;
        $this->email = $email;
        $this->password = $password;
    }
    
    // public 方法:任何地方都可以调用
    public function getEmail()
    {
        return $this->email;
    }
    
    // protected 方法:子类可以调用
    protected function validateEmail()
    {
        return filter_var($this->email, FILTER_VALIDATE_EMAIL);
    }
    
    // private 方法:只有类内部可以调用
    private function hashPassword($password)
    {
        return password_hash($password, PASSWORD_DEFAULT);
    }
}

$user = new User('张三', 'zhang@example.com', '123456');

echo $user->name;         // ✅ 可以访问
echo $user->email;        // ❌ 错误:不能访问 protected 属性
echo $user->password;     // ❌ 错误:不能访问 private 属性
echo $user->getEmail();   // ✅ 通过 public 方法访问

1.3 静态属性和方法

静态成员属于类本身,而不是对象实例。

<?php
class Counter
{
    // 静态属性(所有实例共享)
    private static $count = 0;
    
    // 静态方法
    public static function increment()
    {
        self::$count++;  // 使用 self:: 访问静态成员
    }
    
    public static function getCount()
    {
        return self::$count;
    }
    
    // 实例方法
    public function instanceMethod()
    {
        self::$count++;  // 实例方法也可以访问静态成员
    }
}

// 调用静态方法(不需要创建对象)
Counter::increment();
Counter::increment();
echo Counter::getCount();  // 2

// 创建对象后也可以调用静态方法
$counter = new Counter();
$counter::increment();     // 3

静态方法的限制

  • ❌ 静态方法不能访问非静态属性(因为没有 $this
  • ✅ 静态方法可以访问静态属性
  • ✅ 非静态方法可以访问静态属性和非静态属性

2. 继承

2.1 基本继承

extends 关键字用于继承父类。

<?php
// 父类(基类)
class Animal
{
    protected $name;
    
    public function __construct($name)
    {
        $this->name = $name;
    }
    
    public function eat()
    {
        echo "{$this->name} 正在吃东西\n";
    }
    
    public function sleep()
    {
        echo "{$this->name} 正在睡觉\n";
    }
}

// 子类(派生类)
class Dog extends Animal
{
    // 子类特有的方法
    public function bark()
    {
        echo "{$this->name} 正在叫:汪汪汪\n";
    }
    
    // 重写父类方法
    public function eat()
    {
        echo "{$this->name} 正在吃狗粮\n";
    }
}

// 使用
$dog = new Dog('旺财');
$dog->eat();    // 旺财 正在吃狗粮(调用子类的方法)
$dog->sleep();  // 旺财 正在睡觉(调用父类的方法)
$dog->bark();   // 旺财 正在叫:汪汪汪(子类特有的方法)

2.2 parent 关键字

使用 parent:: 调用父类的方法。

<?php
class Animal
{
    protected $name;
    
    public function __construct($name)
    {
        $this->name = $name;
        echo "创建动物:{$name}\n";
    }
    
    public function eat()
    {
        echo "{$this->name} 正在吃东西\n";
    }
}

class Dog extends Animal
{
    private $breed;  // 品种
    
    public function __construct($name, $breed)
    {
        // 调用父类的构造函数
        parent::__construct($name);
        
        $this->breed = $breed;
        echo "品种:{$breed}\n";
    }
    
    public function eat()
    {
        // 先调用父类的方法
        parent::eat();
        
        // 再添加自己的逻辑
        echo "狗狗吃得真香\n";
    }
}

$dog = new Dog('旺财', '金毛');
// 输出:
// 创建动物:旺财
// 品种:金毛

$dog->eat();
// 输出:
// 旺财 正在吃东西
// 狗狗吃得真香

2.3 final 关键字

final 关键字防止类被继承或方法被重写。

<?php
// final 类:不能被继承
final class Math
{
    public static function add($a, $b)
    {
        return $a + $b;
    }
}

class MyMath extends Math  // ❌ 错误:不能继承 final{
}

// final 方法:不能被重写
class Animal
{
    // final 方法
    final public function breathe()
    {
        echo "呼吸\n";
    }
}

class Dog extends Animal
{
    // ❌ 错误:不能重写 final 方法
    public function breathe()
    {
        echo "狗在呼吸\n";
    }
}

3. 接口(Interface)

3.1 什么是接口?

接口定义了类必须实现的方法,但不包含具体实现。

<?php
// 定义接口
interface PaymentInterface
{
    // 接口中的方法都是 public 的
    public function pay(float $amount): bool;
    
    public function refund(float $amount): bool;
}

// 实现接口
class AlipayPayment implements PaymentInterface
{
    public function pay(float $amount): bool
    {
        echo "使用支付宝支付 {$amount} 元\n";
        return true;
    }
    
    public function refund(float $amount): bool
    {
        echo "支付宝退款 {$amount} 元\n";
        return true;
    }
}

class WechatPayment implements PaymentInterface
{
    public function pay(float $amount): bool
    {
        echo "使用微信支付 {$amount} 元\n";
        return true;
    }
    
    public function refund(float $amount): bool
    {
        echo "微信退款 {$amount} 元\n";
        return true;
    }
}

// 使用接口(多态)
function processPayment(PaymentInterface $payment, float $amount)
{
    $payment->pay($amount);
}

$alipay = new AlipayPayment();
$wechat = new WechatPayment();

processPayment($alipay, 100);  // 使用支付宝支付 100 元
processPayment($wechat, 200);  // 使用微信支付 200 元

3.2 接口的特点

  • ✅ 接口中的方法都是抽象的(没有实现)
  • ✅ 接口中的方法都是 public 的
  • ✅ 一个类可以实现多个接口
  • ✅ 接口可以继承其他接口
  • ❌ 接口不能包含属性(PHP 8.0 之前)

3.3 实现多个接口

<?php
interface Flyable
{
    public function fly(): void;
}

interface Swimmable
{
    public function swim(): void;
}

// 实现多个接口
class Duck implements Flyable, Swimmable
{
    public function fly(): void
    {
        echo "鸭子在飞\n";
    }
    
    public function swim(): void
    {
        echo "鸭子在游泳\n";
    }
}

$duck = new Duck();
$duck->fly();
$duck->swim();

3.4 接口继承

<?php
interface Animal
{
    public function eat(): void;
}

interface Mammal extends Animal
{
    public function giveBirth(): void;
}

// 实现 Mammal 接口时,必须实现 eat() 和 giveBirth()
class Dog implements Mammal
{
    public function eat(): void
    {
        echo "狗在吃东西\n";
    }
    
    public function giveBirth(): void
    {
        echo "狗在生小狗\n";
    }
}

4. 抽象类(Abstract Class)

4.1 什么是抽象类?

抽象类是介于普通类和接口之间的一种类,可以包含抽象方法(没有实现)和具体方法(有实现)。

<?php
// 抽象类
abstract class Shape
{
    protected $color;
    
    public function __construct($color)
    {
        $this->color = $color;
    }
    
    // 具体方法(有实现)
    public function getColor()
    {
        return $this->color;
    }
    
    // 抽象方法(没有实现,子类必须实现)
    abstract public function getArea(): float;
    
    abstract public function getPerimeter(): float;
}

// 继承抽象类
class Circle extends Shape
{
    private $radius;
    
    public function __construct($color, $radius)
    {
        parent::__construct($color);
        $this->radius = $radius;
    }
    
    // 实现抽象方法
    public function getArea(): float
    {
        return pi() * $this->radius * $this->radius;
    }
    
    public function getPerimeter(): float
    {
        return 2 * pi() * $this->radius;
    }
}

class Rectangle extends Shape
{
    private $width;
    private $height;
    
    public function __construct($color, $width, $height)
    {
        parent::__construct($color);
        $this->width = $width;
        $this->height = $height;
    }
    
    public function getArea(): float
    {
        return $this->width * $this->height;
    }
    
    public function getPerimeter(): float
    {
        return 2 * ($this->width + $this->height);
    }
}

// 使用
$circle = new Circle('红色', 5);
echo "圆形颜色:" . $circle->getColor() . "\n";
echo "圆形面积:" . $circle->getArea() . "\n";

$rect = new Rectangle('蓝色', 10, 20);
echo "矩形面积:" . $rect->getArea() . "\n";

4.2 抽象类 vs 接口

特性抽象类接口
方法实现可以有具体方法和抽象方法所有方法都是抽象的(PHP 8 前)
属性可以有属性不能有属性(PHP 8.0 前)
继承/实现一个类只能继承一个抽象类一个类可以实现多个接口
构造函数可以有构造函数不能有构造函数
访问修饰符可以是 public、protected只能是 public
用途代码复用定义规范

使用场景

  • 抽象类:有公共的属性和方法需要复用
  • 接口:定义规范,多个不同的类实现相同的接口

4.3 接口 + 抽象类组合使用

<?php
// 接口:定义规范
interface StorageInterface
{
    public function save(string $key, $value): bool;
    public function get(string $key);
    public function delete(string $key): bool;
}

// 抽象类:提供公共实现
abstract class AbstractStorage implements StorageInterface
{
    protected $prefix = '';
    
    // 公共方法
    protected function buildKey(string $key): string
    {
        return $this->prefix . $key;
    }
    
    // 抽象方法:子类必须实现
    abstract public function save(string $key, $value): bool;
    abstract public function get(string $key);
    abstract public function delete(string $key): bool;
}

// 具体实现:Redis 存储
class RedisStorage extends AbstractStorage
{
    private $redis;
    
    public function __construct()
    {
        $this->redis = new Redis();
        $this->redis->connect('127.0.0.1', 6379);
        $this->prefix = 'redis:';
    }
    
    public function save(string $key, $value): bool
    {
        $key = $this->buildKey($key);  // 使用父类的方法
        return $this->redis->set($key, serialize($value));
    }
    
    public function get(string $key)
    {
        $key = $this->buildKey($key);
        $value = $this->redis->get($key);
        return $value ? unserialize($value) : null;
    }
    
    public function delete(string $key): bool
    {
        $key = $this->buildKey($key);
        return $this->redis->del($key) > 0;
    }
}

// 具体实现:文件存储
class FileStorage extends AbstractStorage
{
    private $path;
    
    public function __construct($path)
    {
        $this->path = $path;
        $this->prefix = 'file:';
    }
    
    public function save(string $key, $value): bool
    {
        $key = $this->buildKey($key);
        $filename = $this->path . '/' . md5($key);
        return file_put_contents($filename, serialize($value)) !== false;
    }
    
    public function get(string $key)
    {
        $key = $this->buildKey($key);
        $filename = $this->path . '/' . md5($key);
        if (file_exists($filename)) {
            return unserialize(file_get_contents($filename));
        }
        return null;
    }
    
    public function delete(string $key): bool
    {
        $key = $this->buildKey($key);
        $filename = $this->path . '/' . md5($key);
        if (file_exists($filename)) {
            return unlink($filename);
        }
        return false;
    }
}

// 使用(多态)
function saveData(StorageInterface $storage, string $key, $value)
{
    $storage->save($key, $value);
}

$redisStorage = new RedisStorage();
$fileStorage = new FileStorage('/tmp/cache');

saveData($redisStorage, 'user:1', ['name' => '张三']);
saveData($fileStorage, 'user:2', ['name' => '李四']);

5. Trait(特性)

5.1 什么是 Trait?

Trait 是一种代码复用机制,可以在多个类中复用方法。

问题:PHP 只支持单继承,如果多个类需要相同的方法怎么办?

解决方案:使用 Trait

<?php
// 定义 Trait
trait Timestampable
{
    protected $createdAt;
    protected $updatedAt;
    
    public function setCreatedAt($time)
    {
        $this->createdAt = $time;
    }
    
    public function setUpdatedAt($time)
    {
        $this->updatedAt = $time;
    }
    
    public function getCreatedAt()
    {
        return $this->createdAt;
    }
}

trait Loggable
{
    public function log($message)
    {
        echo "[" . date('Y-m-d H:i:s') . "] {$message}\n";
    }
}

// 使用 Trait
class User
{
    use Timestampable, Loggable;  // 使用多个 Trait
    
    private $name;
    
    public function __construct($name)
    {
        $this->name = $name;
        $this->setCreatedAt(date('Y-m-d H:i:s'));
        $this->log("用户 {$name} 已创建");
    }
}

$user = new User('张三');
// 输出:[2025-10-23 12:00:00] 用户 张三 已创建

echo $user->getCreatedAt();  // 2025-10-23 12:00:00

5.2 Trait 冲突解决

当使用多个 Trait,且它们有同名方法时,需要解决冲突。

<?php
trait A
{
    public function sayHello()
    {
        echo "Hello from A\n";
    }
}

trait B
{
    public function sayHello()
    {
        echo "Hello from B\n";
    }
}

class MyClass
{
    use A, B {
        A::sayHello insteadof B;  // 使用 A 的方法,忽略 B 的
        B::sayHello as sayHelloB;  // 给 B 的方法起别名
    }
}

$obj = new MyClass();
$obj->sayHello();   // Hello from A
$obj->sayHelloB();  // Hello from B

6. 命名空间(Namespace)

6.1 什么是命名空间?

命名空间用于解决类名冲突问题,类似于文件系统的目录。

<?php
// 文件:App/Controller/UserController.php
namespace App\Controller;

class UserController
{
    public function index()
    {
        echo "用户控制器\n";
    }
}

// 文件:App/Service/UserService.php
namespace App\Service;

class UserService
{
    public function getUsers()
    {
        return ['张三', '李四'];
    }
}

// 文件:index.php
// 方式一:使用完整命名空间
$controller = new \App\Controller\UserController();

// 方式二:使用 use 导入
use App\Controller\UserController;
use App\Service\UserService;

$controller = new UserController();
$service = new UserService();

// 方式三:使用别名
use App\Controller\UserController as UC;
use App\Service\UserService as US;

$controller = new UC();
$service = new US();

6.2 子命名空间

<?php
namespace App\Controller\Admin;  // 子命名空间

class UserController
{
    // ...
}

// 使用
use App\Controller\Admin\UserController;

6.3 全局类的访问

<?php
namespace App\Service;

class UserService
{
    public function sendEmail()
    {
        // 访问全局类(PHP 内置类)需要加反斜杠
        $date = new \DateTime();  // ✅ 正确
        $date = new DateTime();   // ❌ 错误:会查找 App\Service\DateTime
    }
}

7. 类型声明(Type Hinting)

7.1 参数类型声明

<?php
class UserService
{
    // 类型声明:参数必须是指定类型
    public function createUser(
        string $name,       // 字符串
        int $age,           // 整数
        float $balance,     // 浮点数
        bool $isActive,     // 布尔值
        array $tags,        // 数组
        User $friend        // 对象
    ) {
        // ...
    }
}

// 调用
$service->createUser(
    '张三',
    25,
    100.50,
    true,
    ['tag1', 'tag2'],
    new User()
);

// ❌ 错误调用
$service->createUser('张三', '25', ...);  // 错误:age 必须是 int

7.2 返回值类型声明

<?php
class UserService
{
    // 声明返回值类型
    public function getUserById(int $id): ?User  // 返回 Usernull
    {
        return User::find($id);
    }
    
    public function getUserList(): array  // 返回数组
    {
        return User::all()->toArray();
    }
    
    public function isAdmin(int $userId): bool  // 返回布尔值
    {
        $user = User::find($userId);
        return $user && $user->role === 'admin';
    }
}

7.3 联合类型(PHP 8.0+)

<?php
class UserService
{
    // 参数可以是 int 或 string
    public function getUserById(int|string $id): User|null
    {
        return User::find($id);
    }
    
    // 返回 int 或 float 或 null
    public function calculate(): int|float|null
    {
        return 100;
    }
}

7.4 严格类型模式

<?php
declare(strict_types=1);  // 开启严格类型模式

function add(int $a, int $b): int
{
    return $a + $b;
}

add(1, 2);      // ✅ 正确
add(1.5, 2.5);  // ❌ 错误:严格模式下不会自动转换类型
add('1', '2');  // ❌ 错误:严格模式下不会自动转换类型

8. 魔术方法

8.1 常用魔术方法

<?php
class User
{
    private $data = [];
    
    // 构造函数:创建对象时调用
    public function __construct($name, $email)
    {
        $this->data['name'] = $name;
        $this->data['email'] = $email;
    }
    
    // 析构函数:对象销毁时调用
    public function __destruct()
    {
        echo "对象被销毁\n";
    }
    
    // 获取不存在的属性时调用
    public function __get($name)
    {
        return $this->data[$name] ?? null;
    }
    
    // 设置不存在的属性时调用
    public function __set($name, $value)
    {
        $this->data[$name] = $value;
    }
    
    // 检查属性是否存在
    public function __isset($name)
    {
        return isset($this->data[$name]);
    }
    
    // 删除属性
    public function __unset($name)
    {
        unset($this->data[$name]);
    }
    
    // 调用不存在的方法时调用
    public function __call($name, $arguments)
    {
        echo "调用方法:{$name}\n";
        echo "参数:" . json_encode($arguments) . "\n";
    }
    
    // 调用不存在的静态方法时调用
    public static function __callStatic($name, $arguments)
    {
        echo "调用静态方法:{$name}\n";
    }
    
    // 对象转字符串时调用
    public function __toString()
    {
        return "User: {$this->data['name']}";
    }
    
    // 对象被当作函数调用时
    public function __invoke($arg)
    {
        echo "对象被调用,参数:{$arg}\n";
    }
}

// 使用
$user = new User('张三', 'zhang@example.com');

echo $user->name;        // 张三(调用 __get)
$user->age = 25;         // 调用 __set
echo $user->age;         // 25(调用 __get)

echo isset($user->age);  // true(调用 __isset)
unset($user->age);       // 调用 __unset

$user->unknownMethod('arg1', 'arg2');  // 调用 __call
User::unknownStatic();                 // 调用 __callStatic

echo $user;              // User: 张三(调用 __toString)
$user('参数');            // 对象被调用,参数:参数(调用 __invoke)

8.2 __clone(克隆对象)

<?php
class User
{
    public $name;
    public $friend;  // 对象属性
    
    public function __construct($name)
    {
        $this->name = $name;
    }
    
    // 克隆对象时调用
    public function __clone()
    {
        // 深拷贝:同时克隆对象属性
        if ($this->friend) {
            $this->friend = clone $this->friend;
        }
        
        echo "对象被克隆\n";
    }
}

$user1 = new User('张三');
$user1->friend = new User('李四');

// 克隆对象
$user2 = clone $user1;

$user2->name = '王五';
$user2->friend->name = '赵六';

echo $user1->name;         // 张三(原对象未受影响)
echo $user1->friend->name; // 李四(深拷贝,原对象未受影响)
echo $user2->name;         // 王五
echo $user2->friend->name; // 赵六

9. 多态

9.1 什么是多态?

多态:同一个方法调用,不同的对象有不同的实现。

<?php
interface PaymentInterface
{
    public function pay(float $amount): bool;
}

class AlipayPayment implements PaymentInterface
{
    public function pay(float $amount): bool
    {
        echo "支付宝支付 {$amount} 元\n";
        return true;
    }
}

class WechatPayment implements PaymentInterface
{
    public function pay(float $amount): bool
    {
        echo "微信支付 {$amount} 元\n";
        return true;
    }
}

class CreditCardPayment implements PaymentInterface
{
    public function pay(float $amount): bool
    {
        echo "信用卡支付 {$amount} 元\n";
        return true;
    }
}

// 多态:同一个方法,不同的实现
class OrderService
{
    public function checkout(PaymentInterface $payment, float $amount)
    {
        // 不关心具体是哪种支付方式,只要实现了 PaymentInterface 即可
        if ($payment->pay($amount)) {
            echo "支付成功\n";
        }
    }
}

$orderService = new OrderService();

// 使用不同的支付方式
$orderService->checkout(new AlipayPayment(), 100);
$orderService->checkout(new WechatPayment(), 200);
$orderService->checkout(new CreditCardPayment(), 300);

9.2 多态的优势

  • 扩展性好:新增支付方式无需修改 OrderService
  • 灵活性高:可以动态选择支付方式
  • 易于测试:可以注入 Mock 对象

10. 依赖注入(重要!)

10.1 什么是依赖注入?

依赖注入:将类所依赖的对象从外部传入,而不是在类内部创建。

不使用依赖注入(高耦合):

<?php
class UserController
{
    private $userService;
    
    public function __construct()
    {
        // 在类内部创建依赖
        $this->userService = new UserService();
    }
    
    public function getUsers()
    {
        return $this->userService->getList();
    }
}

// 问题:
// 1. UserController 直接依赖 UserService 的具体实现
// 2. 无法替换为其他实现(如 MockUserService)
// 3. 难以进行单元测试

使用依赖注入(低耦合):

<?php
class UserController
{
    private $userService;
    
    // 从外部注入依赖
    public function __construct(UserServiceInterface $userService)
    {
        $this->userService = $userService;
    }
    
    public function getUsers()
    {
        return $this->userService->getList();
    }
}

// 使用
$userService = new UserService();
$controller = new UserController($userService);

// 或者用于测试
$mockService = new MockUserService();
$controller = new UserController($mockService);  // 可以轻松替换实现

10.2 依赖注入容器

手动注入的问题:如果依赖很多,创建对象会很麻烦。

<?php
// UserService 依赖 Database
$database = new Database();
$userService = new UserService($database);

// UserController 依赖 UserService 和 LogService
$logService = new LogService();
$controller = new UserController($userService, $logService);

// 依赖层级很深时,创建对象非常繁琐

DI 容器:自动创建和注入依赖。

<?php
// Hyperf 的 DI 容器会自动处理依赖关系
$container = \Hyperf\Context\ApplicationContext::getContainer();

// 自动创建 UserController 及其所有依赖
$controller = $container->get(UserController::class);

11. PHP 8 新特性

11.1 属性(Attributes)

PHP 8 引入了属性(Attributes),用于给类、方法、属性添加元数据。

<?php
use Attribute;

// 定义属性
#[Attribute(Attribute::TARGET_METHOD)]
class Route
{
    public function __construct(
        public string $path,
        public string $method = 'GET'
    ) {
    }
}

// 使用属性
class UserController
{
    #[Route(path: '/api/users', method: 'GET')]
    public function index()
    {
        return ['users' => []];
    }
    
    #[Route(path: '/api/users', method: 'POST')]
    public function create()
    {
        return ['id' => 1];
    }
}

// 读取属性(反射)
$reflection = new ReflectionClass(UserController::class);
$methods = $reflection->getMethods();

foreach ($methods as $method) {
    $attributes = $method->getAttributes(Route::class);
    
    foreach ($attributes as $attribute) {
        $route = $attribute->newInstance();
        echo "{$route->method} {$route->path}{$method->getName()}\n";
    }
}

// 输出:
// GET /api/users → index
// POST /api/users → create

11.2 构造器属性提升

<?php
// PHP 7
class User
{
    private $name;
    private $email;
    
    public function __construct($name, $email)
    {
        $this->name = $name;
        $this->email = $email;
    }
}

// PHP 8(更简洁)
class User
{
    public function __construct(
        private string $name,
        private string $email
    ) {
        // 自动创建属性并赋值
    }
}

11.3 命名参数

<?php
class User
{
    public function __construct(
        public string $name,
        public string $email,
        public int $age = 0,
        public bool $isActive = true
    ) {
    }
}

// 传统方式
$user = new User('张三', 'zhang@example.com', 25, true);

// PHP 8:命名参数(可以跳过默认参数)
$user = new User(
    name: '张三',
    email: 'zhang@example.com'
);

$user = new User(
    email: 'zhang@example.com',
    name: '张三',
    age: 25
);

12. 要点

必须掌握

  • 类和对象的概念
  • 访问修饰符(public、protected、private)
  • 继承和多态
  • 接口和抽象类的区别
  • 依赖注入的概念
  • 命名空间的使用

加分项

  • Trait 的使用场景
  • 魔术方法的应用
  • PHP 8 新特性(属性、联合类型)
  • 设计模式(工厂、单例、策略等)

高频题

1. 接口和抽象类有什么区别?

答:

  • 接口:定义规范,所有方法都是抽象的,一个类可以实现多个接口
  • 抽象类:可以有具体方法和抽象方法,一个类只能继承一个抽象类
  • 使用场景:接口定义规范,抽象类提供公共实现

2. 什么是依赖注入?

答:将类所依赖的对象从外部传入,而不是在类内部创建。

优势:

  • 降低耦合度
  • 便于测试
  • 便于替换实现

3. private、protected、public 有什么区别?

答:

  • public:任何地方都可以访问
  • protected:类内部和子类可以访问
  • private:只有类内部可以访问

4. Trait 有什么用?

答:Trait 是一种代码复用机制,可以在多个类中复用方法,解决 PHP 单继承的限制。


下一步:阅读 01-核心概念.md 开始学习 Hyperf