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.

Wednesday, August 1, 2018

Laravel Allow Single Login Only

Hello,

Recently in one of my project we need functionality to allow only single session for user. So if I am logged in with one user account then I can not use it on other device. If they try to do so, it will log you out from first last session and will continue with current session.

So here is the trick I have used is to store active session id to users table and then check it with new session id on login. If both are not same then destroy the old session.

So first of all create migration and add session id column in users table.

Schema::table('users', function($table)
        {       
            $table->string('session_id')->nullable();
        });

Now in your AuthController or LoginController add following function after user is authenticated.

$user = \Auth::user();
$currentSessionId = $request->session()->getId();
if($lastSessionId != null){
if($currentSessionId != $lastSessionId){
//destroy last session
\Session::getHandler()->destroy($lastSessionId);
}
}
$user->session_id = $currentSessionId;
$user->save();

So here it will destroy old session and create new one. Please note this is one way to achieve single login. There could be better trick, in that case please share here.lara

Saturday, July 21, 2018

Step By Step : Laravel - Publish Post on Facebook Page with Graph API

Hello,

In this quick blog we will quickly go through how to publish a post on Facebook Page with graph API from your Laravel Application.

Step 1 : Create Facebook App

Login to https://developers.facebook.com/ with your Facebook account and create an app.

Now go to Settings -> Basic of your Facebook app and copy app id and app secret.


Step 2 : Install Facebook PHP SDK

Run following command to install PHP SDK in your laravel application.

composer require facebook/graph-sdk

Step 3: Get Exchange Token from Facebook App

Go to Facebook Graph API Explorer. Here is the link  https://developers.facebook.com/tools/explorer/

From here first select your application and then select the page for Page Access Token


When you are generating this token please select graph API version 2.2 and select the following permissions.

publish_actions, 
manage_pages, 
pages_show_list, 
publish_pages, 
public_profile

Step 4 : Generate Access Token 

From the exchange token generated in Step 3, Get the access token.

$url = 'https://graph.facebook.com/oauth/access_token?grant_type=fb_exchange_token&client_id= YOUR_APP_ID&client_secret= YOUR_APP_SECRET&fb_exchange_token=YOUR_TOKEN';

$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$result = curl_exec($curl);
$output = json_decode($result);
$access_token = $output->access_token;

Step 5 : Call Facebook Graph API to Send Post to Page

Create SDK object

$fb = new \Facebook\Facebook([
'app_id' => 'YOUR_APP_ID',
'app_secret' => 'YOUR_APP_SECRET',
'default_graph_version' => 'v2.2',
]);

Generate Payload

$linkData = [
 'link' => YOUR_LINK,
 'message' => YOUR_TITLE
];

Call Graph API.

$pageAccessToken =$access_token;

try {
 $response = $fb->post('/me/feed', $linkData, $pageAccessToken);
} catch(Facebook\Exceptions\FacebookResponseException $e) {
 echo 'Graph returned an error: '.$e->getMessage();
} catch(Facebook\Exceptions\FacebookSDKException $e) {
 echo 'Facebook SDK returned an error: '.$e->getMessage();
}
$graphNode = $response->getGraphNode();

Now check your Facebook page there will be post on your Facebook page. Hope this helps you.