I have a Laravel application in which I integrated PHP graph sdk to use Facebook graph API. I have a stats page, I display number of posts per type, top 3 posts, and some insights metric like "page_post_engagements" ... in moris charts.
this is my controller:
public function stats($id,Facebook $fb)
{
$page = Page::find($id);
$page_fb_id = $page->fb_id;
$page_access_token = $page->access_token;
$oAuth2Client = $fb->getOAuth2Client();
$fb->setDefaultAccessToken($oAuth2Client->getLongLivedAccessToken($page_access_token)->getValue());
$nb_photos = '0';
$nb_videos = '0';
$nb_links = '0';
$nb_likes = '0';
$nb_comments = '0';
$nb_shares = '0';
$count_posts = '0';
$startDate = Carbon::now()->subDays('29');
$endDate = Carbon::now();
$numberOfDays = $endDate->diffInDays($startDate);
$classement = array();
$posts = $fb->get('/'.$page_fb_id.'/posts?fields=type&since='.Carbon::parse($startDate).'&until='.Carbon::parse($endDate))->getGraphEdge();
if(empty($posts))
{
$classement = ['total'=>0,'likes'=>0,'comments'=>0,'shares'=>0];
}
else
{
foreach ($posts as $key => $post)
{
if($post['type'] == 'photo')
{
$nb_photos++;
}
else if($post['type'] == 'video')
{
$nb_videos++;
}
else if($post['type'] == 'link')
{
$nb_links++;
}
$count_posts++;
$impress = $fb->get('/'.$post['id'].'/insights?metric=post_impressions_unique')->getGraphEdge();
$engage = $fb->get('/'.$post['id'].'/insights?metric=post_engaged_users')->getGraphEdge();
$classement[] = ['total'=>($engage[0]['values'][0]['value']/$impress[0]['values'][0]['value'])*100,'id'=>$post['id'],'impressions'=>$impress[0]['values'][0]['value'],'engage'=>$engage[0]['values'][0]['value']];
}
if(is_array($classement))
{
asort($classement);
$tops = array_slice($classement, -3, 3);
$start_elem = array_slice($tops, 0, 1);
$mid_elem = array_slice($tops, 1, 1);
$end_elem = end($tops);
}
if($end_elem['id'])
{
$top1 = $fb->get('/'.$end_elem['id'].'/?fields=id,message,full_picture,source,type,created_time,from{name,picture}')->getGraphNode();
$likes1 = $fb->get('/'.$end_elem['id'].'/likes?limit=1000000')->getGraphEdge()->count();
$comments1 = $fb->get('/'.$end_elem['id'].'/comments?limit=1000000')->getGraphEdge()->count();
$shares1 = $fb->get('/'.$end_elem['id'].'/sharedposts?limit=1000000')->getGraphEdge()->count();
}
if($mid_elem[0]['id'])
{
$top2 = $fb->get('/'.$mid_elem[0]['id'].'/?fields=id,message,full_picture,source,type,created_time,from{name,picture}')->getGraphNode();
$likes2 = $fb->get('/'.$mid_elem[0]['id'].'/likes?limit=1000000')->getGraphEdge()->count();
$comments2 = $fb->get('/'.$mid_elem[0]['id'].'/comments?limit=1000000')->getGraphEdge()->count();
$shares2 = $fb->get('/'.$mid_elem[0]['id'].'/sharedposts?limit=1000000')->getGraphEdge()->count();
}
if($start_elem[0]['id'])
{
$top3 = $fb->get('/'.$start_elem[0]['id'].'/?fields=id,message,full_picture,source,type,created_time,from{name,picture}')->getGraphNode();
$likes3 = $fb->get('/'.$start_elem[0]['id'].'/likes?limit=1000000')->getGraphEdge()->count();
$comments3 = $fb->get('/'.$start_elem[0]['id'].'/comments?limit=1000000')->getGraphEdge()->count();
$shares3 = $fb->get('/'.$start_elem[0]['id'].'/sharedposts?limit=1000000')->getGraphEdge()->count();
}
}
foreach (range(0, $numberOfDays) as $day)
{
$a[] = ['year'=>$endDate->copy()->subDays($day)->format('Y-m-d')];
}
foreach (array_reverse($a) as $key => $value)
{
$page_fans = $fb->get('/'.$page_fb_id.'/insights?metric=page_fans&since='.Carbon::parse($value['year']).'&until='.Carbon::parse($value['year'])->addDays('2'))->getGraphEdge()[0]['values'][0]['value'];
$fans[] = ['year'=>$value['year'],'value'=>$page_fans];
$page_post_engagements = $fb->get('/'.$page_fb_id.'/insights?metric=page_post_engagements&since='.Carbon::parse($value['year']).'&until='.Carbon::parse($value['year'])->addDays('2'))->getGraphEdge()[0]['values'][0]['value'];
$post_engagements[] = ['year'=>$value['year'],'value'=>$page_post_engagements];
$page_impressions = $fb->get('/'.$page_fb_id.'/insights?metric=page_impressions&since='.Carbon::parse($value['year']).'&until='.Carbon::parse($value['year'])->addDays('2'))->getGraphEdge()[0]['values'][0]['value'];
$impressions[] = ['year'=>$value['year'],'value'=>$page_impressions];
$page_actions_post_reactions_like_total = $fb->get('/'.$page_fb_id.'/insights?metric=page_actions_post_reactions_like_total&since='.Carbon::parse($value['year']).'&until='.Carbon::parse($value['year'])->addDays('2'))->getGraphEdge()[0]['values'][0]['value'];
$post_reactions_like_total[] = ['year'=>$value['year'],'value'=>$page_actions_post_reactions_like_total];
/*$page_engaged_users = $fb->get('/'.$page_fb_id.'/insights?metric=page_engaged_users&since='.Carbon::parse($value['year']).'&until='.Carbon::parse($value['year'])->addDays('2'))->getGraphEdge()[0]['values'][0]['value'];
$engaged_users[] = ['year'=>$value['year'],'value'=>$page_engaged_users];
$page_views_total = $fb->get('/'.$page_fb_id.'/insights?metric=page_views_total&since='.Carbon::parse($value['year']).'&until='.Carbon::parse($value['year'])->addDays('2'))->getGraphEdge()[0]['values'][0]['value'];
$views_total[] = ['year'=>$value['year'],'value'=>$page_views_total];*/
}
/*$fans_total = end($fans)['value'];
$moyenne_interaction = array_sum(array_column($engaged_users,'value'))/count(array_column($engaged_users,'value'));
$average_interaction = array_sum(array_column($engaged_users,'value'))/count(array_column($engaged_users,'value'))/(end($fans)['value']);*/
$fans = json_encode($fans);
$post_engagements = json_encode($post_engagements);
$impressions = json_encode($impressions);
$post_reactions_like_total = json_encode($post_reactions_like_total);
/*$engaged_users = json_encode($engaged_users);
$views_total = json_encode($views_total);*/
return view('stats',with(compact('randon','id','tasks','page','fans','impressions','post_engagements','post_reactions_like_total','engaged_users','views_total','nb_photos','nb_videos','nb_links','count_posts','fans_total','top1','likes1','comments1','shares1','top2','likes2','comments2','shares2','top3','likes3','comments3','shares3')));
}
Is there a way to optimize my code so I can get a better response time and especially avoid the Connection timed out after 10000 milliseconds exception?
I'm assuming to get the API data and parse it... it is taking longer than 10 seconds?
You have 2 things to do to improve your system: 1) Use Cache 2) Use Queues.
Cache! (Save the API/parsed result for 15 minutes or so)
Queues! (API parsing is done in the server background)
Your system workflow will be:
User hits /stats
Is there a cache version? Use it. Response time ~ barely 500ms.
No/Expired cache? Fire a Queued Job to get the new API data.
Show the user 'Data is being refreshed!' and display the latest cache.