deefour/presenter

PHP 对象的 Presenters/Decorators

3.0.1 2017-11-07 15:03 UTC

README

Build Status Total Downloads Latest Stable Version License

面向对象的展示逻辑。

入门

运行以下命令将 Presenter 添加到项目的 composer.json 中。有关特定版本,请参阅 Packagist

composer require deefour/presenter

需要 >=PHP5.5.0

解析器

Deefour\Presenter\Resolver 决定与对象关联的展示类类的完全限定名 (FQN)。解析器的默认行为是在 Article FQN 后追加 'Presenter'

use Deefour\Presenter\Resolver;

(new Resolver)->presenter(new Article); //=> 'ArticlePresenter'

可以通过向解析器传递一个可调用来自定义此行为。

use Deefour\Presenter\Resolver;

$resolver = new Resolver;

$resolver->resolveWith(function ($instance) {
  return "App\Presenters\" . get_class($instance) . 'Presenter';
});

$resolver->presenter(new Article); //=> 'App\Presenters\ArticlePresenter'

解析器将在对象上查找 modelClass() 方法。如果找到,将使用返回的 FQN 而不是对象本身。

class BlogPost
{
  static public function modelClass()
  {
      return Article::class;
  }
}

(new Resolver)->presenter(new BlogPost); //=> 'ArticlePresenter'

实例化

实例化展示类实例是您的责任。

use Deefour\Presenter\Resolver;

$article       = new Article;
$presenterName = (new Resolver)->presenter($article);
$presenter     = new $presenterName($article);
use Deefour\Presenter\Resolver;

(new Resolver)->presenter(new Article); //=> 'BlogPresenter'

如果从解析器返回的 FQN 与现有的有效类名不匹配,将返回 null 或抛出 NotDefinedException

use Deefour\Presenter\Resolver;

(new Resolver)->presenter(new ObjectWithoutPresenter); //=> null
(new Resolver)->presenterOrFail(new ObjectWithoutPresenter); //=> throws NotDefinedException

展示者

展示者本身扩展 Deefour\Presenter\Presenter

use Deefour\Presenter\Presenter;

class ArticlePresenter extends Presenter
{
    public function isDraft()
    {
        return $this->_model->isDraft() ? 'Yes' : 'No';
    }
}

API

API 快速概述。

use Deefour\Producer\Factory;

$presenter = (new Factory)->make(new Article, 'presenter'); //=> ArticlePolicy

$presenter->_model; //=> Article

$presenter->_model->isDraft(); //=> false
$presenter->isDraft(); //=> 'No'
$presenter->is_draft; //=> 'No'

$presenter->_model()->published; //=> true
$presenter->published; //=> true

一些需要注意的事项

  • 可以通过 $_model 属性或 model() 方法访问被展示者装饰的底层对象。
  • 底层对象上公开的任何属性或方法也可以通过展示者直接访问。
  • 展示者或底层模型上的任何公开的、驼峰式的公共方法都可以通过蛇形属性访问来访问。

自动展示者解析

当通过展示者的 __get()__call() 方法解析属性或方法时,将尝试解析并将返回值包装在展示者中。

namespace App;

use Illuminate\Support\Collection;

class Article
{
    public function category()
    {
        return new Category;
    }

    public function tags()
    {
        $collection = new Collection;

        $collection->push(new Tag);
        $collection->push(new Tag);
        $collection->push(new Tag);

        return $collection;
    }
}

给定存在 ArticlePresenterCategoryPresenterTagPresenter,将返回以下内容

use Deefour\Presenter\Resolver;

$presenter = (new Resolver)->presenter(new Article); //=> ArticlePresenter

(new $presenter)->category;      //=> CategoryPresenter
(new $presenter)->tags->first(); //=> TagPresenter

注意: 集合解析通过查找 IteratorAggregate 的实例来工作。迭代器用于遍历集合并为每个项目生成展示者。然后尝试实例化一个实现 IteratorAggregate 的原始对象的新的实例。这是返回值。

如果您想访问原始关联,只需从底层对象请求它。

$presenter->_model->tags()->first(); //=> Tag

贡献

变更日志

3.0.1 - 2017年11月7日

  • 在检查是否存在底层模型上的方法之前,先检查它是否是一个属性。修复了与 Laravel 的 __isset() 实现在 Illuminate\Database\Eloquent\Model 上的冲突。

3.0.0 - 2017年7月20日

  • 解析器不再接受对象进行实例化。相反,对象直接传递到 presenter()presenterOrFail() 方法。
  • 解析器上新增了 resolveWith() 方法,接受一个可调用来自定义解析。
  • 解析器中已删除对 presenterClass() 的支持,转而使用解析器上的新 resolveWith() 方法。您可以将包含现有 presenterClass() 逻辑的可调用传递给解析器。
  • 应仅通过新的 model() 方法进行模型访问。已禁用对 _model 的访问。

2.0.0 - 2017年2月12日

  • Factory 替换为新的 Resolver 类。
  • 移除了对 deefour\producer 的依赖。
  • 移除了 Presentable 合约。
  • 简化了 README.md

1.0.0 - 2015年10月7日

  • 发布 1.0.0 版本。

0.8.0 - 2015年8月8日

  • deefour/producer 的更新进行兼容性更改。
  • 新的 Factory 类可用于防止在 deefour/producer 中直接与工厂交互。
  • 将呈现器解析抽象到新的 deefour/producer
  • 移除了 Laravel 服务提供者和外观。应使用 deefour/producer 中的 'producer' 服务。

0.6.2 - 2015年6月5日

  • 现在遵循 PSR-2。

0.6.0 - 2015年5月24日

  • 移除了基呈现器上的 model() 方法。
  • $model 属性重命名为 $_model 以避免与名为 'model' 的实际模型属性冲突。
  • 呈现器现在只为呈现器上的 公共 属性提供属性访问。
  • 在基呈现器上对 API 方法/属性使用 _ 前缀以进一步避免与属性覆盖冲突。
  • 使 $_model 属性公开。
  • 更新代码格式。

0.5.0 - 2015年4月27日

  • 蛇形到驼峰式方法转换现在被缓存以提高性能。
  • 对于缺少的属性/方法不再抛出异常。有关说明,请参阅 6f33dda

0.4.0 - 2015年3月19日

  • presenter() 辅助函数重命名为 present()
  • 从 Composer 自动加载中移除 helpers.php。开发者应能够选择是否包含这些函数。
  • 清理文档块。
  • 对呈现器工厂进行类型提示。
  • Presentable 特性重命名为 ResolvesPresenters 以避免与 \Deefour\Presenter\Contracts\Presentable 命名冲突。

0.3.0 - 2015年3月16日

  • 允许显式请求呈现器,绕过模型默认值。例如
      $article = new Article;
      echo get_class($article->presenter()); //=> 'ArticlePresenter'
      echo get_class($article->presenter(FeaturedArticlePresenter::class)); //=> 'FeaturedArticlePresenter'

0.2.3 - 2015年2月27日

  • 现在可以直接将 Illuminate\Support\Collection 实例和原生 PHP 数组传递给 presenter() 辅助函数。

0.2.2 - 2015年2月20日

  • 更新了对 Laravel Eloquent 关系的支持。现在在请求时,关系会被检索并转换为包裹在呈现器中的对象或集合。

0.2.0 - 2015年2月5日

  • 修复服务提供者。
  • 如果可用,全局 presenter() 将与 Laravel IoC 容器一起工作。
  • 移动特性。

0.1.0 - 2014年11月21日

  • 初始发布。

许可

版权所有 (c) 2014 Jason Daly (deefour)。在 MIT 许可证 下发布。