Tuesday, December 11, 2018

Laravel Check if SMTP Connection is valid

Hello,

While working with Laravel we often add SMTP credentials to send mail. It's important to check SMTP connection before sending mail or else it may give you error and throw run time exception. Here in this blog I am going to explain how to check SMTP connection before sending mail.

Below is the code you can use to check.

try {
$security = ($request->get('mail_encryption') != 'None') ? request()->get('mail_encryption') : null;
$transport = new \Swift_SmtpTransport($request->get('mail_host'), $request->get('mail_port'), $security);
$transport->setUsername($request->get('mail_username'));
$transport->setPassword($request->get('mail_password'));
$mailer = new \Swift_Mailer($transport);
$mailer->getTransport()->start();
}
catch (\Swift_TransportException $e) {
return redirect('mailSettings')->withInput()->with(array('message'=>'Can not connect to SMTP with given credentials.'));
}

As you can see in above code, first we are setting security config and create Swift_SmtpTransport class. After this we add add username and password. After that we create Swift_Mailer class and check it, if it throws an exception that means credentials are wrong or else credentials are correct.

Laravel Create Custom Validator

As we all know that Laravel comes with in built set of custom validators like required, unique etc using which we can do form or request validations on server side. In this blog I am going to explain how to create custom validator.

Custom validator is required when you have some special logic validations. For example a field should be minimum of 12 characters, it should start with special prefix etc.

To do this Laravel provides way to create custom field validator. You have to extend Validator in boot method of AppServiceProvider. Here is the complete code.

use Validator;

public function boot()
{
        Validator::extend('VALIDATOR_NAME', function($attribute, $value, $parameters, $validator) {
               //validation logic
               //should return true or false
        });

       Validator::replacer('greater_than_field', function($message, $attribute, $rule, $parameters) {
  return $attribute."MESSAGE".$parameters[0];
});
}

As you can see in above code, first we define validator with Validator::extend and then using Validator::replacer we can define the message to be displayed.

This way you can create your own validators and then use it with Validator class.

$this->validate($request, [
          'field'=>'VALIDATOR_NAME'
]);

Thursday, November 1, 2018

Laravel : Better Way To Deal with Trying to Get Property Of Non Object

Hello Everyone,

After a gap of almost 3 months I am again writing a blog. In laravel project we sometimes face issues like we try to access model but it's not available due to various reason like
  • id we passed is wrong
  • we manually deleted records from database
  • wrong value saved in database.
  • wrong model you are trying to access with wrong value.
When we get this error, Laravel throws an ErrorException with message "Trying to get property of non object."

However, end user does not understand this error so we have to show them proper message on what's missing. We can not display generic error page and for each line of code we can not put the check so better to check it at single place. Laravel gives this functionality in Exception Handler. Here the trick is to get model which throws this error and get name of Model and display proper message. 

Laravel has class ModelNotFoundException which is thrown when you use findOrFail function. However we developers sometime do not use this function and use find function. 

When find function is used, it throws ErrorException which does not contain Model information. However we can modify Laravel source code for this. 

Open following file 

vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php

Here find public function find($id, $columns = ['*'])

and modify it as following.

        if (is_array($id) || $id instanceof Arrayable) {
            return $this->findMany($id, $columns);
        }
        $object = $this->whereKey($id)->first($columns);
        if($object == null){
            throw (new ModelNotFoundException)->setModel(
                get_class($this->model), $id
            );
        }else{
            return $this->whereKey($id)->first($columns);
        }

PLEASE NOTE : I DO NOT RECOMMEND TO MODIFY SOURCE FILE SO BETTER WAY IS TO USE FINDORFAIL FUNCTION.

Now if you use find or findOrFail function it will throw ModelNotFoundException. Now open app/Exception/Handler.php file and find out function public function render($request, Exception $exception)

Add following code at start of the function.

       if(get_class($exception) == 'Illuminate\Database\Eloquent\ModelNotFoundException'){
            $modelName = explode("\\",$exception->getModel());
            $modelName = $modelName[count($modelName)-1];
            $message = "You are trying to access ".$modelName." which does not exist.";
                return Response::make(view('Frontend.error')->with(array(
                    "message"=>$message
            )));
        }

That's it and now it will display proper message like

You are trying to access User which does not exist.
You are trying to access Post which does not exist.

Hope this helps you.