I am trying to optimize my query for a page with pagination results in Cakephp and therefore I am looking to calculate the exact time with the PHP function microtime().
That way, I will know better how much time it's taking to execute the certain request.
Moreover, I am trying to cache the results of the pagination through Cache::read and Cache::write, which both are internal Cakephp functions as regards caching methods in Cakephp 2.x.
Thus, what I have at this point is this:
I am thinking that in order to calculate exactly the whole timelapse, should I put the rest of the code inside the while loop ?
Any help would be quite appreciating.
Thanks
$start = microtime(true);
while ($start) {
$this->paginate = $options;
$resultado = $this->paginate('Doctor');
}
$time_elapsed_secs = microtime(true) - $start;
pr($time_elapsed_secs);
foreach ($resultado AS $k => $r) {
$hasProduct = Cache::read(__('thedoctors::') . 'hasProduct_by_dr_' . PAIS . '_' . $r['Doctor']['id'], '1day');
if (empty($hasProduct)) {
$hasProduct = $this->DoctorsProduct->find('all', [
'recursive' => -1,
'fields' => ['Product.*', 'DoctorsProduct.*'],
'joins' => [
['table' => 'td_products',
'alias' => 'Product',
'type' => 'INNER',
'conditions' => [
'Product.id = DoctorsProduct.id_product'
]
]
],
'conditions' => [
'id_doctor' => $r['Doctor']['id'],
'DoctorsProduct.status' => 1
],
'order' => [
'Product.id ASC',
]
]);
Cache::write(__('thedoctors::') . 'hasProduct_by_dr_' . PAIS, $hasProduct, '1day');
}
$resultado[$k]['Products'] = $hasProduct;
$resultado[$k]['Article'] = 0;
}
Well, the approach which I posted it is indeed wrong, that would possibly just loop infinitely. Finally, what I found as a solution to the question would be to just put the microtime function at the very beginning. I declare a new variable as $time.
After this, I am just substracting the actual microtime with the time which was declared beforewards. Works like a charm.
$time = microtime( TRUE );
foreach ($resultado AS $k => $r) {
$hasProduct = Cache::read(__('thedoctors::') . 'hasProduct_by_dr_' . PAIS . '_' . $r['Doctor']['id'], '1day');
if (empty($hasProduct)) {
$hasProduct = $this->DoctorsProduct->find('all', [
'fields' => ['Product.*', 'DoctorsProduct.*'],
'joins' => [
['table' => 'td_products',
'alias' => 'Product',
'type' => 'INNER',
'conditions' => [
'Product.id = DoctorsProduct.id_product'
]
],
],
'conditions' => [
'id_doctor' => $r['Doctor']['id'],
'DoctorsProduct.status' => 1
],
'order' => [
'Product.id ASC',
]
]);
Cache::write(__('thedoctors::') . 'hasProduct_by_dr_' . PAIS,
$hasProduct, '1day');
}
$resultado[$k]['Products'] = $hasProduct;
$resultado[$k]['Article'] = 0;
}
$time = microtime( TRUE ) - $time;
echo $time;
die("123");
Related
Sorry I am new to Laravel and PHP. I have a web application code that I need to debug. I run the code, and it gives me ErrorException Trying to get property 'name' of non-object. I looked it up, and I know it's a common problem but I still cannot figure out what is causing this error. I already looked at this page and I don't understand: Reference - What does this error mean in PHP?
This is my controller code:
function getActivity(){
$lead_history = Lead::with('user','eventTypeTrashed','locationTrashed')->get();
$event_history = Event::with('user','booking','contactus.event_type_trashed','booking.location_trashed')->get();
$data = [];
foreach ($lead_history as $key => $leads){
if(count($leads->revisionHistory) > 0){
foreach ($leads->revisionHistory as $history){
$date_diff = \DateTime::createFromFormat('Y-m-d H:i:s',date('Y-m-d H:i:s'))->diff(\DateTime::createFromFormat('Y-m-d H:i:s',date('Y-m-d H:i:s',strtotime($history->updated_at))));
if($date_diff->d > 0 ){
$date = $date_diff->d . ' days ago';
} elseif($date_diff->h > 0){
$date = $date_diff->h . ' hours ago';
}else{
$date = $date_diff->i . ' minutes ago';
}
$data[] = [
'id' => $leads->id,
'type' => 'lead',
'image' => $history->userResponsible()->user_avatar,
'user' => $history->userResponsible()->first_name .' '. $history->userResponsible()->last_name,
'user_id' => $history->userResponsible()->id,
'key' => ucwords(str_replace("_"," ",$history->fieldName())),
'client' => $leads->client_name,
'status' => 'update',
'old_value' =>$history->oldValue(),
'new_value' =>$history->newValue(),
'updated_at' => $history->updated_at,
'time_diff' =>$date,
'priority' => $leads->priority,
'location' => $leads->locationTrashed->name, // This line casuses an error
'event_type' => ($leads->eventTypeTrashed) ? $leads->eventTypeTrashed->name : ''
];
}
}
$date_diff = \DateTime::createFromFormat('Y-m-d H:i:s',date('Y-m-d H:i:s'))->diff(\DateTime::createFromFormat('Y-m-d H:i:s',date('Y-m-d H:i:s',strtotime($leads->created_at))));
if($date_diff->d > 0){
$date = $date_diff->d . ' days ago';
} elseif($date_diff->h > 0){
$date = $date_diff->h . ' hours ago';
}else{
$date = $date_diff->i . ' minutes ago';
}
$data[] = [
'id' => $leads->id,
'type' => 'lead',
'image' => $leads->user->user_avatar,
'user' => $leads->user->first_name .' '. $leads->user->last_name,
'user_id' => $leads->user->id,
'key' => '',
'client' => $leads->client_name,
'status' => 'created',
'updated_at' => $leads->created_at,
'old_value' =>'',
'new_value' =>'',
'time_diff' =>$date,
'priority' => $leads->priority,
'location' => $leads->locationTrashed->name,
'event_type' => ($leads->eventTypeTrashed) ? $leads->eventTypeTrashed->name : ''
];
}
foreach ($event_history as $key => $events){
if(count($events->revisionHistory) > 0){
foreach ($events->revisionHistory as $history){
$date_diff = \DateTime::createFromFormat('Y-m-d H:i:s',date('Y-m-d H:i:s'))->diff(\DateTime::createFromFormat('Y-m-d H:i:s',date('Y-m-d H:i:s',strtotime($history->updated_at))));
if($date_diff->d > 0){
$date = $date_diff->d . ' days ago';
}elseif ($date_diff->h > 0){
$date = $date_diff->h . ' hours ago';
}else{
$date = $date_diff->i . ' minutes ago';
}
$data[] = [
'id' => $events->id,
'type' => 'event',
'image' => $history->userResponsible()->user_avatar,
'user' => $history->userResponsible()->first_name .' '. $history->userResponsible()->last_name,
'user_id' => $history->userResponsible()->id,
'key' => ucwords(str_replace("_"," ",$history->fieldName())),
'client' => $events->booking->booking_name,
'status' => 'update',
'updated_at' => $history->updated_at,
'old_value' =>$history->oldValue(),
'new_value' =>$history->newValue(),
'time_diff' =>$date,
'priority' => $events->status,
'location' => $events->booking->location_trashed->name,
'event_type' => $events->contactus->event_type_trashed->name
];
}
}
$date_diff = \DateTime::createFromFormat('Y-m-d H:i:s',date('Y-m-d H:i:s'))->diff(\DateTime::createFromFormat('Y-m-d H:i:s',date('Y-m-d H:i:s',strtotime($events->created_at))));
if($date_diff->d > 0){
$date = $date_diff->d . ' days ago';
}elseif($date_diff->h > 0){
$date = $date_diff->h . ' hours ago';
}else{
$date = $date_diff->i . ' minutes ago';
}
$data[] = [
'id' => $events->id,
'type' => 'event',
'image' => ($events->user) ? $events->user->user_avatar : '',
'user' => ($events->user) ? $events->user->first_name .' '. $events->user->last_name : '',
'user_id' => ($events->user) ? $events->user->id : '',
'key' => '',
'client' => $events->booking->booking_name,
'status' => 'created',
'updated_at' => $events->created_at,
'old_value' =>'',
'new_value' =>'',
'time_diff' => $date,
'priority' => $events->status,
'location' => $events->booking->location_trashed->name,
'event_type' => $events->contactus->event_type_trashed->name
];
}
usort($data, function ($a, $b){
$dateA = \DateTime::createFromFormat('Y-m-d H:i:s', $a['updated_at']);
$dateB = \DateTime::createFromFormat('Y-m-d H:i:s', $b['updated_at']);
return $dateB >= $dateA;
});
return $data;
}
Sorry if this is a bad question and please tell me if I need to include anything else
This error occurs when there's no relational record found. Like in your code you've a relation "locationTrashed". When lead don't have any record related to it in location_trashed table it'll return error. In Laravel 8 you can return default model result if not results available against record or just simply use ($param ?? null).
You have a lot going on there! I have some suggestions that might make your life easier and your code cleaner. But first, the missing 'name' error...
'location' => $leads->locationTrashed->name,
Relationship Name
First thing I noticed about this relationship is the name should be 'location_trashed' instead of the camelCase 'locationTrashed'. In your other models, it is 'location_trashed', so make sure this is correct. I'll continue to reference it as locationTrashed, since this is what your current code reflects.
Finding the Cause
You're probably correct in identifying this line as causing the error. The issue is probably that the locationTrashed doesn't exist. You should look for the locationTrashed_id (or location_trashed_id) to figure out what the id is, and make sure the item exists in the database and hasn't been deleted.
Which Object Doesn't Exist?
If you aren't sure which object is causing the error, you can try dumping the object if the relationship doesn't exist. Laravel has convenient methods like has() and doesntHave() to make this easy. Put this right above the '$data[] = [' line.
https://laravel.com/docs/8.x/eloquent-relationships#querying-relationship-existence
if($leads->doesntHave('locationTrashed')) {
dd($leads);
}
$data[] = [
'id' => $leads->id,
'type' => 'lead',
...
This will let you see the object in question and determine which related 'locationTrashed' is missing.
Or... ignore it
If you need the relationship, use the above to try to figure it out. However, if the relationship isn't there because it doesn't always exist, set it to be ignored.
You can use an exists() method on the relationship to check if it exists.
'location' => ($leads->locationTrashed()->exists()) ? $leads->locationTrashed->name : ''
Now some suggestions:
Carbon for Dates
You should really look into using Carbon. This will take the 8 lines of code you have and reduce it to:
$date_diff = Carbon::parse($history->updated_at)->diffForHumans();
https://carbon.nesbot.com/docs/#api-humandiff
Attribute Accessors
Your user model has a first_name and last_name attribute that you're putting together to display their full name. If you do this often, you can set up an attribute accessor so you don't have keep doing it.
// User Model
public function getFullNameAttribute() {
return $this->first_name.' '.$this->last_name;
}
// Controller
'user' => $history->userResponsible->full_name
https://laravel.com/docs/8.x/eloquent-mutators#accessors-and-mutators
Laravel Collections
When working with arrays, you can instead convert them into collections and take advantage of the many useful methods that it provides. Instead of ordering the data items yourself, you can use the sortBy() method:
$collection = collect($data)->sortBy('updated_at');
$collection = collect($data)->sortByDesc('updated_at'); // or descending
https://laravel.com/docs/8.x/collections
I used ArrayDataProvider to mix models and then merged them into one data-provider. I used the data-provider in grid-view and everything is works fine.
But I need to order the grid-view by one column I tried a lot of solutions but none of them are worked.
This my model code (order by item_order )
public function getAllSelectedItemsInTheUnit($unitId, $grid = false)
{
$finalList = array();
$storiesList = array();
$activityList = array();
$breakList = array();
$stories = UnitStories::find()->joinWith(['story'])->where("unit_id=$unitId")->all();
if (count($stories) > 0) {
foreach ($stories as $item) {
$storiesList[] = [
'key' => self::TYPE_STORY . $item->id,
'id' => $item->id,
'title' => $item->story->title,
'type' => self::TYPE_STORY,
'item_order' => $item->unit_order,
];
}
}
$activities = UnitActivities::find()->joinWith(['activity'])->where("unit_id=$unitId")->all();
if (count($activities) > 0) {
foreach ($activities as $item) {
$activityList[] = [
'key' => self::TYPE_ACTIVITY . $item->id,
'id' => $item->id,
'title' => $item->activity->title,
'type' => self::TYPE_ACTIVITY,
'item_order' => $item->activity_order,
];
}
}
$breaks = UnitBreaks::find()->where("unit_id=$unitId")->all();
if (count($breaks) > 0) {
foreach ($breaks as $item) {
$breakList[] = [
'key' => self::TYPE_BREAK . $item->id,
'id' => $item->id,
'title' => $item->title,
'type' => self::TYPE_BREAK,
'item_order' => $item->unit_order,
];
}
}
$finalList = array_merge($storiesList, $activityList, $breakList);
$dataProvider = new ArrayDataProvider([
'allModels' => $finalList, 'key' => 'key',
'sort' => [
'attributes' => ['item_order'],
],
]);
return $dataProvider;
}
Any solution will be very good even sort array by pure PHP I guess will fix the problem .
You can use usort()
usort($finalList, function ($a, $b) {
return $a['item_order'] < $b['item_order'];
});
Add your condition in callback >, <, <= etc
I am currently using Highcharts in symfony. It works good when I enter static data (array1/array2/array3/array4) like this:
$ob1 = new Highchart();
$ob1->chart->renderTo('barchart');
$ob1->title->text('Chart 1');
$ob1->xAxis->categories($arrayResult);
$ob1->plotOptions->pie(array(
'allowPointSelect' => true,
'cursor' => 'pointer',
'dataLabels' => array('enabled' => false),
'showInLegend' => true
));
$ob1->series(array(array('type' => 'column','name' => 'bar1', 'data' => $array1),
(array('type' => 'column','name' => 'bar2', 'data' => $array2)),
(array('type' => 'column','name' => 'bar3', 'data' => $array3)),
(array('type' => 'column','name' => 'bar4', 'data' => $array4))
));
but what I need is to enter data within a loop because I have an irregular number of arrays. I tried this but I got an error "unexpected 'while' (T_WHILE)" Is there anything I have missed here?
Here is my code using while to add Chart's Data Series:
$i=1;
$number=4;
$ob1->series(array(
(
$myarray = array();
while($i <= $number): array_push($myarray, array(0 => 'value', 1=> $i));
$i++;
array('type' => 'column','name' => 'bar'.$i, 'data' => $myarray)
endwhile;
),
));
I also tried this and displays only the last iteration of the while
$i=1;
$number=4;
$myarray = array();
while($i <= $number):
array_push($myarray, array(0 => 'value', 1=> $i));
$i++;
$ob1->series(array (array('type' => 'column','name' => 'bar'.$i, 'data' => $myarray)));
endwhile;
Your php statement is not valid, has invalid syntax. To avoid this type of error, never create a loop inside the function argument. Simplify your syntax and use temporal variables, is easy to read and to understand what are you doing, remember, every good developer always say: "divide and conquer" :)
$i = 1;
$number = 4;
$chartData = [];
while ($i <= $number) {
$chartData[] = [
'type' => 'column',
'name' => 'bar'.$i,
'data' => [
'value',
$i,
],
];
$i++;
}
$ob1->series($chartData);
I just want to add different colors for each records within foreach loop.I tried to add but I couldn't make it. Given below is my function.
public function service()
{
$result = Order::getService();
$out = array();
foreach($result as $row) {
$out[] = array(
'id' => $row['orderID'],
'class'=>'event-special',
'title' => $row['customer_name'].' - '.$row['order_number'],
'url' => URL::to('/').'/customer/'.$row['customerID'].'/order/'.$row['orderID'].'/edit',
'start' => strtotime($row['start_date']) . '000',
'end' => strtotime($row['end_date']) .'000'
);
}
return json_encode(array('success' => 1, 'result' => $out));
}
Can anyone please help me with this?
You could create yourself a set of event-special css classes i.e. event-special1, event-special2 ......
And then amend the code to add a number to your existing class
public function service()
{
$result = Order::getService();
$out = array();
$color = 1;
foreach($result as $row) {
$out[] = array(
'id' => $row['orderID'],
'class'=>'event-special' . $color,
'title' => $row['customer_name'].' - '.$row['order_number'],
'url' => URL::to('/').'/customer/'.$row['customerID'].'/order/'.$row['orderID'].'/edit',
'start' => strtotime($row['start_date']) . '000',
'end' => strtotime($row['end_date']) .'000'
);
$color++;
}
return json_encode(array('success' => 1, 'result' => $out));
}
first of, just wanted to let you know that I am a newbie at CI. but I am having trouble with this piece of code where is breaking and I can't seem to be able to find the answer anywhere.
for some reason the code is breaking at the first if statement.. if possible could you help me out understand what is really happening there?
Thank you all for your help!
function main
{
$this->load->model(getData) psudo code for this area...
}
---model---
function getData....
{
Sql = this->db->query(sql code that returns all the information required.)
$result = $sql->result_array();
$types = array ( 'EVENT|TIME' => array( 'id' => 1, 'name' => 'Regular' ),
'PROPOSITION|REGULAR' => array( 'id' => 2, 'name' =>'Propositions'),
'EVENT|TIME' => array( 'id' => 3, 'name' => 'Now' ),
'PROPOSITION|FUTURES' => array( 'id' => 4, 'name' => 'Future' ));
$var = array();
foreach ($result as $event) {
$cat = $event['type'] . '|' . $event['sub_type'];
$typeId = $types[$cat]['id'];
if(!is_array($var[$event['event_id']]['var'][$event['type_id']]))
{
if(!is_array($var[$event['event_id']]))
{
$var[$event['event_id']] = array( 'event_name' =>
$event['event_name'],'event_abbreviation' =>
$event['event_abbreviation']);
}
$var[$event['event_id']]['var'][$event['type_id']] = array(
'type_name' => $event['abbreviation'],'type_abbreviation' => $event['name']
);
}
$event[$event['event_id']]['var'][$event['type_id']]['types'][$typeId] =
$types[$cat]['name'];
}
return $myResults;
}
In this line
if(!is_array($var[$event['event_id']]['var']$event['type_id']]))
You are missing a [ somewhere. I'm guessing before $event['type_id'].
So replace with:
if(!is_array($var[$event['event_id']]['var'][$event['type_id']]))