27

Everytime when I change something in templates I have to clear cache manually. Is there some way to disable templates caching in development mode?

Antonio Carlos Ribeiro
  • 86,191
  • 22
  • 213
  • 204
wino
  • 271
  • 1
  • 3
  • 3
  • Are you referring to Blade? You shouldn't have to clear the compiled views as if you change a view Blade will re-compile it. – Jason Lewis Jun 07 '13 at 00:59
  • Yes. I'm using blade. I don't see changes when I updating someting in templates. I have to remove cache files from app/store/views directory manually. – wino Jun 07 '13 at 05:40
  • 14
    It's my fault. PhpStorm by default preserves files timestamp after upload. – wino Jun 11 '13 at 18:52
  • I (*think I*) had a similar need to disable the view caching, in the case where I was working on a blade extension. Altering the Blade::extend code didn't cause the view cache to refresh. – Dustin Graham Aug 05 '13 at 22:33
  • @wino Try this: http://stackoverflow.com/questions/20579182/laravel-and-view-caching-in-development-cant-see-changes-right-away – Volatil3 Jan 14 '14 at 14:24
  • There are cases when you want to edit another thing than the blade template, for example the return value of a directive. It's when compilation is annoying during dev, as directive substitution is cached (which is useful in prod). – Dereckson Jul 02 '16 at 13:12

9 Answers9

12

If you are using PHP5.5, then I would suggest configuring opcache in php.ini

opcache.revalidate_freq=0

This value sets the time frequency when views should be updated from cache. This value is usually 60 seconds or so. Setting it to 0 will make your cache update every time.

ek9
  • 3,392
  • 5
  • 23
  • 34
7

According to this request, change your application cache driver to array for the local environment.

Vikas Khunteta
  • 1,394
  • 1
  • 14
  • 15
6

I used the solution of "Gadoma" some times. But since there is not "filters.php" in Laravel 5 anymore, here is my middleware class for the newest Laravel version:

<?php
namespace App\Http\Middleware;

use Closure;
use Illuminate\Contracts\Routing\Middleware;

class CacheKiller implements Middleware {

    /**
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {

        $cachedViewsDirectory = app('path.storage').'/framework/views/';

        if ($handle = opendir($cachedViewsDirectory)) {

            while (false !== ($entry = readdir($handle))) {
                if(strstr($entry, '.')) continue;    
                @unlink($cachedViewsDirectory . $entry);    
            }

            closedir($handle);
        }

        return $next($request);

    }

}

And in your Kernel.php:

protected $middleware = [
        ...
        'App\Http\Middleware\CacheKiller',
    ];

Not the nicest solution but it works.

Simon Schneider
  • 1,216
  • 1
  • 15
  • 23
  • 2
    Change cache driver to array for the local environment. – Emeka Mbah Apr 15 '15 at 09:11
  • I had to remove `... implements Middleware`. By the way, when I set the cache driver: `CACHE_DRIVER=array`, view cache files continued to be written to: framework/views/. I would still prefer a solution that doesn't affect every request. This works for the time being. Thank you. :) – Larry Eitel May 19 '15 at 16:46
  • I added to local dev .env the following: `ENABLE_MIDDLEWARE_KILL_VIEWS_CACHE=true` And then in the middleware: public function handle($request, Closure $next) { // added this block if (!env('ENABLE_MIDDLEWARE_KILL_VIEWS_CACHE')) { return $next($request); } – Larry Eitel May 19 '15 at 16:59
4

It looks that blade are using file timestamp for rebuilding pages.

So if pages are not directly updated by blade there are several options :

1 - If you are working by FTP or other remote protocol you may have the date mismatching on the two OS. Try to put your client in the future or the server in the past (few seconds is enough).

Reminder : for linux based os, a simple date --set works, for example date --set 18:30:00 for 18h30 pm.

2 - (Repost wino comment) You client may does not update the timestamp of your edited file. You have to edit the configuration of your IDE.

Ifnot
  • 4,914
  • 4
  • 33
  • 47
  • This worked, thanks! For me, I was using phpStorm (to sync the files using sftp) and I had to both set the `opcache.revalidate_freq=0`and also set the server date/time to be behind my client as you suggested. – prograhammer Mar 09 '15 at 16:11
  • In fact for using FTP access between two OS the date and time makes difference when renewing the cache. As access to the virtual machine by PhpStorm was generating this problem, I changed the date of the VM and it worked. – vandersondf Nov 11 '16 at 12:32
4

It's harder to debug when I don't really understand your configuration. All I can offer as help is instead of deleting the view cache directly you can run:

$ php artisan cache:clear

You could probably add a process (depending on your OS) to listen for file changes and automatically run the command.

Neo
  • 876
  • 1
  • 9
  • 25
2

In laravel 5.2: Create a new middleware, add to 'web' $middlewareGroups in Kernel.php. This will call the artisan command to clear all compiled view files.

namespace App\Http\Middleware;

use Artisan;
use Closure;

class ClearViewCache
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        if (env('APP_ENV') === 'local') {
            Artisan::call('view:clear');
        }

        return $next($request);
    }
}
CodeMouse92
  • 6,840
  • 14
  • 73
  • 130
Taylor
  • 443
  • 3
  • 9
1

You can try this route filter, setting the cache time to 0, that way your view will be recreated on every request :)

From this gist,

Route::filter('cache', function( $response = null )
{

    $uri = URI::full() == '/' ? 'home' : Str::slug( URI::full() );

    $cached_filename = "response-$uri";

    if ( is_null($response) )
    {
        return Cache::get( $cached_filename );
    }
    else if ( $response->status == 200 )
    {
        $cache_time = 30; // 30 minutes

        if ( $cache_time > 0 ) {
            Cache::put( $cached_filename , $response , $cache_time );
        }
    }

});

Hope this helps you out, but I didn't test it so I cant guarrantee it'll work.

Pranav 웃
  • 8,469
  • 6
  • 38
  • 48
Gadoma
  • 6,475
  • 1
  • 31
  • 34
1

Just put this somewhere in your app:

if (env('APP_DEBUG')) ini_set('opcache.revalidate_freq', '0');
Rafael Beckel
  • 2,199
  • 5
  • 25
  • 36
  • As @edvinas.me said, you need PHP 5.5+ to use it. For more information, see [This Question](http://stackoverflow.com/questions/17224798/how-to-use-php-opcache) – Rafael Beckel Apr 13 '15 at 19:48
0

Some additional caching issues from a PHP 5.3 to PHP 5.5 upgrade avaliable here: Laravel and view caching in development -- can't see changes right away

Community
  • 1
  • 1
Tim Ogilvy
  • 1,923
  • 1
  • 24
  • 36