Migrating to Laravel 5, route:cache throwing exception - laravel

Moving from Laravel 4.2 to 5.0
We have about ~200 routes in our API, most of them were Closures. So I've spent the better part of the last couple days converting them all to controller routes. Everything is back to being stable, but when I try to run php artisan route:cache it throws an exception
[Exception]
Serialization of 'Closure' is not allowed
I did a ctrl+f for function, and the only ones left in the routes file are the two Route::group entries (which, yes, are closures...but surely only routes count...).
Any guidance? After the tediousness of the last two days, this error is...not what I wanted to see.
EDIT: Full stacktrace
Route cache cleared!
[Exception]
Serialization of 'Closure' is not allowed
Exception trace:
() at C:\Users\cjtho_000\Desktop\ecapi_l5\vendor\laravel\framework\src\Illuminate\Foundation\Console\RouteCacheCommand.php:95
serialize() at C:\Users\cjtho_000\Desktop\ecapi_l5\vendor\laravel\framework\src\Illuminate\Foundation\Console\RouteCacheCommand.php:95
Illuminate\Foundation\Console\RouteCacheCommand->buildRouteCacheFile() at C:\Users\cjtho_000\Desktop\ecapi_l5\vendor\laravel\framework\src\Illuminate\Foundation\Console\RouteCacheCommand.php:65
Illuminate\Foundation\Console\RouteCacheCommand->fire() at n/a:n/a
call_user_func_array() at C:\Users\cjtho_000\Desktop\ecapi_l5\vendor\laravel\framework\src\Illuminate\Container\Container.php:523
Illuminate\Container\Container->call() at C:\Users\cjtho_000\Desktop\ecapi_l5\vendor\laravel\framework\src\Illuminate\Console\Command.php:115
Illuminate\Console\Command->execute() at C:\Users\cjtho_000\Desktop\ecapi_l5\vendor\symfony\console\Symfony\Component\Console\Command\Command.php:257
Symfony\Component\Console\Command\Command->run() at C:\Users\cjtho_000\Desktop\ecapi_l5\vendor\laravel\framework\src\Illuminate\Console\Command.php:101
Illuminate\Console\Command->run() at C:\Users\cjtho_000\Desktop\ecapi_l5\vendor\symfony\console\Symfony\Component\Console\Application.php:874
Symfony\Component\Console\Application->doRunCommand() at C:\Users\cjtho_000\Desktop\ecapi_l5\vendor\symfony\console\Symfony\Component\Console\Application.php:195
Symfony\Component\Console\Application->doRun() at C:\Users\cjtho_000\Desktop\ecapi_l5\vendor\symfony\console\Symfony\Component\Console\Application.php:126
Symfony\Component\Console\Application->run() at C:\Users\cjtho_000\Desktop\ecapi_l5\vendor\laravel\framework\src\Illuminate\Foundation\Console\Kernel.php:94
Illuminate\Foundation\Console\Kernel->handle() at C:\Users\cjtho_000\Desktop\ecapi_l5\artisan:36
EDIT 2: removed the route groups to test, still throws the exception

Turns out, the entirely unhelpful error message was trying to tell me that I had a duplicate route (copy paste error, I had two get routes matching the same uri).
Removing the duplicate fixed the issue.

Per your stack trace,
vendor\laravel\framework\src\Illuminate\Foundation\Console\RouteCacheCommand.php:95
serialize() at vendor\laravel\framework\src\Illuminate\Foundation\Console\RouteCacheCommand.php:95
Laravel is trying to serialize the routes collection on line 95 of RouteCacheCommand.php.
The error you're getting
Serialization of 'Closure' is not allowed
looks like its PHP's standard "someone tried to serialize an anonymous function" exception message (vs. it might be a custom Laravel exception).
All this means something is adding an anonymous function (i.e. "closure") to your route collection. If you're 100% sure you've removed them all from routes.php, my guess would be the route's in third party code somewhere.
It's best not to guess. Try some debugging code that's something like the following
//un-tested pseudo debugging code
//get the application's routes, using the same
//technique as the route:cache command
$app = require /path/to/your/laravel/bootstrap/app.php';
$app->make('Illuminate\Contracts\Console\Kernel')->bootstrap();
$routes = $app['router']->getRoutes();
//go through each route
foreach($routes as $route)
{
//if the route is a closure
if(is_object($route) && ($route instanceof Closure))
{
//use reflection to find out which file the closure is defined in
$r = new ReflectionFunction($route);
var_dump($route->getFileName ());
}
}
This will let you figure out where the closure that's causing your problems is defined, which should be enough to point to the problem.

Related

Laravel - Non-static method should not be called statically

I have recently started using laravel for work and I boumped into many issues I cannot stil solve.
I have looked over many many topics and already anwered questions but none of those have helped me with my issue
So, I get this error trying to do 'php artisan serve'
"Non-static method Illuminate\Cache\RateLimiter::for() should not be called statically"
So I went up looking at the code, this is the RateLimiter.php code that gives me the error
protected function configureRateLimiting()
{
RateLimiter::for('api', function (Request $request) {
return Limit::perMinute(60)->by(optional($request->user())->id ?: $request->ip());
});
}
the error is at the 2nd line of this code, in the RateLimiter:: etc
I get those errors in the CMD
app/Providers/RouteServiceProvider.php:59
Illuminate\Foundation\Bootstrap\HandleExceptions::handleError("Non-static method Illuminate\Cache\RateLimiter::for() should not be called statically", "myPathToTheProject/app/Providers/RouteServiceProvider.php", [])
app/Providers/RouteServiceProvider.php:38
App\Providers\RouteServiceProvider::configureRateLimiting()
the function is called like this
$this->configureRateLimiting();
hoping you can help me, I will give more infos if are needed
I found out the problem. You need to import the facade, and when you auto-import, it tends to get the wrong package.
Look at the imports. If you find:
use Illuminate\Cache\RateLimiter;
You should replace with
use Illuminate\Support\Facades\RateLimiter;
Worked for me!

Laravel memcached errors after random time

Hello I am using memcached in laravel application 5.8.
After some time the error is:
production.ERROR: Invalid argument supplied for foreach()
Code in controller is:
$page = \Request::get('page', '0');
Cache::tags('posts')->remember('page-'.$page, 15, function(){
return Post::orderBy('created_at', 'desc')
->paginate(20);
});
$posts = Cache::tags('posts')->get('page-'.$page);
The error comes, because of the #foreach loop in the view.
When I get the error, I can fix it by restarting the server, but this is not really a good solution. How can I prevent this issue and still use memcached?
I am sure that it comes from the cache, because if I change the cache driver to array than the error is gone.
Update:
So I have tried to change from remember to rememberForever in controller, but the problem remains. It errors and only solution is to turn off cache or reboot server. Otherwise it is giving me production.ERROR: Invalid argument supplied for foreach().

Laravel: How to run a Library in background (Process component)

I'm trying to create a program which generates event dates for the whole year. The program works if the user select few events but if the user select 100+ events and assigned them every week it reaches the Maximum execution time error.
In order to fix this, my idea is to run the program in the background.
I'm using Laravel 5.4, running the script below will call the function
$process = new Process('php -f '.$path.' generate_evnt_prepared ' . $content['evntid']);
$process->run();
Function Script
namespace App\Library\shellexec;
use App\Model\V1\EvntPlanDtl;
use App\Model\V1\EvntPlanDtlPrePo;
use Carbon\Carbon;
class RoutePlan {
//put your code here
public function process($method = null, $param = 0)
{
$this->$method($param);
}
I'm pretty sure that the function is called as I'm getting an error in error_logs that the Models are not found
PHP Fatal error: Class 'App\Model\V1\EvntPlanDtl' not found in C:\xampp\htdocs\rdmsoffice\app\Library\shellexec\EventPlan.php on line 30
PHP Stack trace:
PHP 1. {main}() C:\xampp\htdocs\rdmsoffice\app\Library\shellexec\EventPlan.php:0
PHP 2. App\Library\shellexec\EventPlan->process() C:\xampp\htdocs\rdmsoffice\app\Library\shellexec\EventPlan.php:88
PHP 3. App\Library\shellexec\EventPlan->generate_evnt_prepared ()
Anyone knows how to fix this? I'm open to suggestions if this is the wrong way.
Big thanks!
Sounds like a more scalable way is to create a "chunked" version and fire them into a queue for processing. For example, based off some assumptions about the example you provided, I might suggest one firing one queued message for each Event the user selects.
That adds some overhead to manage, but honestly I've always found it's more effective to take some of that cost up front and do it right, rather than finding workarounds like increasing settings or (shudder) shelling out to sub processes.

How to have usefull debugging or error messages from laravel

I'm a bit new to laravel, but I'm experienced in Php.
In previous works, I set a mecanism that allowed me to be informed when nearly any problem occurred on the server:
I got full stack
precise PHP error messages
for nearly all king of errors
a mail sent to me
So when I began to work with laravel, I tried to do the same things, and achieved:
full stack
a mail sent to me
But I can't have meaningful error in all case. One example:
$store = Store::create(...)
In this line I forget to specify the namespace (\App\Store::create), and I get those error messages:
first:
FatalThrowableError ; Type error: Argument 1 passed to App\Http\Controllers\User::create() must be an instance of Illuminate\Http\Request, array given, called in /var/www/html/laravel/blog/app/Http/Controllers/User.php on line 94
second:
ErrorException ; Trying to get property of non-object in VerifyCsrfToken.php (line 156)
third:
FatalThrowableError ; Type error: Argument 1 passed to Illuminate\Session\Middleware\StartSession::addCookieToResponse() must be an instance of Symfony\Component\HttpFoundation\Response, array given, called in /var/www/html/laravel/blog/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php on line 72
I understand that laravel is a complex framework but I can't figure why it produces this errors, and how I can have more useful errors (as as it is I can only know that "something is bad").
Has someone an idea ?
ยน There is some errors that Php prefers to keep to himself (in its logs) :-)
When you start a new Laravel project, error and exception handling is
already configured for you. The App\Exceptions\Handler class is where
all exceptions triggered by your application are logged and then
rendered back to the user.
https://laravel.com/docs/5.4/errors
I recommend you to dive into the official docs and into your App\Exceptions\Handler.
Maybe you are looking for report and render methods in that class.
I finally cornered the problem and I learned a lot.
I thank for their benevolence #Don't Panic and #Vitalmax !
The error was that I forgot that PHP namespaces are case insensitive: in my post I cleaned a bit the code as I knew that it didn't stick to the code's conventions (a controller's name must begin with a capital letter). Originally my controller name was user and the faulty code was:
$user = User::create(...)
As you can guess PHP believed that I wanted to call user::create (as I have such a method in my controller) and not User::create (as I wanted).
What I learned:
don't alter the code when asking for help
Laravel use a cache system that can get in the way of the debugging (see a question that I asked on laracast's forum )
take more time to read the error message; I know this rule but I keep doing otherwise

Queued Events in Laravel 4: Event::flusher() method not found

According to the Laravel 4 Documentation on queued Events, I tried to register an event flusher this way:
Event::flusher('foo.bar', function($data)
{
Mail::send(array('emails.notification', 'emails.notification_text'), array('content' => $data), function($message)
{
$message
->to('email#example.com', 'My Name')
->bcc('test#example.com')
->subject('Message from Listener');
});
});
But I am getting the following error upon loading of the script:
Call to undefined method Illuminate\Events\Dispatcher::flusher()
I also couldn't find this method in the source codes of L4. But when I change this from Event::flusher() to Event::listen(), everything works as expected.
So my guess is, that the documentation isn't up to date and the Event::flusher() method has been dropped, since Event::listen() does the same work. Or are there any differences between those two methods and I have an error in my code?
You may need to update your libraries using:
$ composer update
If that doesn't work, let us know what your composer.json file looks like - you might be using a beta version if the framework. It was updated very often before the first stable release.

Resources