I'm trying to replace a query scope with a global query scope, but while my query scope works fine the global one causes the following exception:
Symfony \ Component \ Debug \ Exception \ FatalErrorException (E_ERROR)
Maximum function nesting level of '100' reached, aborting!
here is my global scope apply() method
public function apply(Builder $builder)
{
$builder->whereHas('lifetime', function($query)
{
$query->whereNested(function($query)
{
$query->whereNull('lifetimes.days')
->orWhereRaw('NOW() < DATE_ADD(updated_at, INTERVAL lifetimes.days DAY)');
});
});
}
I just extracted the code in the original query scope and put it here.
The problem is with the whereHas() method, its callback never called and if i replaced it with another query building method like a where('col', 'value') there would be no error
In fact it indirectly calls getQuery() on the model then it is handled with the Model::__call() after that the global scopes be called again on the model, including mine and causes never ending recursive calls.
stack frames (starts from up and goes down):
Model::all()
Model->newQuery()
Model->applyGlobalScopes()
MyScope->apply()
Builder->whereHas()
Builder->has()
Relations\BelongsTo->getRelationCountQuery()
Relations\Relation->wrap()
MyModel->getQuery()
Model->__call()
Model->newQuery()
Model->applyGlobalScopes()
MyScope->apply()
Builder->whereHas()
....
They have fixed this. issue on github
Related
I am calling afterSave method in application.php to perform action on all models saving event. Issue is whenever I using SAVE method inside afterSave method application showing fatal error:
SQLSTATE[HY000]: General error: 2006 MySQL server has gone away
Point is same method working fine in specific model, without any memory exhausted error, I think there is something that need to be fixed over database connection. Below is the code which one I am trying.
//Application.php file
namespace App;
...
...
\Cake\Event\EventManager::instance()->on(
'Model.afterSave',
function (
\Cake\Event\EventInterface $event,
\Cake\Datasource\EntityInterface $entity,
\ArrayObject $options
) {
$auth_data = isset($_SESSION['Auth'])?$_SESSION['Auth']:[];
$ActionLogs = TableRegistry::get('ActionLogs');
$ActionLogsEntity = $ActionLogs->newEmptyEntity();
$ActionLogsEntity->change_log = $change_log;
$ActionLogsEntity->action_taken_by = $auth_data->username;
$ActionLogs->save($ActionLogsEntity); //This statement working fine in specific modelTable
class Application extends BaseApplication
implements AuthenticationServiceProviderInterface
{
...
...
}
Aside from the fact that the code should go into the Application class' bootstrap() method as mentioned in the comments, when you save inside of an afterSave event that listens to all models, then you naturally create a recursion, as saving the log will trigger an afterSave event too.
You have to put a safeguard in place that prevents the logging logic from running when the afterSave event belongs to the logging model, for example:
if ($event->getSubject() instanceof \App\Model\Table\ActionLogsTable) {
return;
}
// ...
Edited:
I have a custom exception with render method which is being called when I throw it e.g. from controller, but not being called when I throw it in View composer.
So when I do something like that
public function compose(View $view)
{
throw new CustomException();
}
and put dd() to exception render method
public function render()
{
dd('render is called');
}
I get no result.
If I log my exception directly, finds out that first the CustomException being thrown, then as the result I see ErrorException.
I found a place where it being thrown.
\Illuminate\View\Engines\CompilerEngine::handleViewException
protected function handleViewException(Exception $e, $obLevel)
{
$e = new ErrorException($this->getMessage($e), 0, 1, $e->getFile(), $e->getLine(), $e);
parent::handleViewException($e, $obLevel);
}
I didn't found any mentions in Laravel docs about that case.
I found a tread on github with the same issue: https://github.com/laravel/framework/issues/24658
So the question is, is this expected? Is there any adequate way to avoid this behaviour?
Edit
So, as you know, any exception during view compilation is intercepted and rethrown as ErrorException or as FatalThrowableError.
What you can do is intercept ErrorException and check if ($e->getPrevious() instanceof \CustomException) if so, you do your code, else, let the handler continue.
So I've found working solution for myself.
I've extended CompilerEngine and added additional processing in order to not throw ErrorException when I don't want to.
The important thing is - your resulting Exception must be inherited from ErrorException. Otherwise you will face multiple calls to \App\View\Engines\CompilerEngine::handleViewException which can break your logic and write multiple log entities to your log file.
I'm trying to make an ajax request along with a variable in the url of the request.
The request is supposed to retrieve results for Recipes, which has a pivot table for Flavors.
The query should retrieve all Recipes with specified flavor. I am not able to pass the $flavorID variable into the query though. Getting an undefined error.
Route::get('/api/recipes/flavor/{flavorID}', function($flavorID){
return App\Recipe::whereHas('flavors', function ($query) {
$query->where('flavor_id', $flavorID);
})->paginate(20);
});
$flavorID does not exist in the scope of the function being passed to whereHas. Use the use keyword to include the variable in the scope of the function.
Route::get('/api/recipes/flavor/{flavorID}', function($flavorID){
return App\Recipe::whereHas('flavors', function ($query) use ($flavorID) {
$query->where('flavor_id', $flavorID);
})->paginate(20);
});
See https://www.php.net/manual/en/functions.anonymous.php
When you have a sub-function, you need to pass variables into scope:
// http://example.com/api/recipies/flavor/vanilla
Route::get('/api/recipes/flavor/{flavorID}', function($flavorID){
return App\Recipe::whereHas('flavors', function ($query) use($flavorID) {
$query->where('flavor_id', $flavorID);
})->paginate(20);;
});
Adding use($flavorId) allows $flavorID to be used within function($query). If you omit it, then you get an undefined error as you're experiencing.
I need to save an image, consider that the image arrive correctly from a request, after that I need to save in storage/app.
Below the code in controller class:
public function getImage(ImageRequest $request)
{
$path = $request->image->storeAs( 'images','img.jpg','local');
}
i see this error without nothing saved:
Symfony \ Component \ Debug \ Exception \ FatalThrowableError (E_ERROR)
Call to a member function storeAs() on null
Call to a member function storeAs() on null
This error tells you that you are trying to call the storeAs() method on a null object, which means $request->image is null/doesn't exists.
I am developing a project on Laravel 5.2 , i may use facades (Auth,Request,Cache.. ) in controllers but not in any model.
this is the error:
FatalErrorException in Post.php line 73:
syntax error, unexpected '(', expecting ',' or ';'
and this is line 73:
protected $user = \Auth::user();
You cannot set a class property's default value like that. Below you can find an excerpt taken from the PHP: Properties Documentation:
This declaration may include an initialization, but this initialization must be a constant value--that is, it must be able to be evaluated at compile time and must not depend on run-time information in order to be evaluated.
Since Auth::user() depends on run-time information stored in the session for its value to be returned, your definition is invalid. To overcome that you can set the default value in the constructor like so:
protected $user;
public function __construct()
{
$this->user = \Auth::user();
}