Error is:
Serialization of 'Closure' is not allowed
Error at:
.../vendor/laravel/framework/src/Illuminate/Cache/RedisStore.php:295
Throws when remembering forever on Cache for the first time.
After second try (when reloading browser) it works as it should work.
public function cache()
{
$task = $this;
return Cache::rememberForever('apply:' . $task->apply->slug . ':' . $task->slug, function () use ($task) {
return $task;
});
}
Interesting part is this. So it works on caching $apply on Apply's index page. (The code is the same)
Note: This issue is related to Redis directly. Please don't mention old questions about serialization. You can check official Laravel 6.x documentation too. Everything is added related to it: https://laravel.com/docs/6.x/cache#retrieving-items-from-the-cache
I fixed it by manually storing and returning data if it exists on cache (how rememberForever() should be work).
public function cache () {
$slug = 'task:'.$this->slug;
if(Cache::has($slug)) return Cache::get($slug);
if(!Cache::put($slug, $this)) throw new ProtocolException(1045);
return Cache::get($slug);
}
Related
I am trying to store the last run time of a scheduled job in Laravel. However, the cache is not updating the date. I want the cache to be remembered until the function is called again.
public function setLastRun() {
Cache::forget('last_automation_api_run');
Cache::rememberForever('last_automation_api_run', function () {
return now()->toDateTimeString();
});
}
You should use remember and forget method in different functions.
public function getLastRun() {
return \Cache::rememberForever('last_automation_api_run', function () {
return now()->toDateTimeString();
});
}
public function forgetLastRun() {
\Cache::forget('last_automation_api_run');
}
Every time you delete the cache before fetching cache values makes, logically incorrect.
And you have to return the values coming from rememberForever cache method.
If you're using a clustered cache then there's a chance the first change hasn't propagated through the cache when you make the 2nd one. If that is the case (or generally for what you're doing) you can try the following:
public function setLastRun() {
Cache::put('last_automation_api_run', now()->toDateTimeString());
}
this should mindlessly overwrite the current value rather than deleting and readding it.
In my laravel app, I noticed that every route is executed twice, and can't figure out why
for example:
Route::get('called_twice', function () {
dump('---');
});
return string '---' twice
Edit:
trying to backtrace the source of the issue, I put a dump in file
src/Illuminate/Foundation/Http/Kernel.php
protected function sendRequestThroughRouter($request)
{
$this->app->instance('request', $request);
Facade::clearResolvedInstance('request');
$this->bootstrap();
dump('kernel');
return (new Pipeline($this->app))
->send($request)
->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)
->then($this->dispatchToRouter());
}
and another dump in the constructor of the file
src/Illuminate/Pipeline/Pipeline.php
public function __construct(Container $container = null)
{
dump('pipeline');
$this->container = $container;
}
and I get this:
the Pipeline class is called many time
Laravel 6.8.0
I think $next($request) is probably called twice in a middleware. The reason is that the response is passed throught each middleware (pipes) before it is returned back.
So if $next($request) is called twice in one middleware it is normal that all pipes will be called again.
Found mine in the master. there was a script that was causing the page to reload in the background.
I built a little counter with admin access only and smoked it out. Came down to one script.
I've created an API using Laravel and I'm trying to find out how to cache Eloquent models. Lets take this example as one of the API endpoints /posts to get all the posts. Also within the method there are various filter options such as category and search and also gives the option to expand the user.
public function index()
{
$posts = Post::active()->ordered();
if (Input::get('category')) $posts = $posts->category(Input::get('category'));
if (Input::get('search')) $posts = $posts->search(Input::get('search'));
if ($this->isExpand('user')) $posts = $posts->with('user');
$posts = $posts->paginate($this->limit);
return $this->respondWithCollection($this->postTransformer->transformCollection($posts->all()), $posts);
}
I have been reading up and found in Laravel 4 you could cache a model like this
return Post::remember($minutes);
But I see this has been removed for Laravel 5.1 and now you have to cache using the Cache facade, but is only retrievable by a single key string.
$posts = Cache::remember('posts', $minutes, function()
{
return Post::paginate($this->limit);
});
As you can see, my controller method contains different options, so for the cache to be effective I would have to create a unique key for each option like posts_cagetory_5, posts_search_search_term, posts_category_5_search_search_term_page_5 and this will clearly get ridiculous.
So either I'm not coming across the right way to do this or the Laravel cache appears to have gone backwards. What's the best solution for caching this API call?
As the search is arbitrary, using a key based on the search options appears to be the only option here. I certainly don't see it as "ridiculous" to add a cache to for expensive DB search queries. I may be wrong as I came by this post looking for a solution to your exact problem. My code:
$itemId = 1;
$platform = Input::get('platform'); // (android|ios|web)
$cacheKey = 'item:' . $itemId . ':' . $platform;
$item = Item::find(1);
if( Cache::has($cacheKey) ) {
$result = Cache::get($cacheKey);
} else {
$result = $this->response->collection( $item, new ItemTransformer( $platform ) );
Cache::tags('items')->put($cacheKey, $result, 60); // Or whatever time or caching and tagged to be able to clear the lot in one go...
}
return $result;
I realise that my example has less complexity but it seems to cover all the bases for me. I then use an observer to clear the cache on update.
I have a problem with output buffering in laravel 4.
This code works good in other frameworks but in laravel i get fatal error for ob_get_flush()
class Ajax
{
public function __construct()
{
if ( Request::ajax() )
{
ob_clean();
ob_start(function(){});
register_shutdown_function(array(&$this,'setOutput'));
}
}
public function setOutput()
{
$html = ob_get_flush();
}
}
error :
ob_get_flush(): failed to delete and flush buffer. No buffer to delete or flush
Looks like you are trying to flush before you ob_start()ed.
It's "just" a Notice, not an Error. Your buffer content is empty, so PHP (through laravel) sends you a notice because it has nothing to do with ob_get_flush. Maybe notices are disabled in other frameworks you tried. According to this answer, you can do something like this, if you want to make it work even if your buffer is empty:
public function setOutput()
{
if (ob_get_level() > 1) $html = ob_get_flush();
}
Hope it will help !
Is it possible that the class is being called before Request::ajax() can return true?
If so then your constructor conditional would return false and ob_start would not be called. Perhaps you can move that part out of the conditional or try rewriting it to where you write the data to the object and then call renderOutput() and this method would have your ob calls in the proper order.
I'm following Dayle Rees' book "Code Bright" tutorial on building a basic app with Laravel (Playstation Game Collection).
So far so good, the app is working but, following his advices at the end of the chapter, I'm doing my homeworks trying to improve it
So, this snippet is working fine for existing models but throws an error if the item doesn't exists:
public function edit(Game $game){
return View::make('/games/edit', compact('game'));
}
In other words, http://laravel/games/edit/1 shows the item with ID = 1, but http://laravel/games/edit/21456 throws an error since there's no item with that ID
Let's improve this behaviour, adapting some scripts found also here on StackOverflow (Laravel 4: using controller to redirect page if post does not exist - tried but failed so far):
use Illuminate\Database\Eloquent\ModelNotFoundException; // top of the page
...
public function edit(Game $game){
try {
$current = Game::findOrFail($game->id);
return View::make('/games/edit', compact('game'));
} catch(ModelNotFoundException $e) {
return Redirect::action('GamesController#index');
}
}
Well... nothing happens! I still have the error with no redirect to the action 'GamesController#index'... and please notice that I have no namespaces in my Controller
I tried almost anything:
Replace catch(ModelNotFoundException $e) with catch(Illuminate\Database\Eloquent\ModelNotFoundException $e): no way
put use Illuminate\Database\Eloquent\ModelNotFoundException; in Model instead of Controller
Return a simple return 'fail'; instead of return Redirect::action('GamesController#index'); to see if the problem lies there
Put almost everywhere this snippet suggested in Laravel documentation
App::error(function(ModelNotFoundException $e)
{
return Response::make('Not Found', 404);
});
Well, simply nothing happened: my error is still there
Wanna see it? Here are the first two items in the errors stack:
http://www.iwstudio.it/laravelerrors/01.png
http://www.iwstudio.it/laravelerrors/02.png
Please, can someone tell me what am I missing? This is driving me mad...
Thanks in advance!
Here are few of my solutions:
First Solution
The most straightforward fix to your problem will be to use ->find() instead of ->findOrFail().
public function edit(Game $game){
// Using find will return NULL if not found instead of throwing exception
$current = Game::find($game->id);
// If NOT NULL, show view, ELSE Redirect away
return $current ? View::make('/games/edit', compact('game')) : Redirect::action('GamesController#index');
}
Second solution
As I notice you may have been using model binding to your route, according to Laravel Route model binding:
Note: If a matching model instance is not found in the database, a 404 error will be thrown.
So somewhere where you define the model binding, you can add your closure to handle the error:
Route::model('game', 'Game', function()
{
return Redirect::action('GamesController#index');
});
Third Solution
In your screenshot, your App::error seems to work as the error says HttpNotFound Exception which is Laravel's way of saying 404 error. So the last solution is to write your redirect there, though this apply globally (so highly discouraged).