Laravel App::make causes infinite loop - laravel

I'm creating some project management functionality.
I'm using Model Observers in Laravel to create an audit trail whenever models are created/updated/deleted. So for example when a project is created, the observer will automatically create a new instance of the project audit model creating a new database entry storing the fields that have changed. This observer also clears the relevant caches, ensuring the user can access the most recent information.
The problem is calling the cache repository causes this error message (with no stack trace):
Symfony \ Component \ Debug \ Exception \ FatalErrorException (E_ERROR)
Maximum function nesting level of '100' reached, aborting!
I'm using App::make to call the cache repository:
$this->projectAuditCache = App::make('cache\ProjectManagement\Interfaces\ProjectAuditCacheInterface');
The Audit Cache Repository then constructs with only one other repository which isn't reliant on anything else.
The only possible clue on the stack trace is this:
Open: /home/vagrant/Sites/fixing/new_fixing/vendor/laravel/framework/src/Illuminate/Container/Container.php
* Determine if the given abstract has a leading slash.
*
* #param string $abstract
* #return bool
*/
protected function missingLeadingSlash($abstract)
{
return is_string($abstract) && strpos($abstract, '\\') !== 0;
}
Is there a way to get this to work? Is using App::make the wrong way to go about this?
Thanks, Ed

The problem which causes the error is xdebug the debug extension of PHP.
The array that this extension wants to echo is to big.
You can just simply adjust the setting of maximum nesting level of xdebug simply in your php.ini.
Or with the command
ini_set('xdebug.max_nesting_level', $limit)
which should be included when your app starts. For Laravel 4.x that would be app/start/global.php.
Source: StackOverflow

Related

Get `LoggerInterface` instance in Laravel >=5.6 (replacement for `Log::getMonolog()`)?

I am using a 3rd party library that provides a constructor which expects an instance of Psr\Log\LoggerInterface. The constructor in that code looks like:
public function __construct(
$configuration = null,
\Psr\Log\LoggerInterface $logger = null
)
{
In my Laravel 5.5 application I had written a service provider to set up that library for me, and I got access to a LoggerInterface for it by using Laravel's Log::getMonolog():
$connection_manager = ConnectionManager::factory(
config('the_lib_config'),
\Log::getMonolog()
);
With the changes to logging that took place in Laravel 5.6, however, the method getMonolog has gone away. I understand why this method isn't there now, but I'm wondering what the prescribed method is to get what this class needs so that it can log in context of the Laravel app (with all the new Laravel logging goodness).
My Google-Fu got stronger throughout the day, and I found the answer I was looking for in a response by #ermyril at https://laracasts.com/discuss/channels/laravel/getting-laravels-logger-instance?reply=530098
The answer is:
\Log::getLogger();

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

Executing Artisan command with arguments

Currently i'm facing following problem:
I want to update my search index automatically after my database has been updated.
I've registered a saved() listener on my tables in AppServiceProvider:
\App\Customer::saved(function(\App\Customer $customer) {
// Update search index here
});
Inside the closure i try to call an Artisan command (scout:import) passing App\\Customer to the command. I've tried
Artisan::queue('scout:import', ['' => 'App\\\Customer']);
// Fails with message: Uninitialized string offset: 0
Artisan::queue('scout:import', ['model' => 'App\\\Customer']);
// Fails: Cannot redeclare class App\Customer
Artisan::queue('scout:import', ['App\\\Customer']);
// Fails: Not enough arguments (missing: "model")
I did'nt find information where to put the required arguments in the offical documentation.
I'm sure that it's dead simple (like everything in laravel) but i'm not able to get it done ...
The correct format is:
Artisan::queue('email:send', [
'user' => 1, '--queue' => 'default'
]);
As per: https://laravel.com/docs/5.3/artisan#programmatically-executing-commands
I'd say your middle example is probably closest, and is executing the command with the correct parameters, but there is something else going on under the surface.
EDIT
Just did a bit more digging, you need to refer to the signature of the Console command, which isn't actually apparent on the surface. In your case, you need to refer to this console command:
https://github.com/laravel/scout/blob/2.0/src/Console/ImportCommand.php
Note the signature is marked with {model}.
So your command would look like:
Artisan::queue('scout:import', ['model' => 'App\\\Customer']);
Another example using the controller make command, note that this time we using the signature segment {name}:
Artisan::call('make:controller', ['name'=>'FOOBAR']);
Again, there is probably an underlying issue here - you should try running the import command from the console/terminal directly to see if you get the same issue.
Try this:
\App\Customer::saved(function(\App\Customer $customer, $input) {
// Update search index here
});
Artisan::queue('scout:import {input}', ['App\\\Customer']);
You don't need to sync with algolia using an artisan call.
Refer to algolia documentation:
Algolia Laravel Doc
'Every time you modify a model, Laravel emits an event. Scout is listening for that event, informing your app to make an HTTP call to Algolia to update its index.
You don’t have anything else to do, use your searchable class the way you usually would do'

Check if extension installed without notice on fail

The method JComponentHelper::isEnabled('com_extension', true); checks if an extension is installed and returns a boolean.
The function will also throw an exception notice it the component is not installed due to the self::getComponent($option, $strict); in the same helper class.
Is there a way to avoid the notice if the component is not installed?
Check your database to see if the component is installed and enabled.
$db = JFactory::getDbo();
$db->setQuery("SELECT enabled FROM #__extensions WHERE name = 'component name'");
$is_enabled = $db->loadResult();
if the value of $is_enabled is 1, then your component is enabled.
While realizing that this is an old question, it is also one of Google's first results and I wanted to share what works for me while avoiding extra database queries.
To avoid the exception you can also check to see if the entry point file of the extension exists like:
if (file_exists(JPATH_ADMINISTRATOR . '/components/com_extension/extension.php') && JComponentHelper::isEnabled('com_extension', true))
{
// Your code here
}
You could use the same function isEnabled and catch that exception, so if the exception is thrown then the component is not installed.
Check out
JComponentHelper::isInstalled('com_extension');

Resources