Skip to content

Commit 7ef55c2

Browse files
authored
Create presenter.md
1 parent 82a5eb4 commit 7ef55c2

File tree

1 file changed

+201
-0
lines changed

1 file changed

+201
-0
lines changed

presenter.md

+201
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
# Presenter
2+
3+
4+
5+
This package provides an easy way to create Presenters that can be used to [decorate](https://en.wikipedia.org/wiki/Decorator_pattern) an Eloquent Model. It is heavily inspired by [Hemp Presenter](https://github.com/davidhemphill/presenter) and [Laravel API Resources](https://laravel.com/docs/6.x/eloquent-resources), however it comes with some key differences:
6+
- It is a *simplified* version that does not offers Traits and Macros
7+
- It provides an easy way to handle *paginated* models
8+
- It does not focus solely in JSON API responses but it serves as a *general purpose* decorator that can be used anywhere in the project
9+
10+
## TL;DR
11+
12+
A **Decorator** is an object that wraps another object in order to add functionality to the wrapped object. It also delegates calls to methods not available on the decorator to the class being decorated. Decorators can be useful when you need to modify the functionality of a class without relying on inheritance. You can use it to add optional features to your objects like logging, access-control, and things of that sort. A **Presenter** is a type of decorator used to present an object to the view of an application, such as a Blade view, or an API response.
13+
14+
15+
## Usage
16+
17+
### Customizing Presenter Classes
18+
19+
Presenters are simple classes designed to encapsulate complex or repetitive view logic. For example, here is a simple `UserPresenter` class:
20+
21+
```php
22+
<?php
23+
24+
namespace App\Presenters;
25+
26+
use CultureGr\Presenter\Presenter;
27+
28+
class UserPresenter extends Presenter
29+
{
30+
31+
public function fullname()
32+
{
33+
return $this->firstname.' '.$this->lastname;
34+
}
35+
}
36+
```
37+
38+
Note that the original model's properties (`firstname`, `lastname`) can be directly accessed using the `$this` variable. This is because the `Presenter` class automatically proxies property and method access down to the underlying model.
39+
40+
This class has a custom method `fullname` that can be called wherever an instance of this Presenter is used.
41+
42+
```php
43+
$presentedUser->firstname; //=> 'John'
44+
$presentedUser->lastname; //=> 'Doe'
45+
$presentedUser->fullname() //=> 'John Doe'
46+
```
47+
48+
If the presented model needs to be transformed into a JSON structure the Presenter class should define a `toArray` method which returns the array of attributes that should be converted to JSON when sending the response.
49+
50+
```php
51+
<?php
52+
53+
namespace App\Presenters;
54+
55+
use CultureGr\Presenter\Presenter;
56+
57+
class UserPresenter extends Presenter
58+
{
59+
public function fullname()
60+
{
61+
return $this->firstname.' '.$this->lastname;
62+
}
63+
64+
public function toArray()
65+
{
66+
return [
67+
'id' => $this->id,
68+
'fullname' => $this->fullname()
69+
// ...
70+
];
71+
}
72+
}
73+
```
74+
75+
### Presenting Single Models
76+
77+
Once the presenter is defined, it may be used to create a presented model using the `make` factory method:
78+
79+
```php
80+
$user = User::first();
81+
$presentedUser = UserPresenter::make($user);
82+
```
83+
84+
The presented model may be used anywhere in the project. If the model needs to be serialized into a response (like for a view or API response) the overwritten `toArray` method must be explicitly called, or it can be directly returned from a route or controller:
85+
86+
```php
87+
<?php
88+
89+
namespace App\Http\Controllers;
90+
91+
use App\Models\User;
92+
use App\Presenters\UserPresenter;
93+
94+
class UserController extends Controller
95+
{
96+
public function show($id)
97+
{
98+
return view('users.show', [
99+
'user' => UserPresenter::make(User::find($id))->toArray()
100+
]);
101+
}
102+
}
103+
```
104+
105+
### Presenting Collections
106+
107+
To present a collection of models, the static `collection` method on the Presenter class can be used:
108+
109+
```php
110+
$users = User::all();
111+
$presentedUsers = UserPresenter::collection($users);
112+
```
113+
114+
The collection of presented models may be used anywhere in the project. If the collection needs to be serialized into a response (like for a view or API response) the overwritten `toArray` method must be explicitly called, or it can be directly returned from a route or controller:
115+
116+
```php
117+
<?php
118+
119+
namespace App\Http\Controllers;
120+
121+
use App\Models\User;
122+
use App\Presenters\UserPresenter;
123+
124+
class UserController extends Controller
125+
{
126+
public function index()
127+
{
128+
$users = User::all();
129+
130+
return UserPresenter::collection($users);
131+
}
132+
}
133+
```
134+
135+
The output will be something like this:
136+
137+
```json
138+
[
139+
{"id": "1", "fullname": "John Doe"},
140+
{"id": "2", "fullname": "Jane Doe"}
141+
]
142+
```
143+
144+
### Presenting Paginated Collections
145+
146+
To present a paginated collection of models, the static `pagination` method on the Presenter class can be used:
147+
148+
```php
149+
$users = User::paginate();
150+
$presentedUsers = UserPresenter::pagination($users);
151+
```
152+
153+
The paginated collection of presented models may be used anywhere in the project. If the collection needs to be serialized into a response (like for a view or API response) the overwritten `toArray` method must be explicitly called, or it can be directly returned from a route or controller:
154+
155+
```php
156+
<?php
157+
158+
namespace App\Http\Controllers;
159+
160+
use App\Models\User;
161+
use App\Presenters\UserPresenter;
162+
163+
class UserController extends Controller
164+
{
165+
public function index()
166+
{
167+
$users = User::paginate();
168+
169+
return UserPresenter::pagination($users);
170+
}
171+
}
172+
```
173+
174+
The output will contain the presented models wrapped in a `data` key, as long as `meta` and `links` keys with information about the paginator's state:
175+
176+
```json
177+
{
178+
"data": [
179+
{"id": "1", "fullname": "John Doe"},
180+
{"id": "2", "fullname": "Jane Doe"}
181+
],
182+
"links":{
183+
"first": "http://example.com/pagination?page=1",
184+
"last": "http://example.com/pagination?page=1",
185+
"prev": null,
186+
"next": null
187+
},
188+
"meta":{
189+
"current_page": 1,
190+
"from": 1,
191+
"last_page": 1,
192+
"path": "http://example.com/pagination",
193+
"per_page": 15,
194+
"to": 10,
195+
"total": 10
196+
}
197+
}
198+
```
199+
200+
201+

0 commit comments

Comments
 (0)