Home >PHP Framework >Laravel >Let's talk about how to use PHP's decorator pattern in Laravel
How to use PHP's decorator pattern in Laravel? The following article will introduce to you how to use the PHP decorator mode in Laravel. I hope it will be helpful to you!
Design patterns are important for every developer. It solves very common problems in every project you build.
It helps you add extra behavior on an object without affecting other objects in the same class other objects.
The decorator pattern is a design pattern that allows for dynamically adding behavior to a single object, Without affecting the behavior of other objects in the same class
Suppose we have a Post model
class Post extends Model { public function scopePublished($query) { return $query->where('published_at', '<=', 'NOW()'); } }
In our PostsController, we have the index method as follows
class PostsController extends Controller { public function index() { $posts = Post::published()->get(); return $posts; } }
In order to cache the posts and avoid querying the database every time we need to list the posts, we can do the following
class PostsController extends Controller { public function index() { $minutes = 1440; # 1 day $posts = Cache::remember('posts', $minutes, function () { return Post::published()->get(); }); return $posts; } }
Now we cache posts for 1 day. But looking at the code, the controller knows too much. It knows how many days we have cached it, it caches the object itself.
Similarly, assume you are implementing the same functionality for Tag, Category, Archives of HomePageController. That's too much code to read and maintain.
In most cases, the warehouse pattern is connected to the decorator pattern.
First, let’s use the repository pattern to separate the way of getting posts, creating app/Repositories/Posts/PostsRepositoryInterface.php
namespace App\Repositories\Posts; interface PostsRepositoryInterface { public function get(); public function find(int $id); }# with the following content ##Create a
PostsRepository with the following content in the same directory
namespace App\Repositories\Posts; use App\Post; class PostsRepository implements PostsRepositoryInterface { protected $model; public function __construct(Post $model) { $this->model = $model; } public function get() { return $this->model->published()->get(); } public function find(int $id) { return $this->model->published()->find($id); } }Go back to the PostsController and apply the changes to
namespace App\Http\Controllers; use App\Repositories\Posts\PostsRepositoryInterface; use Illuminate\Http\Request; class PostsController extends Controller { public function index(PostsRepositoryInterface $postsRepo) { return $postsRepo->get(); } }The controller becomes healthy and knows enough Details get the job done. Here, we rely on Laravel's IOC to inject the specific object of the Posts interface to get our postsAll we need to do is tell Laravel's IOC which class to create when using the interface. In your
app/Providers/AppServiceProvider.php add binding method
namespace App\Providers; use App\Repositories\Posts\PostsRepositoryInterface; use App\Repositories\Posts\PostsRepository; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider { public function register() { $this->app->bind(PostsRepositoryInterface::class,PostsRepository::class); } }Now whenever we inject
PostsRepositoryInterface Laravel will create# An instance of ##PostsRepository
and returns it.
Here caching is the behavior and the object/class is the
PostsRepository. Let’s create
app/Repositories/Posts/PostsCacheRepository.php In this class, we Accepts a Caching object and a PostsRepository object, and then uses a class (decorator) to add caching behavior to the PostsRepository instance.
We can use the same example to send an HTTP request to some service and then return the model in case of failure. I believe you will benefit from this pattern and how easy it is to add behavior.
namespace App\Repositories\Posts; use App\Post; use Illuminate\Cache\CacheManager; class PostsCacheRepository implements PostsRepositoryInterface { protected $repo; protected $cache; const TTL = 1440; # 1 day public function __construct(CacheManager $cache, PostsRepository $repo) { $this->repo = $repo; $this->cache = $cache; } public function get() { return $this->cache->remember('posts', self::TTL, function () { return $this->repo->get(); }); } public function find(int $id) { return $this->cache->remember('posts.'.$id, self::TTL, function () { return $this->repo->find($id); }); } }Now check the file again and you will see that it is very easy to read and maintain. Likewise, it's testable if you decide to remove the cache layer at some point. You just need to change the binding in
AppServiceProvider
. No additional changes are required.Conclusion
laravel video tutorial]
The above is the detailed content of Let's talk about how to use PHP's decorator pattern in Laravel. For more information, please follow other related articles on the PHP Chinese website!