We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

Caching minified view

I'm implementing a per page cache. I'm minifying rendered HTML in a view:afterRenderView event. When caching, this event is however not fired, so that the cached pages are not minified.

How do I get the cached pages to be minified?

I have things implemented like this:

The page caching happens in a class called from Controller->beforeExecuteRoute(), and looks like this:

            $pageCacheId = $sectionName.'-'.$pageAction.'.html';
            $view->cache( ['key' => $pageCacheId] );
            // Check for a cached version of this page
            if ($view->getCache()->exists($pageCacheId)) {
                return;
            }

My minify code is in the services.php file, in $di->set("view", function () use ($config, $di) { .... }:

        // Minify after rendering view
        $eventsManager = $di['eventsManager'];
        $eventsManager->attach("view:afterRenderView", function($event, $view) {
            $content = $view->getContent();

            // Remove spaces at start of lines, and empty lines
            $content = preg_replace('/\r?\n\s*(\r?\n)?/', "\n", $content);
            // Remove xhtml endings
            $content = str_replace(' >', '>', str_replace('/>', '>', $content));

            $view->setContent($content);
        });
        $view->setEventsManager($eventsManager);

(I'm using Phalcon 2.0.9, Windows for development, Linux for production.)

I haven't gotten to the stage yet where I need to turn on view caching but I think you'd have to call the View's cache function in your afterRenderView-event once you've minified it:

$view->cache(
    array(
        "lifetime" => 86400,
        "key"      => "yourkey"
    )
);

I'm not sure how you would get access to the key you generate in the first part of your code though.



2.5k

Actually, the particular caching code needs to be before the view starts rendering. It needs to be able to prevent the view rendering process from starting, so as to serve a cached version of the page instead.

Phalcon's view cache system apparently stores a page's HTML in a particular event, that happens before view:afterRenderView. I might be able to get this to work, if I could change the event where that happens, or move the minification code to an event before that. I tried having the minification code in the view:afterRender event, but that didn't help.

I wasn't able to find a list of view events. Anyone knows where it is in the documentation?

By the particular caching code you mean the code that checks if the cache exists ($view->getCache()->exists($key)) and not the generating of the cache itself right?

This example app uses the caching system: https://github.com/phalcon/php-site. Just take a look at the App controllers and you'll see the caching happens in the controller actions, not in the beforeExecuteRoute event.

Where in your code do you call $view->render()? And if you call $view->getContent() after that, is that minified? If it is, call the $view->cache function after $view->render() and be sure to remove $view->cache from the beforeExecuteRoute function.



2.5k

Burt, have you actually worked with Phalcon's build-in cache generation classes? I do the cache generation with these. They're set in the services.php like this:

    use Phalcon\Cache\Frontend\Output as OutputFrontend;
    use Phalcon\Cache\Backend\File as BackFile;

    $di->set('viewCache', function () use ($config) {
        $frontCache = new OutputFrontend(
            array(
                "lifetime" => 86400
            )
        );

        $cache = new BackFile(
            $frontCache,
            array(
                "cacheDir" => $config->application->cacheDir,
                "prefix"   => "page-"
            )
        );

        return $cache;
    }, true);

I do have reasons for using the Controller->beforeExecuteRoute() event, you know, I do lots of things there. Loading various route dependent config files, setting up View variables, handling 404's, etc. And cache handling. These are needed when things happen in the Controller action.

I have no need to call $view->render() in my code, actually. Minification works fine.

No, I haven't. I plan on messing with them this weekend as your question has made me curious so hopefully I can add something more constructive afterwards.

My setup differs a lot from yours though, I render my views using the $view->render() function and then handle it's output manually after that.



2.5k

I use Volt as a templating engine. I suppose that does away with the need to use $view->render().

I wrote a separate caching class, that is called from /public/index.php. It bypasses most of the framework when there's a cache hit. It only needs the config, and not the class loader, services, and Application class.

This sort of solves my problem, and is faster than using Phalcon's built-in caching. But it's not a very neat way to do it, and I must improvise things like logging.

I use Volt as well. I implented cache yesterday and it works for me, more or less. Your original post is right in that caching doesn't take the after-events into account, which is a shame. I looked up the render function in the Zephir code: https://github.com/phalcon/cphalcon/blob/master/phalcon/mvc/view.zep. The way to get around it seems to be to create the cache manually at a stage in your code where the view's content is available in the state that you want it.

I was using a single view object to render multiple Volt templates in one action and found that it caches the first time you call render. I ended up creating two separate view objects, one with caching enabled, the other one without and only rendering the final view in the view object that has caching enabled. Still not satisfied but it works for now and I need to focus on some more important features first :)