<返回目录     Powered by claud/xia兄

第11课: 面向对象编程

面向对象编程基础

面向对象编程(OOP)是一种编程范式,使用"对象"来组织代码。PHP完全支持OOP,包括类、继承、接口等特性。

定义类和对象

<?php
// 定义类
class User {
    // 属性(成员变量)
    public $name;
    public $email;
    private $password;
    protected $age;

    // 构造函数
    public function __construct($name, $email) {
        $this->name = $name;
        $this->email = $email;
    }

    // 方法(成员函数)
    public function sayHello() {
        return "你好,我是 {$this->name}";
    }

    // Getter方法
    public function getEmail() {
        return $this->email;
    }

    // Setter方法
    public function setPassword($password) {
        $this->password = password_hash($password, PASSWORD_DEFAULT);
    }
}

// 创建对象
$user = new User("张三", "zhang@example.com");
echo $user->name;           // 访问公共属性
echo $user->sayHello();     // 调用方法
$user->setPassword("123456"); // 设置密码
?>

访问修饰符

<?php
class Example {
    public $publicVar = "公共";      // 任何地方都可访问
    private $privateVar = "私有";    // 仅类内部可访问
    protected $protectedVar = "保护"; // 类和子类可访问

    public function publicMethod() {
        // 可以访问所有属性
        echo $this->publicVar;
        echo $this->privateVar;
        echo $this->protectedVar;
    }

    private function privateMethod() {
        echo "私有方法";
    }

    protected function protectedMethod() {
        echo "保护方法";
    }
}

$obj = new Example();
echo $obj->publicVar;        // 正常
// echo $obj->privateVar;    // 错误:无法访问
$obj->publicMethod();        // 正常
// $obj->privateMethod();    // 错误:无法访问
?>

构造函数和析构函数

<?php
class Database {
    private $connection;

    // 构造函数:创建对象时自动调用
    public function __construct($host, $user, $pass, $db) {
        $this->connection = new mysqli($host, $user, $pass, $db);
        echo "数据库连接已建立\n";
    }

    // 析构函数:对象销毁时自动调用
    public function __destruct() {
        if ($this->connection) {
            $this->connection->close();
            echo "数据库连接已关闭\n";
        }
    }

    public function query($sql) {
        return $this->connection->query($sql);
    }
}

$db = new Database("localhost", "user", "pass", "mydb");
// 使用数据库...
// 脚本结束时自动调用析构函数
?>

继承

<?php
// 父类(基类)
class Animal {
    protected $name;
    protected $age;

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

    public function eat() {
        echo "{$this->name} 正在吃东西\n";
    }

    public function sleep() {
        echo "{$this->name} 正在睡觉\n";
    }
}

// 子类(派生类)
class Dog extends Animal {
    private $breed;

    public function __construct($name, $age, $breed) {
        parent::__construct($name, $age);  // 调用父类构造函数
        $this->breed = $breed;
    }

    // 新增方法
    public function bark() {
        echo "{$this->name} 汪汪叫\n";
    }

    // 重写父类方法
    public function eat() {
        echo "{$this->name} 正在吃狗粮\n";
    }
}

$dog = new Dog("旺财", 3, "金毛");
$dog->eat();    // 调用重写的方法
$dog->bark();   // 调用新方法
$dog->sleep();  // 调用继承的方法
?>

抽象类

<?php
// 抽象类不能被实例化
abstract class Shape {
    protected $color;

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

    // 抽象方法:子类必须实现
    abstract public function calculateArea();
    abstract public function calculatePerimeter();

    // 普通方法:子类可以继承
    public function getColor() {
        return $this->color;
    }
}

class Circle extends Shape {
    private $radius;

    public function __construct($color, $radius) {
        parent::__construct($color);
        $this->radius = $radius;
    }

    public function calculateArea() {
        return pi() * $this->radius ** 2;
    }

    public function calculatePerimeter() {
        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 calculateArea() {
        return $this->width * $this->height;
    }

    public function calculatePerimeter() {
        return 2 * ($this->width + $this->height);
    }
}

$circle = new Circle("红色", 5);
echo "圆形面积: " . $circle->calculateArea();

$rect = new Rectangle("蓝色", 4, 6);
echo "矩形面积: " . $rect->calculateArea();
?>

接口

<?php
// 接口定义契约
interface Drawable {
    public function draw();
}

interface Resizable {
    public function resize($scale);
}

// 类可以实现多个接口
class Image implements Drawable, Resizable {
    private $path;
    private $width;
    private $height;

    public function __construct($path, $width, $height) {
        $this->path = $path;
        $this->width = $width;
        $this->height = $height;
    }

    public function draw() {
        echo "绘制图片: {$this->path}\n";
    }

    public function resize($scale) {
        $this->width *= $scale;
        $this->height *= $scale;
        echo "调整大小为: {$this->width}x{$this->height}\n";
    }
}

$img = new Image("photo.jpg", 800, 600);
$img->draw();
$img->resize(0.5);
?>

静态属性和方法

<?php
class Math {
    // 静态属性
    public static $pi = 3.14159;
    private static $count = 0;

    // 静态方法
    public static function square($n) {
        return $n * $n;
    }

    public static function cube($n) {
        return $n * $n * $n;
    }

    public static function incrementCount() {
        self::$count++;
    }

    public static function getCount() {
        return self::$count;
    }
}

// 访问静态成员(不需要创建对象)
echo Math::$pi;
echo Math::square(5);
Math::incrementCount();
echo Math::getCount();

// 也可以通过对象访问
$math = new Math();
echo $math::square(3);
?>

常量

<?php
class Config {
    // 类常量
    const VERSION = "1.0.0";
    const MAX_SIZE = 1024;
    public const DEBUG = true;      // PHP 7.1+
    private const SECRET = "key";   // PHP 7.1+

    public static function getVersion() {
        return self::VERSION;
    }
}

// 访问公共常量
echo Config::VERSION;
echo Config::MAX_SIZE;

// 通过类访问
echo Config::getVersion();
?>

魔术方法

<?php
class MagicExample {
    private $data = [];

    // __get: 访问不存在的属性时调用
    public function __get($name) {
        echo "获取属性: $name\n";
        return $this->data[$name] ?? null;
    }

    // __set: 设置不存在的属性时调用
    public function __set($name, $value) {
        echo "设置属性: $name = $value\n";
        $this->data[$name] = $value;
    }

    // __isset: 检查不存在的属性时调用
    public function __isset($name) {
        return isset($this->data[$name]);
    }

    // __unset: 删除不存在的属性时调用
    public function __unset($name) {
        unset($this->data[$name]);
    }

    // __call: 调用不存在的方法时调用
    public function __call($name, $arguments) {
        echo "调用方法: $name\n";
        echo "参数: " . implode(", ", $arguments) . "\n";
    }

    // __toString: 对象转字符串时调用
    public function __toString() {
        return "MagicExample对象";
    }

    // __invoke: 对象当作函数调用时
    public function __invoke($x) {
        echo "对象被调用,参数: $x\n";
    }
}

$obj = new MagicExample();
$obj->name = "张三";     // 触发__set
echo $obj->name;         // 触发__get
echo $obj;               // 触发__toString
$obj(100);               // 触发__invoke
?>

命名空间

<?php
// 定义命名空间
namespace App\Models;

class User {
    public $name;
}

namespace App\Controllers;

class UserController {
    public function index() {
        // 使用完全限定名称
        $user = new \App\Models\User();

        // 或使用use导入
        // use App\Models\User;
        // $user = new User();
    }
}

// 使用命名空间
namespace App;

use App\Models\User;
use App\Controllers\UserController as Controller;

$user = new User();
$controller = new Controller();
?>

Trait(特性)

<?php
// Trait用于代码复用
trait Timestampable {
    private $createdAt;
    private $updatedAt;

    public function setCreatedAt() {
        $this->createdAt = date('Y-m-d H:i:s');
    }

    public function setUpdatedAt() {
        $this->updatedAt = date('Y-m-d H:i:s');
    }

    public function getCreatedAt() {
        return $this->createdAt;
    }
}

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

// 使用多个Trait
class Article {
    use Timestampable, Loggable;

    private $title;
    private $content;

    public function __construct($title, $content) {
        $this->title = $title;
        $this->content = $content;
        $this->setCreatedAt();
        $this->log("文章创建: $title");
    }
}

$article = new Article("PHP教程", "这是内容");
echo $article->getCreatedAt();
?>

类型声明(PHP 7+)

<?php
class Calculator {
    // 参数类型声明和返回类型声明
    public function add(int $a, int $b): int {
        return $a + $b;
    }

    public function divide(float $a, float $b): float {
        if ($b == 0) {
            throw new Exception("除数不能为0");
        }
        return $a / $b;
    }

    // 可空类型(PHP 7.1+)
    public function greet(?string $name): string {
        return $name ? "Hello, $name" : "Hello, Guest";
    }

    // void返回类型(PHP 7.1+)
    public function log(string $message): void {
        echo $message . "\n";
    }
}

$calc = new Calculator();
echo $calc->add(5, 3);        // 8
echo $calc->divide(10, 2);    // 5.0
echo $calc->greet("张三");    // Hello, 张三
$calc->log("日志信息");
?>

实际应用示例

<?php
// 用户管理系统
class User {
    private $id;
    private $username;
    private $email;
    private $password;

    public function __construct($username, $email) {
        $this->username = $username;
        $this->email = $email;
    }

    public function setPassword($password) {
        $this->password = password_hash($password, PASSWORD_DEFAULT);
    }

    public function verifyPassword($password) {
        return password_verify($password, $this->password);
    }

    public function getUsername() {
        return $this->username;
    }

    public function getEmail() {
        return $this->email;
    }
}

class UserRepository {
    private $db;

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

    public function save(User $user) {
        // 保存用户到数据库
        $stmt = $this->db->prepare(
            "INSERT INTO users (username, email) VALUES (?, ?)"
        );
        $stmt->execute([$user->getUsername(), $user->getEmail()]);
    }

    public function findByUsername($username) {
        $stmt = $this->db->prepare(
            "SELECT * FROM users WHERE username = ?"
        );
        $stmt->execute([$username]);
        return $stmt->fetch();
    }
}

// 使用
$user = new User("zhangsan", "zhang@example.com");
$user->setPassword("123456");

$repo = new UserRepository($db);
$repo->save($user);
?>

设计模式

设计模式是解决软件设计中常见问题的可重用方案。以下是PHP中常用的设计模式:

单例模式

<?php
// 单例模式确保一个类只有一个实例
class Database {
    private static $instance = null;
    private $connection;
    
    // 私有构造函数防止外部实例化
    private function __construct() {
        $this->connection = new mysqli('localhost', 'user', 'pass', 'db');
    }
    
    // 私有克隆方法防止克隆
    private function __clone() {}
    
    // 静态方法获取实例
    public static function getInstance() {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    
    public function getConnection() {
        return $this->connection;
    }
}

// 使用
$db = Database::getInstance();
$connection = $db->getConnection();
?>

工厂模式

<?php
// 工厂模式用于创建对象,隐藏创建逻辑
interface Logger {
    public function log($message);
}

class FileLogger implements Logger {
    public function log($message) {
        file_put_contents('log.txt', "[File] $message\n", FILE_APPEND);
    }
}

class DatabaseLogger implements Logger {
    public function log($message) {
        // 写入数据库
        echo "[Database] $message\n";
    }
}

class LoggerFactory {
    public static function getLogger($type): Logger {
        switch ($type) {
            case 'file':
                return new FileLogger();
            case 'database':
                return new DatabaseLogger();
            default:
                throw new Exception("Unknown logger type: $type");
        }
    }
}

// 使用
$logger = LoggerFactory::getLogger('file');
$logger->log('Application started');
?>

依赖注入模式

<?php
// 依赖注入提高代码的可测试性和可维护性
class UserService {
    private $userRepository;
    private $logger;
    
    // 通过构造函数注入依赖
    public function __construct(UserRepository $userRepository, Logger $logger) {
        $this->userRepository = $userRepository;
        $this->logger = $logger;
    }
    
    public function createUser($username, $email) {
        $user = new User($username, $email);
        $this->userRepository->save($user);
        $this->logger->log("User created: $username");
        return $user;
    }
}

// 使用
$logger = LoggerFactory::getLogger('file');
$userRepository = new UserRepository($db);
$userService = new UserService($userRepository, $logger);
$userService->createUser('zhangsan', 'zhang@example.com');
?>

观察者模式

<?php
// 观察者模式实现对象间的一对多依赖
interface Observer {
    public function update($subject);
}

class Subject {
    private $observers = [];
    
    public function attach(Observer $observer) {
        $this->observers[] = $observer;
    }
    
    public function detach(Observer $observer) {
        $this->observers = array_filter($this->observers, function($o) use ($observer) {
            return $o !== $observer;
        });
    }
    
    public function notify() {
        foreach ($this->observers as $observer) {
            $observer->update($this);
        }
    }
}

class UserSubject extends Subject {
    public $user;
    
    public function createUser($user) {
        $this->user = $user;
        $this->notify();
    }
}

class EmailObserver implements Observer {
    public function update($subject) {
        echo "发送邮件给: {$subject->user->getEmail()}\n";
    }
}

class LogObserver implements Observer {
    public function update($subject) {
        echo "记录用户创建: {$subject->user->getUsername()}\n";
    }
}

// 使用
$userSubject = new UserSubject();
$userSubject->attach(new EmailObserver());
$userSubject->attach(new LogObserver());

$user = new User('lisi', 'li@example.com');
$userSubject->createUser($user);
?>

OOP性能优化

面向对象编程性能优化技巧:

安全编程实践

OOP安全最佳实践:

安全的密码处理

<?php
class User {
    private $passwordHash;
    
    public function setPassword($password) {
        // 验证密码强度
        if (strlen($password) < 8) {
            throw new Exception('密码长度至少8位');
        }
        
        // 使用bcrypt加密
        $this->passwordHash = password_hash($password, PASSWORD_DEFAULT);
    }
    
    public function verifyPassword($password) {
        return password_verify($password, $this->passwordHash);
    }
}

// 使用
$user = new User();
$user->setPassword('MySecurePassword123!');
if ($user->verifyPassword('MySecurePassword123!')) {
    echo '密码正确';
}
?>

防止SQL注入

<?php
class UserRepository {
    private $db;
    
    public function __construct($db) {
        $this->db = $db;
    }
    
    // 使用参数化查询防止SQL注入
    public function findByUsername($username) {
        $stmt = $this->db->prepare(
            "SELECT * FROM users WHERE username = ?"
        );
        $stmt->execute([$username]);
        return $stmt->fetch();
    }
    
    // 批量插入时也使用参数化查询
    public function batchInsert($users) {
        $stmt = $this->db->prepare(
            "INSERT INTO users (username, email) VALUES (?, ?)"
        );
        
        foreach ($users as $user) {
            $stmt->execute([$user->getUsername(), $user->getEmail()]);
        }
    }
}
?>
OOP最佳实践:

实践练习

  1. 创建类:设计一个Book类,包含标题、作者、价格等属性
  2. 继承练习:创建Vehicle父类和Car、Bike子类
  3. 接口实现:定义Payable接口,实现不同的支付方式
  4. 抽象类:创建抽象类Employee,派生Manager和Developer
  5. 静态方法:创建工具类,包含常用的静态方法
  6. 魔术方法:实现一个配置类,使用魔术方法访问配置项
  7. Trait使用:创建可复用的Trait,如Sortable、Searchable
  8. 完整系统:设计一个简单的博客系统(Post、Comment、User类)