robclancy / presenter
使用presenter装饰你的对象。主要目的是将展示逻辑从你的模型中分离出来。
Requires
- php: ^8.1
Requires (Dev)
- illuminate/view: >=9.0
- mockery/mockery: ~1.3.0
- phpunit/phpunit: ^10.0
README
使用presenter装饰你的对象。主要目的是将展示逻辑从你的模型中分离出来。
对于任何紧急问题,请通过@robboclancy联系我,GitHub并不总是能正确通知我。
这个库提供了一个简单的类,帮助你为对象或数组创建Presenter
。它还提供了一些额外的功能,用于在Laravel中与控制器中的少量额外代码一起使用(在大多数情况下不需要额外代码)。
目录
安装
composer require robclancy/presenter:^2.0
或者
将robclancy/presenter
添加到你的composer.json
文件的“require”部分。
"robclancy/presenter": "^2.0"
运行composer update
以获取包的最新版本。
Laravel
此包为Laravel 5.8+ < Laravel 10提供了一个可选的服务提供者,以便你可以自动化一些额外步骤。您需要使用上面的composer方法进行安装,然后注册服务提供者到您的应用程序。
打开app/config/app.php
并找到providers
键。添加以下内容
'Robbo\Presenter\PresenterServiceProvider',
到数组中某个位置
'Illuminate\View\ViewServiceProvider',
现在,如果您使用以下描述的laravel方法
,则presenter将自动创建。
用法
Presenter
是一个非常简单的类,它重载了方法和变量,这样你就可以在不向模型或控制器等区域添加视图逻辑的情况下,向对象或数组添加额外的逻辑,并保持任何额外的逻辑不在视图中。
通用用法
假设你有一个用户列表,并且你想为每个用户生成一个链接到其个人资料。许多人会在视图中构建URL,或者更糟糕的是,在控制器中构建。为了分离这种逻辑,我们改用presenter。假设我们有一个具有id
和username
属性的简单User
类。presenter可能看起来像这样。
class UserPresenter extends Robbo\Presenter\Presenter { public function url() { return $this->id.'-'.$this->username; } }
现在,我们的视图应该接收这个presenter的实例,这个实例可以通过以下方式创建:$user = new UserPresenter(new User);
。如果我们想链接到用户页面,我们只需要调用$user->url
。现在,你已经实现了逻辑和视图的良好分离,并且可以轻松修改这个类,为所有区域添加User
的属性。然而,你可能不希望以这种方式调用方法,这可能与你的做法不一致,或者你可能想让代码看起来更整洁。这就是带有present
前缀的方法的作用。我们只需将presenter更新为以下内容。
class UserPresenter extends Robbo\Presenter\Presenter { public function presentUrl() { return $this->id.'-'.$this->username; } }
现在,当您执行$user->url
时,presenter将调用这个新方法。此外,您可以通过调用$user['url']
来通过ArrayAccess
访问此方法。关于ArrayAccess
支持的更多信息,请参阅以下内容。
手动启动
如上所述,要创建一个presenter,您只需使用new
关键字初始化,并注入对象或数组。
class User { // ... } class UserPresenter extends Robbo\Presenter\Presenter { // ... } $user = new User; // handle stuff here // make sure to "convert" to a presenter before the object gets to your views $user = new UserPresenter($user); // Can also create a presenter for arrays $user = [ 'id' => 1, 'username' => 'Robbo', ]; // same as before $user = new UserPresenter($user);
Laravel用法
如果您正在使用Laravel并且已经按照上述安装说明操作,您可以使用提供的接口Robbo\Presenter\PresentableInterface
来自动将模型实例转换为Presenter
,无论是从集合还是当模型直接发送到视图时。
服务提供者所做的就是在创建视图对象之前扩展Laravel的视图组件。这一步通过调用->getPresenter()
将实现PresentableInterface
的任何内容转换为Presenter
。这意味着您不需要在控制器中添加任何额外内容来让视图使用对象展示器。
例如。
class UserPresenter extends Robbo\Presenter\Presenter { // ... } class User implements Robbo\Presenter\PresentableInterface { /** * Return a created presenter. * * @return Robbo\Presenter\Presenter */ public function getPresenter() { return new UserPresenter($this); } }
现在,当您的User
模型被发送到视图时,无论是作为一个集合、数组还是单独发送,它都会通过提供的getPresenter()
方法转换为展示器。所以您的控制器将与User
一起工作,当您到达视图时,它将使用UserPresenter
与内部对象User
一起工作。
数组用法
1.1.x引入了对数组的支持。展示器将实现ArrayAccess
,所以如果您想在视图中使用$presenter['variable']
访问变量,您可以这样操作。但更重要的是,您可以用一个数组而不是一个对象来传递展示器。所以您可以使用展示器来处理数组数据以及对象。
例如。
$user = [ 'id' => 1, 'username' => 'Robbo', ]; class UserPresenter extends Robbo\Presenter\Presenter { public function presentUrl() { // This will work exactly the same as previous examples return $this->id.'-'.$this->username; // You can also do this... return $this['id'].'-'.$this['username']; } } // Now we create a presenter much the same as before $user = new UserPresenter($user); // In our views we can use the $user as if it were still an array echo 'Hello, ', $user['username']; // Or even treat it like the object that it is echo 'Hello, ', $user->username; // And like other examples, we can present the url in the same way echo 'The URL: ', $user->url; echo 'And again: ', $user['url'];
扩展装饰器
从1.2.x开始,我增加了一个装饰器对象。这个对象负责将具有PresentableInterface
的对象转换为Presenter
。与之前的实现相比,引入新类的原因是可以更好地测试它,并允许您扩展它。以下是一个扩展Decorator
的示例,这样您就可以使用对象上的公共变量$presenter
而不是使用PresentableInterface
和getPresenter()
方法。
注意:这些说明适用于Laravel。
首先扩展装饰器...
use Robbo\Presenter\Decorator as BaseDecorator; class Decorator extends BaseDecorator { /* * If this variable implements Robbo\Presenter\PresentableInterface then turn it into a presenter. * * @param mixed $value * @return mixed $value */ public function decorate($value) { if (is_object($value) and isset($value->presenter)) { $presenter = $value->presenter; return new $presenter; } return parent::decorate($value); } }
要使用您的新装饰器,请将以下内容添加到start/global.php
中,或者添加到您自己的服务提供者中。
// In start/global.php App::make('presenter.decorator', App::share(function($app) { $decorator = new Decorator; Robbo\Presenter\Presenter::setExtendedDecorator($decorator); return $decorator; })); // In a service provider's 'register' method $this->app['presenter.decorator'] = $this->app->share(function($app) { $decorator = new Decorator; Robbo\Presenter\Presenter::setExtendedDecorator($decorator); return $decorator; });
这就完成了。您可以使用这种方法轻松自动化创建展示器,以满足您的工作流程。
变更日志
3.0
- 最低PHP版本现在是8.1
- 修复了PHP 8.1的ArrayAccess弃用
2.0.1
- 从2.x分支以支持< PHP 8.1
- 在一定程度上现代化了存储库
- 更新了文档
2.0.0
- 最低Laravel版本现在是5.8
- 最低PHP版本现在是7.1
- 改进了视图工厂的集成,应该是有前瞻性的
1.4.0
- 添加了Laravel包发现,感谢luisdalmolin
- 使用Laravel视图工厂的合约而不是具体类,这修复了与https://github.com/fntneves/laravel-transactional-events的不兼容性
- 更新https://github.com/FriendsOfPHP/PHP-CS-Fixer/releases,并使其在测试中也运行
1.3.3
- 更新测试,以更好地覆盖5.4之后的Laravel版本,并将许可证更改为MIT
1.3.2
- 更新以支持
laravel 5.4.x
,只有实际更改,不包括样式或测试 - 添加php-cs-fixer以更新代码样式
- 添加示例,以便在完整应用程序场景中对提供者的测试进行测试
1.3.1
- 更新以支持
laravel 5.x
1.3.0
- 更新以支持
laravel 4.2.x
,要在4.1.x
中使用,请保持版本为1.2.*
- 迁移到PSR-4,现在支持PHP 5.4+
- 进行了一些小的重构和检查,对'present'方法使用'isset',感谢BenConstable
1.2.0
- 展示器现在可以嵌套,感谢alexwhitman
- 添加了对使用Laravel的
View::with(array here)
的支持,感谢skovachev - 增加了在presenter变量上使用
isset(...)
和unset(...)
的功能,感谢nsbucky - 新增了一个用于创建presenter对象的装饰器。这使得您能够轻松地扩展对象装饰时的行为
1.1.0
- Presenter类现在实现了ArrayAccess
- 增加了使用数组作为内部数据的功能
1.0.2
- 修复了由Laravel更新引起的bug
- 增加了从PresentableInterface对象更智能地转换presenters的功能
- 增加了对象获取器
getObject
以检索内部对象
1.0.1
- 修复了由Laravel更新引起的bug
1.0.0
- 初始发布