Les billets libellés: laravel. Afficher tous les billets.

Error Handling in Laravel

vendredi 29 septembre 2017

For a Laravel application I am working on the need arose to log errors to the database rather than to log files. I also wanted to show a custom error page instead of Laravel's default error page. This is my solution:

In app/Exceptions/Handler.php:

public function report(Exception $exception)
{
    if(!config('app.debug')) {
        if ($this->shouldReport($exception)) {
            $this->logError($exception);
        }
    }
    if(env('APP_ENV') == 'local'){
        parent::report($exception);
    }
}

public function render($request, Exception $exception)
{
    if(!config('app.debug')) {
        if($this->shouldReport($exception)){
            return response()->view('errors.500', compact('exception'));
        }
    }
    return parent::render($request, $exception);
}

Function report checks to see if APP_ENV is set to local, if so it displays the error as normal. If it is not local it calls function logError which writes the error to the database. 

Function render also checks APP_DEBUG and if it is set to true it reports the error to the screen as normal. If it is set to false it returns a custom error template which is stored in resources/views/error/500.blade.php.

 

Libellés: coding, laravel, php2
Aucun commentaire

Update on Custom Logging

mercredi 09 août 2017

After spending yesterday figuring out how to write custom log files, today I changed my mind and went a different route. The problem with these log files is that they would need to be parsed to generate the reports I would need to generate. While this could easily and efficiently be done with something like Python, in order to stick with using PHP I decided to take a completely different approach.

I created a statistics table where I can just increment the appropriate column rather than writing a whole line to a text file. My concern with this was that it would down the site substantially, so rather than recording the data while the user is performing the searches I created a Job and queue it to be processed later. This doesn't help with the server load, but it does remove the response time for the user as a factor.

Libellés: coding, laravel
Aucun commentaire

Laravel comes with Monolog which it uses to log application exceptions and such. The need arose recently to log other information to text files, specifically searches performed by users. I tried logging this to the database but the table grew very quickly and performance suffered as a result. 

So I decided to log to text files, which I can then process when reporting is needed. It would be relatively easy to use PHP file operations to open and append to a text file, but I decided to try to stick to using Monolog. Most of the information I was able to find online about how to do this involved overwriting Laravel's Logging Configuration classes to allow different types of data to be written to different log files, but it seemed like an awful lot of code to do something that should be relatively simple. After more searching I found a method that uses 4 lines of code and works perfectly:

$logPath = [path to log file]
$orderLog = new Logger('searches');
$orderLog->pushHandler(new StreamHandler($logPath), Logger::INFO);
$orderLog->info('Search : ', $data);

By including the date in the $logPath as part of the file name I can automatically rotate the logs and write to whatever location I choose to. The $data variable needs to be an array and is encoded to JSON and written to the log. The parameter passed into the new Logger() is the channel written to the log. 

The only thing I have not yet been able to customize is the Priority - in this case "Info." For my purposes this isn't really necessary and could be ommitted, but having it doesn't have any downsides so I don't know if it's worth the trouble of figuring out how to remove it. 

 

Libellés: coding, laravel
Aucun commentaire

PHP Traits

mardi 27 juin 2017

Over the last few weeks I have become enamored of using traits in PHP. Whereas I previously would put functions that need to be reused into either my Models or into helper functions, I have now started to make traits with these functions in them. For my Laravel application I created a directory app/Http/Traits where I keep my traits.

I started doing this when I began to optimize my code, trying to remove redundant code and remove unneccesary weight from my models. Using PHPStorm's very useful ability to find duplicated code I searched for blocks of 10 lines or more that were reused and moved those into traits. As I continued to do this I started to realize other benefits of using traits - mainly that it provides a way to simplify things. If the same action is taken in different controller or different parts of the application by using a Trait if I decide to change it I only have to change the code in one place rather than tracking down every place in the code that needs to be changed.

 

Libellés: coding, laravel, php2
Aucun commentaire

For the project I am working on we want to have multiple SMTP configurations in the database, which can be chosen at runtime. It's very easy to update the mail config using the config() helper, but for some reason that did not change the SMTP settings used to actually send the mail. I did a lot of research and found some answers for older versions of Laravel that did not work with 5.4.

Eventually I was able to find how to accomplish this from this post on Laravel.io. It seems that the mailer instance is created with the app, so updating the config won't change the properties of it which have already been set. To do that you need to use the following code:

extract(config('mail'));

$transport = \Swift_SmtpTransport::newInstance($host, $port);
// set encryption
if (isset($encryption)) $transport->setEncryption($encryption);
// set username and password
if (isset($username))
{
    $transport->setUsername($username);
    $transport->setPassword($password);
}

// set new swift mailer
Mail::setSwiftMailer(new \Swift_Mailer($transport));
// set from name and address
if (is_array($from) && isset($from['address']))
{
    Mail::alwaysFrom($from['address'], $from['name']);
}

If you execute this after you have updated the config it will create a new instance of swift_mailer with the update mail config. Once that is done you can just send the mails and it will use the proper SMTP server.

Libellés: coding, laravel
Aucun commentaire

Archives du Blogue