Caching strategies in MVC Framework?

2020-06-23 13:34发布

I wrote my own little PHP MVC Framework, and now Im exploring caching strategies in PHP MVC Frameworks. Im thinking about what can be cached, where and how.

The framework I have is simple MVC Framework. I have front controller, that boots up application, registers class auto loading, sets up php run time directives... and at the end analyses URL and dispatches request to appropriate controller, method, action controller, how ever you want to call it. From controller, I have access to Domain Objects, and Data Mappers that can persist Domain Objects to some storage, most of the time Relation Database. From Controllers I have access to Domain Objects and Data Mappers.

So as far as caching goes these are the things I can things I know I can do at the moment. With PHP I can use APC Cache that is opcode cache, but I can also use it to save variables into RAM. Then I can use Memcache and Memcahed that works joust as APC cache but I can access stored cache from different servers If I have to scale. And those two are not opcode caches.

As far as I know I can do these things:

  1. When in controllers, I can save Domain Objects into cache, so I dont have to open connection to database every time, if I already have that Domain Object in cache.

  2. I can build my cache system, that would analyze URLs at bootstrap, and then get already interpreted page for that URL if cache with that page URL exists, if not it would process request and then save that page into cache and associate it with current URL

So, as you can see I dont really know how to implement cache in my MVC, and where should I cache things, how, and what possibilities exists.

So can someone explain this better, or redirect me to some good articles where I could learn about cacheing?

Thanks!

1条回答
来,给爷笑一个
2楼-- · 2020-06-23 14:20

The opcode cache is there to offset the cost of interpreting your PHP code for each request. It's related to server infrastructure. Kinda like load balancing. Leave it to your admin(s). Or someone who has used *NIX distro, that is not ubuntu.

In an MVC application there are 3 points where you can cache stuff:

  • periphery:

    Parts of application that are not really related to MVC pattern itself, but are involved in getting to MVC: routing mechanism and (if you use it) DIC.

    What you can cache for routing mechanisms kinda depends on implementation. If you are using some regexp generation from more readable patterns, then you can cache to produced expressions. And also it is possible to cache part of parameters that would be normally produced by route. Both of those are reasonable in medium/large sites and completely pointless for small ones.

    If you decided to use DIC (personally I think that it is an antipattern, but all the cool kids disagree), then caching is almost mandatory, because correctly written DIC will utilize reflections. And reflections are slow.

  • response

    Sometimes there are parts of application, that require lot of resources to create. If your MVC interpretation has a fully realized View, then it is possible to cache some of the templates, which are used for generating the output.

    For example, take site like StackOverflow. If you decided to create "top tags in past 24 hours" block on the sidebar it would be impossible to regenerate that for each page-view. One way of getting around this limitation would be to recount the tags only each hour or so and store the generated result in a HTML fragment. This fragment can then be reused over an over again. If the cached fragment is some JSON used by XHR, you can even add client-side expire header to decrease server load even more.

    You can cache either only fragments of page or the whole thing. This is basically how in a site with MVC-imbued architecture one deals with parts that have static content.

  • model layer

    This is the tricky bit.

    First of all you have to understand that cache is just another form of storage, which means that caching is handled by special mappers.

    $user = new User;
    $cache = new UserCacheMapper;
    
    $user->setId( 42 );
    if ( ! $cache->fetch( $user ) )
    {
        $storage = new UserDbMapper( $pdo );
        $storage->fetch( $user );
    
        $cache->store( $user );
    }
    
    // the $user object has been initialized
    

    The cache mapper is also the place where invalidation of cache would happen and this way you can add the caching mechanism at any stage of project.

    Though, I would recommend to stop using controllers for handling the interaction between domain objects and storage. You are basically leaking the domain business logic in the presentation layer. I would recommend to create services that contain this part of application and let you isolate controllers from the domain logic.

查看更多
登录 后发表回答