brandonshar/presenters
Composer 安装命令:
composer require brandonshar/presenters
包简介
JSONable Presenters Objects
README 文档
README
WARNING While this is tested, I have not used it in a production or extensively in a development environment yet. I'm pretty sure I'm going to love using it, but until I do that I feel obligated to offer a warning about its usefulness.
Installation
Install via composer and just start using it. Couldn't be easier!
composer require brandonshar/presenters
So what is this?
Have you ever had a model, or combination of models, that you wanted to return with different data depending on the endpoint? Maybe you have a resource controller called VehicleOnCraigslistController and when someone hits your VehicleOnCraigslistController@show method, you want to return a set of data that represents a vehicle listed on Craigslist. This set of data is likely comprised of your Vehicle model and your CraigslistAd model, but different than what you return from your VehicleController@show method, your CraigslistAdController@show, or just a combination of the two. This is where Presenters come in to save the day!
How do I do those great sounding things?
Presenters have a number of great features. Let's see them all in action!
Basic Presenter Example
use brandonshar\Presenter; class VehicleOnCraigslistPresenter extends Presenter { protected $vehicle; protected $craigslistAd; public function __construct(Vehicle $vehicle, CraigslistAd $craigslistAd) { $this->vehicle = $vehicle; $this->craigslistAd = $craigslistAd; } } $presenter = VehicleOnCraigslistPresenter::present($vehicle, $vehicle->craiglistAd);
There's the minimum code for a presenter! (present is just some nice syntactic sugar that provides a more fluent way to instantiate your presenter. If it makes you nervous, you can always new it up like usual).
Ok... I can see that you're not very impressed yet. Let's do things with it!
Delegation
Delegation allow you to reach through your presenter to the models (or other objects) it contains while avoiding much of the boilerplate of typical getters.
class VehicleOnCraigslistPresenter extends Presenter { //... protected $delegatesTo = [ 'vehicle' => ['year', 'make'], 'craigslistAd' => ['listedAt'], ]; //... }
Now we can "reach through" the presenter to access the delegates properties!
$presenter = VehicleOnCraigslistPresenter::present($vehicle, $vehicle->craiglistAd); $presenter->year; //$presenter->vehicle->year; $presenter->make; //$presenter->vehicle->make; $presenter->listedAt; // $presenter->craigslistAd->listedAt;
Ok, a little cooler, right? What if we need something more complicated?
Getters (Accessors)
The presenter has getters that work just like Laravel's Eloquent getters: just create a method called getPropertyNameAttribute (if your property is called "propertyName") that optionally accepts a single argument (the currently set value of the named property) :
class VehicleOnCraigslistPresenter extends Presenter { //... public function getVehicleTitleAttribute() { return "{$this->vehicle->year} {$this->vehicle->make} {$this->vehicle->model}"; } public function getCachedAtAttribute($currentValue) { return DateTime::createFromFormat('Y-m-d', $currentValue)->format('l, M jS'); } //... }
We can now access this like any other property:
$presenter->vehicleTitle; //or if you prefer $presenter->vehicle_title;
Both camelCase and snake_case work the same. If you put information into your presenter manually, it will automatically be passed as an argument to your getter.
$presenter->cachedAt = '2017-09-21'; echo $presenter->cachedAt; //Thursday, Sept 21st
Note: Wish you had a better way to put data on your presenter? Just hang tight for the tap method below!
getAttribute
If you need to access an attribute that isn't the attribute named in your getter, you should use the getAttribute method:
return $this->getAttribute('cachedAt'); //or (they both work the same) return $this->getAttribute('cached_at');
You could go directly to the attributes array property, but this requires you to make sure you match case with the json casting below (defaulting to snake_case). Because of this, the preferred way is to use the get (and corresponding set) attribute methods.
Setters (Mutators)
Technically, the presenters do have setters, but I haven't thought of a use case for them. They exist in order to aid the getters, but could be used standalone. I haven't thought of a real use case for them, but here's a quick example in case you do:
public function setSomeExampleAttribute($value) { $this->setAttribute('someExample', strtoupper($value)); }
Now you can:
$presenter->someExample = 'my message'; echo $presenter->someExample; //MY MESSAGE
setAttribute
Just like getting above, the preferred way to set internal attributes is as follows:
$this->setAttribute('someExample', $value); // or $this->setAttribute('some_example', $value);
Tap
I'm a sucker for fluid syntax and avoiding temporary variables, so if you want to add some instance variables to your presenter when it's instantiated, you can do so with the tap method:
$presenter = VehicleOnCraigslistPresenter::present($vehicle, $vehicle->craiglistAd)->tap(function ($presenter) { $presenter->cachedAt = date('Y-m-d'); }); echo $presenter->cachedAt; //Thursday, Sept 21st (don't forget our getter from above)
Json
I try to exclusively develop API endpoints to be consumed by my front-end, so my use cases for this are always json. If you're like me, then you'll be happy to know that you have three great ways to get json out of your presenter: You can use the toJson method:
echo $presenter->toJson();
You can simply use the php function json_encode (presenters implement JsonSerializable)
echo json_encode($presenter);
OR if you use Laravel (and if you don't, you should strongly reconsider), you can just directly return presenters from any controller route and they'll be converted to json automatically! This is where the code really starts to get sexy:
return VehicleOnCraigslistPresenter::present($vehicle, $vehicle->craiglistAd)->tap(function ($p) { $p->cachedAt = date('Y-m-d'); });
Wait, what is converted to JSON?
Presenters automatically turn all of their delegates, any getters, and any variables that were manually set (through tap or otherwise) as JSON. Our json from the presenter we've been building will look something like this:
{"year": 2015, "make": "Chevy", "listed_at": "2017-08-01", "vehicle_title": "2015 Chevy Volt", "cached_at": "Thursday, Sept 21st", "some_example": "MY MESSAGE"}
But hang on, I prefer my JSON to be camelCase? Is there any hope for me?
Oh come on, how on earth would we manage to make something like.. OH WAIT ONE SECOND
class VehicleOnCraigslistPresenter extends Presenter { //... protected $jsonEncodeCase = 'camel'; //... }
Happy? Valid options are camel, snake, or (if you're an irredeemable monster), studly
That's all for now! I hope to update as I begin using this in my projects more and would be irrationally thrilled to receive a pull request if you think you can improve it.
brandonshar/presenters 适用场景与选型建议
brandonshar/presenters 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 16 次下载、GitHub Stars 达 1, 最近一次更新时间为 2017 年 07 月 14 日, 在 PHP 生态内属于活跃度较高的组件。
我们在过去多个企业项目中使用过 brandonshar/presenters 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 brandonshar/presenters 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
统计信息
- 总下载量: 16
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 1
- 点击次数: 0
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: Unknown
- 更新时间: 2017-07-14