farafiri/class-generator-for-php

用于创建和自动加载常见模式(如装饰者、空对象、组合、延迟加载、代理对象)的类的库

dev-master 2016-12-11 19:09 UTC

This package is not auto-updated.

Last update: 2024-09-22 04:28:14 UTC


README

用于创建和自动加载常见模式(如装饰者、空对象、组合、延迟加载、代理对象)的类的库。所有生成的类都可以进行缓存,因此不会对性能产生相关影响。

示例

假设你有一个以下实体类。请注意,为了可读性,该类不完整(没有属性声明等)

class Book implements PriceInterface {
    public function __construct($id) {
        $this->id = $id;
        $this->loadPropertiesFromDb($id);
    }

    /**
     * @return \Author
     */
    public function getAuthor() {
        return new Author($this->authorId);
    }

    /**
     * @return int
     */
    public function getPrice() {
        return $this->price;
    }

    /**
     * @return \Tag[]
     */
    public function getTags() {
        return array_map(function($id) {return new Tag($id);}, $this->tagsIds);
    }
}

装饰

class DiscountDecorator extends ClassGenerator\BaseDecorator {
    const CG_DECORATED = 'PriceInterface'; //by default you can decorate any class. This const will restrict to given interface or class
    protected $discount;

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

    public function getPrice() {
        return ceil($this->cgDecorated->getPrice() * $this->discount);
    }
}

$book = new DecorableBook($id);
$book->getPrice(); // 100
$book->cgDecorate(new DiscountDecorator(0.9));
$book->getPrice(); // 90

$book instanceof Book //return true

空对象

$book = new NullBook($id);
//null object gets expected result type from phpDoc and returns proper empty value
$book->getPrice(); // 0
$book->getTags(); // array()
$book->getAuthor(); // NullAuthor

延迟构造函数

$book = new LazyConstructorBook($id);
//no DB query performed yet
$book->getPrice();
//retrieved data from DB and proper price returned

延迟

$book = new LazyBook($id);
//OR
$book = new LazyBook::cgGet(function() { return new Book($id); });
//no DB query performed yet
$book->getPrice();
//retrieved data from DB and proper price returned

延迟与延迟构造函数的区别

$lazyConstructorBook = new LazyConstructorBook($id); //no DB query performed yet
$lazyBook = new LazyBook($id); //no DB query performed yet

$author1 = $lazyConstructorBook->getAuthor(); // 2 queries performed (book and author)
$author2 = $lazyBook->getAuthor(); // still no queries performed (LazyAuthor returned)
$author2->getFirstName(); //retrieve book and author data

组合

$book1 = new Book(1);
$book2 = new Book(2);

$composite = new CompositeBook(array($book1, $book2));

$composite->getAuthor(); //will return composite of book authors (new CompositeAuthor(array($book1->getAuthor(), $book2->getAuthor())))
$composite->getTags(); //will return all tags (array_merge($book1->getTags(), $book2->getTags()))
$composite->getPrice(); // will return first value which evaluate to true

我们可以通过添加 @composite 注解来自定义行为。例如:如果我们向 price 方法添加 @composite sum,则 $composite->getPrice() 将返回所有价格的总和

设置

首先,在您的 composer.json 中添加以下内容:"farafiri/class-generator-for-php": "dev-master"

然后在您的代码中调用 \ClassGenerator\Autoloader::register

\ClassGenerator\Autoloader::getInstance()->register();
//this is not a Singleton (you can create instance with new ..., also method setInstance is available)
//but i need instance getter and I don't want make this code DI container dependent

如果您使用的是 Symfony 2,请检查 Doctrine\README.md

此自动加载器不是独立的 - 它不会从您的 PHP 文件中加载任何类,您需要另一个加载器来完成此任务。它应注册为最后一个加载器 - 否则,它将创建新类而不是从您的项目文件中加载它。(例如:如果您有类 \Item 和 \NullItem,则在尝试使用 \NullItem 时,它将生成新类而不是加载您的实现)确保在开发模式下关闭缓存,在生产模式下打开缓存(在代码更改时清除缓存)。要打开缓存

\ClassGenerator\Autoloader::getInstance()->setCachePath($cacheDirectoryPath)->setEnabledCache(true);

即使缓存未启用,也最好设置 $cachePath - 创建的类将保存并从文件系统加载,而不是简单的代码 eval。感谢这一点,在出现错误时,错误消息将类似于 "Error in cacheFile.php on line X" 而不是 "Error in eval code" + 您的 IDE 应该在它们在文件中时识别这些类。