Home » Code » Laravel 4 Cache as a Service

Laravel 4 Cache as a Service

Posted by on February 3rd, 2014

Laravel 4 Cache as a Service
Cache is an incredibly important component of a web application stack. If you are not caching the data in your application you will likely hit premature bottlenecks and your users will suffer with slow response times. Implementing caching is a big step towards scaling an application and will significantly reduce the overhead of your application.

A couple of weeks ago I looked at using Cache in your Laravel 4 application. Laravel makes it really easy to implement caching in your application by providing a clear and powerful API whilst abstracting the specific implementation of the actual caching mechanism.

At the end of that tutorial I noted that whilst it’s easy to actually use the Laravel Cache API, how to structure and use Cache in terms of your application is not quite so obvious.

In this article I’m going to be looking at setting up Cache as a service in your application. As with my article on setting up advanced Validation Services in Laravel 4, this article was also heavily inspired by the excellent work of Chris Fidao from his book, Implementing Laravel. If you are looking to learn more about these types of patterns in modern web applications, I highly recommend that you grab yourself a copy.

Why a service?

If you have been following a long with this series you will have read my articles on advanced Validation Services, using Repositories and creating Entities.

By structuring our code as separate services we benefit in a number of ways.

Firstly by separating the caching layer from the storage or entity layer you make testing in isolation much simpler. If your Cache was tightly coupled with your storage your tests would involve lots of mocks and it would be difficult to ensure that you were really testing the right thing.

Secondly, by creating separate layers of functionality, we make combining these services really easy. This also has the benefit that if we need to change something in the future, we only have to change a single aspect of our code once, or we could either swap out the implementation or even remove it all together.

Dealing with Cache in your Controller would be a terrible idea, but dealing with it as a service as part of your application specific code means that we can reuse this service for our application, API or even a command line client.

How will Cache as a service work?

Before I get into actually writing the code to create a Cache Service, first I will explain how this is going to work and how it will be structured.

Cache Interface
Firstly I will create a Cache Interface that my Cache Service will implement. As I’ve mentioned in previous articles, this ensures that the methods that are defined on this contract are available on the specific implementation of the class and we can type hint the class to ensure that the methods are available.

Laravel Cache Service
Secondly, I will create a Laravel implementation of my Cache Service. This is basically the same as what I did when I created my Laravel implementation of my Validation Service in this article. This means if I wanted to move away from Laravel’s Cache API and use a generic third party implementation instead I’m not going to be handcuffed to Laravel.

Abstract Decorator
In order for this to work I will be using the Decorator Pattern (I’ll explain what that is below) as a wrapper to my Repository. So for my User Repository I will create an Abstract User Decorator.

Cache Decorator
Now that I have the Abstract Decorate I can create a specific Cache Decorator which can be wrapped around the Repository to implement caching.

Add to the Service Provider
And finally I can add the Cache Decorator to the Repository Service Provider so my caching layer is automatically implemented on the Repository. This means I can continue to use the Repository in exactly the same way up until this point, but instead of hitting the database, the cache layer will return data from the cache if it is available. The rest of my application does not need to know whether caching is implemented or not.

What is the Decorator Pattern?

The Decorator Pattern is a way of adding functionality to an object without modifying the original object. This means you can extend the functionality of an object without effecting any other instances of that same object or you can add many different decorators to an object to modify the functionality of the object in different ways.

So how will this work in this case?

In the Service Provider we will create the Repository as normal by binding the EloquentUserRepository class to the UserInterface to implement the Repository pattern.

We will then pass that object into the Cache Decorator. The Cache Decorator will have a method for each of the methods that we want to implement caching on.

If the Cache Decorator has the data that we require in the cache, we can simply return the cache. However if that data is not in the cache, we can fall back to the Repository and return the data from the database whilst also caching the returned data for subsequent requests.

Finally in the Service Provider we can return the User Repository with the Cache Decorator. This means if we wanted to add multiple Decorators to the Repository, we could do so in the Service Provider but the rest of our application wouldn’t know the difference.

Hopefully that makes sense. Basically we are just taking the original Repository and “wrapping” it in additional functionality. If the Cache layer has the correct data we can return it without touching the database. If the Cache layer does not have the data we can go down a layer to the Repository and return the data from the database whilst also caching the returned data for the next request.

Create the Cache Interface

So the first thing to do is to create the Cache Interface:

<?php namespace Cribbb\Service\Cache;

interface CacheInterface {

  /**
   * Get
   *
   * @param string $key
   * @return mixed
   */
  public function get($key);

  /**
   * Put
   *
   * @param string $key
   * @param mixed $value
   * @param integer $minutes
   * @return mixed
   */
  public function put($key, $value, $minutes = null);

  /**
   * Has
   *
   * @param string $key
   * @return bool
   */
  public function has($key);

}

Currently this Interface is basically the same as the Laravel Cache interface. However, by defining our own interface, we are fee to modify or add methods or functionality that we need for this particular application.

Hopefully the above code should be pretty familiar by now. Here I’m basically defining a contract that will enforce any class that uses this interface to have the above methods.

Create the Laravel Cache Service

Next we can create the Laravel specific Cache Service. As with the Validation Service, this is a Laravel implementation of the Cache Service using Laravel’s built in Cache class. This class will implement the CacheInterface that we just created. If you wanted to use a different Caching system in the future, you would just need to create a new implementation like this to make the change:

<?php namespace Cribbb\Service\Cache;

use Illuminate\Cache\CacheManager;

class LaravelCache implements CacheInterface {

 /**
  * @var Illuminate\Cache\CacheManager
  */
  protected $cache;

  /**
   * @var string
   */
  protected $tag;

  /**
   * @var integer
   */
  protected $minutes;

  /**
   * Construct
   *
   * @param Illuminate\Cache\CacheManager $cache
   * @param string $tag
   * @param integer $minutes
   */
  public function __construct(CacheManager $cache, $tag, $minutes = 60)
  {
    $this->cache = $cache;
    $this->tag = $tag;
    $this->minutes = $minutes;
  }

  /**
   * Get
   *
   * @param string $key
   * @return mixed
   */
  public function get($key)
  {
    return $this->cache->tags($this->tag)->get($key);
  }

  /**
   * Put
   *
   * @param string $key
   * @param mixed $value
   * @param integer $minutes
   * @return mixed
   */
  public function put($key, $value, $minutes = null)
  {
    if( is_null($minutes) )
    {
      $minutes = $this->minutes;
    }

    return $this->cache->tags($this->tag)->put($key, $value, $minutes);
  }

  /**
   * Has
   *
   * @param string $key
   * @return bool
   */
  public function has($key)
  {
    return $this->cache->tags($this->tag)->has($key);
  }

}

In the construct method I will inject an instance of Laravel’s CacheManager. This will make testing possible because we can just mock the CacheManager.

Next we can set a tag for this specific cache section. If you are unfamiliar with how tags work using the Laravel Cache API, take a look at Working with Cache in Laravel 4.

Finally I will set a default number of minutes to be used by the cache. However this can be overwritten if required.

Next we need to implement the get, put and has methods to fulfil the CacheInterface contract.

Create the Abstract Decorator

Next we need to create an AbstractUserDecorator class for the UserRepository. This file will be used as a base for all of the decorators that we might possibly need for the UserRepository:

<?php namespace Cribbb\Repository\User;

use Cribbb\Repository\RepositoryInterface;

abstract class AbstractUserDecorator implements RepositoryInterface, UserRepository {

  /**
   * @var UserRepository
   */
  protected $user;

  /**
   * Construct
   *
   * @param UserRepository $user
   */
  public function __construct(UserRepository $user)
  {
    $this->user = $user;
  }

  /**
   * All
   *
   * @return Illuminate\Database\Eloquent\Collection
   */
  public function all()
  {
    return $this->user->all();
  }

  /**
   * Find
   *
   * @param int $id
   * @return Illuminate\Database\Eloquent\Model
   */
  public function find($id)
  {
    return $this->user->find($id);
  }

  /**
   * Create
   *
   * @param array $data
   * @return boolean
   */
  public function create(array $data)
  {
    return $this->user->create($data);
  }

  /**
   * Update
   *
   * @param array $data
   * @return boolean
   */
  public function update(array $data)
  {
    return $this->user->update($data);
  }

  /**
   * Delete
   *
   * @param int $id
   * @return boolean
   */
  public function delete($id)
  {
    return $this->user->delete($id);
  }

}

In this file we inject an instance of UserRepository and then implement all of the methods that are defined on the interface.

As you can see from the code above, I’m basically just passing the methods through to the Repository. You can think of this like the bottom layer of the stack with each decorator as a layer on top.

Cache Decorator

Next I can create the CacheDecorator:

<?php namespace Cribbb\Repository\User;

use Cribbb\Service\Cache\CacheInterface;

class CacheDecorator extends AbstractUserDecorator {

  /**
   * @var CacheInterface
   */
  protected $cache;

  /**
   * Construct
   *
   * @param UserRepository $user
   * @param CacheInterface $cache
   */
  public function __construct(UserRepository $user, CacheInterface $cache)
  {
    parent::__construct($user);
    $this->cache = $cache;
  }

  /**
   * All
   *
   * @return Illuminate\Database\Eloquent\Collection
   */
  public function all()
  {
    $key = md5('all');

    if($this->cache->has($key))
    {
      return $this->cache->get($key);
    }

    $users = $this->user->all();

    $this->cache->put($key, $users);

    return $users;
  }

  /**
   * Find
   *
   * @param int $id
   * @return Illuminate\Database\Eloquent\Model
   */
  public function find($id)
  {
    $key = md5('id.'.$id);

    if($this->cache->has($key))
    {
      return $this->cache->get($key);
    }

    $user = $this->user->find($id);

    $this->cache->put($key, $user);

    return $user;
  }

}

In this class I inject an instance of the UserRepository and pass it to the AbstractUserDecorator that we created above. I also inject an instance of the CacheInterface that we created at the beginning. This will be the LaravelCache class.

Next we can overwrite the methods that we want to use caching for by implementing them in this class.

For example, the find method:

/**
 * Find
 *
 * @param int $id
 * @return Illuminate\Database\Eloquent\Model
 */
public function find($id)
{
  $key = md5('id.'.$id);

  if($this->cache->has($key))
  {
    return $this->cache->get($key);
  }

  $user = $this->user->find($id);

  $this->cache->put($key, $user);

  return $user;
}

First I create a unique key by using the md5 function to hash the $id.

Next we can check to see if the cache already has this key. If the key is already in the cache we can just return it.

If the key was not found we can fall back to the database to retrieve the user. After we’ve found the user we can put it into the cache so the next request can use the same copy.

Finally we can return the $user.

Add to the Service Provider

Now in the RepositoryServiceProvider we need to wrap the Repository with the CacheDecorator:

<?php namespace Cribbb\Repository;

use User;
use Cribbb\Service\Cache\LaravelCache;
use Illuminate\Support\ServiceProvider;
use Cribbb\Repository\User\CacheDecorator;
use Cribbb\Repository\User\EloquentUserRepository;
use Cribbb\Repository\Post\EloquentPostRepository;

class RepositoryServiceProvider extends ServiceProvider {

  public function register()
  {
    /**
     * User Repository
     *
     * @return Cribbb\Repository\User\EloquentUserRepository
     */
    $this->app->bind('Cribbb\Repository\User\UserRepository', function($app)
    {
      $user = new EloquentUserRepository(
        new User,
        $app->make('Cribbb\Repository\Post\PostRepository')
      );

      return new CacheDecorator(
        $user,
        new LaravelCache($app['cache'], 'user')
      );
    });
  }

}

First we need to create an instance of the UserRepository and save it as a variable.

Next we can create a new instance of the CacheDecorator and pass the $user into it.

Notice how I’m creating the instance of the LaravelCache service here, passing in the instance of the CacheManager and setting the tag to user.

This might seem a bit like inception, but believe me, once you get your head around what is injected into what, it makes a lot of sense. All of the set up of this object happens in the Service Provider so you don’t have to worry about it anywhere else in your code because it will all magically work for you when you need to call on the Repository. By injecting the objects as dependencies we also make it much easier to test.

By setting the tag in the Service Provider we can invalidate this whole section of the cache by changing this tag. You might want to do that if you push a big change and you want to completely flush this section of the cache. In this case it probably make sense to set the tag based on a configuration option, rather than hardcoding it into the Service Provider.

Tests

A common question with these kind of things is, What do I need to write tests for?

It might seem like we’ve done a lot here, but in all honesty there isn’t much to test. Our Cache Service is basically just a wrapper around the Laravel Cache API, and the Decorator is just a wrapper around the Repository (which in itself is just a wrapper around Eloquent).

Whenever you are simply wrapping existing components, you don’t need to test the return values. Those components already have their own tests so you don’t need to waste time to write your own tests.

So the only tests we need to write are for the getters and setters in our own classes. For example you could write unit tests to ensure that only the correct instance of a particular class can be injected, or a method should only accept a particular type of argument and it should return an instance of a particular object.

Don’t worry about going nuts and testing every possible character of code. Unit test the main stuff and write integration tests for the rest. You don’t want to spend more time writing and maintaining tests than you do actually shipping your product.

Conclusion

I love how easy Laravel makes implementing Cache in an application. By abstracting the actually caching mechanism and providing a clean and clear API to use in your code, Laravel has made using cache a total no-brainer.

However, actually implementing caching in your application is not as clear. Whilst I really like that Laravel does not force any conventions on you, sometimes it is beneficial to be told the best way to structure a certain component of your application so you don’t run into trouble at some point in the future.

As I mentioned at the top of this post, this tutorial was heavily inspired by Chris Fidao from his book, Implementing Laravel. I really love the use of the Decorator pattern to wrap the Repository in a layer of cache. This means the rest of your application does not need to know if the data is cached or not which seems like a pretty nice solution to me.

This is a series of posts on building an entire Open Source application called Cribbb. All of the tutorials will be free to web, and all of the code is available on GitHub.

To view a full listing of the tutorials in this series, click here.

Philip Brown

Hey, I'm Philip Brown, a designer and developer from Durham, England. I create websites and web based applications from the ground up. In 2011 I founded a company called Yellow Flag. If you want to find out more about me, you can follow me on Twitter or Google Plus.

  • ejunker

    How does the cache get invalidated? For example, if a record is updated we want to get the updated record and not the stale one in the cache.

    • You would just update the cache in the update method.

      So in the CacheDecorator you would pass the data to the Repository and then pass it back up to the CacheDecorator to update the cache.

      Does that make sense?

      • cenob8

        Is it possible to use Model event listeners and clear the cache in the e.g. model ‘updating’ method? If so how ?

        • Hmm, I guess you could. I’ve never really looked into that before though.

  • hernan

    hi, Phillip thanks for the great tutorial.

    let me see if i understand the cache invalidate stuff.

    if i modify the update method in the cacheDecorator i would write something like: if ($this->cache->has(md5(‘id.’ . data[‘id’])) {$this->cache->forget(md5(‘id.’ . data[‘id’]))}
    after that update the data and return.
    you think that would work?
    thanks in advance!

    • Yeah, you basically just get rid of the old cache, update the data in the database and then update the cache :)

  • micz123

    Using this concept, i don’t think we can use Entities anymore? I saw Cribbb’s github, and i dont see Cribbb/Entities/User/UserEntity, yet UserController still instantiate this in public __construct?

  • srcnckr

    Hi Philip,

    Use this similar methods. My articles have category field. How to use where, orderby or other Eloquent method in all() method? I don’t this;

    public all($where = array(), $orderBy = array(), $blabla…);

    This is not flexible. I actually, want that. Consider the method of pagination. All transactions should be done according to certain criteria. For the index and category pages. Do I need to write separate methods? For example in ArticleRepository;

    public paginate($page = 1, $limit = 10)
    {
    ….
    $result = $this->article->skip( $limit * ($page-1) )
    ->take($limit)
    ->get();
    ….
    }

    public paginateByCat($cat_id, $page = 1, $limit = 10)
    {
    ….
    $result = $this->article->where(‘category_id’, $cat_id)
    ->skip( $limit * ($page-1) )
    ->take($limit)
    ->get();
    ….
    }

    Exhausting is not it? Do you have any recommendations?

    • Yes, I have that exact same problem. Take a look at this post http://culttt.com/2014/03/17/eloquent-tricks-better-repositories/

      • srcnckr

        Thanks for comment. I thought the same, but very troublesome. :(

        • Did that post not solve your problem?

          • srcnckr

            Partially yes, too long but the only remedy.

            public function all(array $where = array());think the real question is as follows;

            My project have EloquentPostRepository (used dashboard) and PostCacheDecorator (used front). I want to this; PostCacheDecorator already apply some filter. For example, post status (draft or published) but this is not necessary EloquentPostRepository . All CachePostDecorator queries used this filter.

            I don’t want to use such as this example;
            public function all(array $where = array());
            public function getById($id, array $where = array());

            How it best way? I’m stuck here, please help me :)

          • I’m not sure I understand what you mean, but you don’t need the getById method because you could achieve that by a generic getBy method and pass it the $id and value as parameters to the $where argument.

            Does that make sense?

          • srcnckr

            No :) Brown, sorry my bad english. The problem is briefly. In the same query I want to send two or more conditions. get all posts category_id = 0 and status = active by all() or getByPage() methods. Need to define a separate method for each situation?

            Similar problems have fideloper repos; https://github.com/fideloper/Implementing-Laravel/issues/21

  • Carlos

    I follow all the tutorial and when my app tries to resolve my ProductRepository i got this error:
    ‘Class cache does not exist ‘

    Any idea?

    This is my code:
    $this->app->bind(‘repositoriesProductRepositoryInterface’, function($app)
    {
    $product = $app->make(‘repositoriesProductDbRepository’);

    return new ProductCacheDecorator( $product,
    new LaravelCache($app[‘cache’], ‘product’) //app[‘cache’] fails resolving
    );
    });

    I also tried with $app->make(‘cache’) and is not working neither.

    • Carlos

      It’s working now. I forgot to remove the old binding. Thank you for the tutorial.

  • Pingback: Model Presenters in Laravel 4 | Culttt()

  • LearningLaravel

    Hi, can you please clarify how you would add additional decorators for the User repository? You state the following:

    > Next we need to create an AbstractUserDecorator class for the UserRepository. This file will be used as a base for all of the decorators that we might possibly need for the UserRepository.

    However, in the service provider, you return the CacheDecorator itself. It seems that in order to add an additional service (such as a logger), you would have to extend the CacheDecorator (since it adds an additional level). If you extend the AbstractUserDecorator, you would be able to return EITHER the Cache or Logger decorator, but not both.

    Additionally, if your AbstractUserDecorator is an exact one-to-one “pass-through” for the User Repository, I don’t see the point of it. You could just extend your decorators from the User Repository itself.

    Thanks a lot.

    • You would create a LoggerDecorator and then wrap the CacheDecorator in the Service Provider with the LoggerDecorator. For each additional decorator you just add another layer to the onion.

      The point of the decorator pattern is that you don’t extend the functionality of a class, you instead wrap it to add functionality. Extending a class often has undesired side effects, but with the decorator pattern you can choose what functionality to add at run time.

      Does that make sense?

      • LearningLaravel

        Here’s how my understanding is. Take a look at this service provider:

        $this->app->bind(‘CribbbRepositoryUserUserRepository’, function($app)
        {
        $user = new EloquentUserRepository(
        new User,
        $app->make(‘CribbbRepositoryPostPostRepository’)
        );

        $cache = new CacheDecorator(
        $user,
        new LaravelCache($app[‘cache’], ‘user’)
        );

        $logger = new LoggerDecorator(
        $cache,
        new LaravelLogger
        );

        return $logger;

        });
        Did I get that right? In the logger class, all “higher” level calls will be to cache class, and from the cache to Eloquent. This way, if the log or cache decorator doesn’t have all the methods, they would still all be there because they extend the AbstractDecorator, which does implement all of them.

        And lastly, what are the undesired side effects you speak of if extending from the Repository directly? It seems that I would be able to extend both Logger and Cache decorators straight from the Repository without a problem.

        Thanks for your help.

        • Yeah that looks right to me.

          Well, the fact that your repository can log stuff, or can cache stuff has nothing to do with the fact that it is a repository. It has no business knowing any of those details.

          There are many undesired effects of not using the Decorator pattern in this example. For example, imagine you extended the repository with the cache and then extended the cache with the logger, but then later you didn’t want the cache. You would have to rewrite all of your classes.

          Or perhaps you want an instance that that doesn’t have the cache, but does have the logger.

          By forcing the inheritance you are tightly coupling yourself to that structure, when really, you want to be able to “decorate” on the fly.

          • LearningLaravel

            Interesting. Perhaps that’s not exactly what I meant. The service provider could actually be exactly the same. You would pass EloquentRepository into the CacheDecorator construct, and the CacheDecorator into the Logger construct. Perhaps there’s no need for the AbstractUserRepository?

            The UserCacheDecorator could stand on its own, and so could the UserLoggerDecorator — they would not extend anything (why should they?). My main question here is the purpose of AbstractUserRepository, as it doesn’t seem to serve any purpose.

          • LearningLaravel

            Actually, after posting this, I realized that the AbstractUserRepository could be simply used as an interface in case any of the decorators don’t override one of the methods. Is that the case? Is there any other reason?

          • Ah I see what you mean! Yeah that’s basically it, it just provides a blueprint for how the decorators should be written.

          • LearningLaravel

            Thanks for taking the time to respond!

            Another question has come up regarding the service-repository pattern: in the Eloquent Repository, I often need to do a simple find($id) to get one row, then perform some other operations, like getting relations or checking if a user is active. However, I want to use DRY and not repeat the find() calls all the time in my methods. My question is, what should I do if I want to call one eloquent method from another one? If the result of the called method is cached in the Cache Decorator, I would want to use it instead.

            Right now, I’m thinking to inject the UserRepository even into the EloquentUserRepository (creating a sort of loop), and perform calls to that instead of to the same class, but I don’t know if that’s good practice. I would call the find($id) method in the UserRepository, which would first check the cache, then use the Eloquent class to get the answer. Hopefully that makes sense.

            Thanks.

          • LearningLaravel

            I just realized that my solution is not possible, since it creates an endless loop, Repository -> Cache -> Eloquent -> Repository -> Cache -> etc.

            How do I go about doing this?

          • Hmm, I’m not really sure. I wouldn’t worry about being strictly DRY though. Sometimes repetition is better than an over-complicated solution.

          • LearningLaravel

            In this situation though, it’s not good to repeat yourself because
            the extra find() call actually means hitting your database multiple
            times–with the exact same query.

            What I ended up doing was calling the get() method from the CacheDecorator in the same clasee, which subsequently called find() in the EloquentRepository, or retrieved from the cache if it was already there. Then I passed the Model into another related EloquentRepository call.

            Hopefully that makes some sense.

          • Ah, I think I see what you mean. I think this all sounds too complicated for me haha :p

          • Yeah that’s basically it :)

  • karan

    Hey I want to get one thing straight. i am new to all this. All “UserRepository” methods need to be reimplemented(even though just a line) in “AbstractUserDecorator”. Is that right? So every new repo will need to make a new Abrstract Decorator.

    If the above is true then why dont you just use the User “CacheDecorator” class and declare “__call()” which calls the missing methods on UserRepository instead?

    • I think you are missing the point of the Decorator Pattern. Each layer adds some additional functionality to the underlying object.

    • LearningLaravel

      That would work if you ONLY had the CacheDecorator, and no other ones. If you wanted to add an additional decorator, you’d have to remove that __call() method and implement it as shown here.

      • ka

        See the gist. https://gist.github.com/karanits/44c79235063b0c522cd3
        i have try to explain. Maybe I am wrong
        Thanks

        • ka

          Just noticed that this may hinder resolving of repo interfaces in their controllers.

          • AllTheCode

            Did you figure out a good way to do this since it doesn’t resolve the interface? Only way I can think of is making a blank interface, which is kind of pointless. But I do want to use the __call() method to make it easier…

        • Hmm, yeah, I guess that could work (without really thinking through the implications). If that works for you, then you should do it. There’s definitely not one right way to do everything.

  • Pingback: Multi-Tenancy in Laravel 4 | Culttt()

  • Leon

    If I wanted to grab some users with either all() or find() without checking the cache, what would be the best way to do this?

    Also what would be the best way to invalidate all() cache?

    Thanks!

    • You could just create an instance of the repository that is not wrapped in the cache decorator. That’s the beauty of using the decorator pattern, the extra layers don’t have to change the underlying object.

      It would probably be a bit awkward to resolve it out of the IoC container though. I’m not really sure what the best way of doing that would be or what structure you should use. I’d experiment to try and see what feels right.

      • Robert B

        I just ran into this sort of issue tonight. Running commands via artisan, I didn’t want the cached results of my project queries. The easiest method I found was altering the CacheProjectDecorator and adding a public method setPass($value = false). This way, in my command code, I could tell my cache decorator whether I wanted a cached result or not (if one exists).

        // Return non-cached
        $this->project->setPass(true);
        $this->project->find($id);

        // Return cached
        $this->project->setPass();
        $this->project->find($id);

        By default, the protected value is set to false so I only need to reset it when I use it and not effect other code.

        Perhaps there is a better way, but a quick fix I needed for a presentation Monday :)

  • Leon

    You would need to use parent::find($id) wouldn’t you, otherwise you are skipping over the other nested implementations? If you had 2 decorators?

    • Yeah, you could do that. I meant, resolve an instance, but then only wrap it in the decorators you wanted.

  • how i can start the service? and how i can get the cached data?

    • You resolve it out of the IoC container. The data you return from the repository will automatically be the cached data so you can continue using the repository as normal.

  • Hisham Aburob

    I liked this but some people say this is over engineer! I actually disagree with them.

  • pen

    Hello Philip,

    First of thanks for all this tutorials:P

    Sorry for my dump question but i am quite new in programming .

    Your AbstractUserDecorator implements RepositoryInterface, UserRepository. Can you implement a repository ? i got confused:P