mercredi 3 mars 2021

mardi 2 mars 2021

PHP: Laravel query optimization

I have this query that is querying through a table of more than 3 hundred thousands records. So here is the query in Laravel 5.5:

$this->select = \DB::table('transport_orders')
   ->join('users', 'users.id', '=', 'transport_orders.user_id', 'left')
   ->join('transport_order_price_requests', 'transport_order_price_requests.transport_order_id', '=', 'transport_orders.id', 'left')
   ->join('price_requests', 'transport_order_price_requests.price_request_id', '=', 'price_requests.id', 'left')
   ->join('order_numbers', 'transport_orders.order_number_id', '=', 'order_numbers.id', 'left')
   ->join(\DB::raw('
                (select transport_order_statuses.transport_order_id, max(transport_order_statuses.id) as last_link_id
                from transport_order_statuses
                group by transport_order_statuses.transport_order_id) as last_statuses'
            ), function ($join) {
     $join->on('transport_orders.id', '=', 'last_statuses.transport_order_id');
            })
   ->join('transport_order_statuses', 'last_statuses.last_link_id', '=', 'transport_order_statuses.id')
   ->join('statuses', 'transport_order_statuses.status_id', '=', 'statuses.id')
   ->select(
        'transport_orders.id as id',
             \DB::raw('CONCAT(users.first_name, \' \', users.last_name) as user_full_name'),
              \DB::raw('DATE_FORMAT(transport_orders.pickup_date , "%Y-%m-%d") as pickup_date'),
         'transport_orders.location_name',
         'transport_orders.carrier_name',
         'transport_orders.country_name',
         'transport_orders.country_code',
         'transport_orders.category_name',
         'transport_orders.zip',
         'transport_orders.rate_type',
         'transport_orders.rate_name',
         'transport_orders.order_number_id',
         'order_numbers.order_number as order_number',
         'transport_orders.comment',
         'transport_orders.inbound',
         'transport_orders.unit',
         'transport_orders.unit_value',
         \DB::raw('DATE_FORMAT(transport_orders.created_at , "%Y-%m-%d") as created_at'),
         'transport_orders.base_price',
         'transport_orders.created_at',
         'transport_orders.updated_at',
         'transport_orders.price',
         'transport_orders.stops',
         'transport_orders.stop_price',
         'transport_orders.id as id',
         'transport_orders.transport_mode as transport_mode_name',
         'statuses.status as status',
         'statuses.id as status_id',
         'transport_orders.multishipment as multishipment',
         'transport_orders.total_weight as total_weight',
         'order_numbers.simulation as simulated'
 )->where('transport_orders.is_deleting', '=', 0);

And after this I do:

$this->select->paginate($itemsPerPage);

Now if this query is to be converted to plain MySql, here it is:

select `transport_orders`.`id` as `id`, CONCAT(users.first_name, ' ', users.last_name) as user_full_name, DATE_FORMAT(transport_orders.pickup_date , "%Y-%m-%d") as pickup_date, `transport_orders`.`location_name`, `transport_orders`.`carrier_name`, `transport_orders`.`country_name`, `transport_orders`.`country_code`, `transport_orders`.`category_name`, `transport_orders`.`zip`, `transport_orders`.`rate_type`, `transport_orders`.`rate_name`, `transport_orders`.`order_number_id`, `order_numbers`.`order_number` as `order_number`, `transport_orders`.`comment`, `transport_orders`.`inbound`, `transport_orders`.`unit`, `transport_orders`.`unit_value`, DATE_FORMAT(transport_orders.created_at , "%Y-%m-%d") as created_at, `transport_orders`.`base_price`, `transport_orders`.`created_at`, `transport_orders`.`updated_at`, `transport_orders`.`price`, `transport_orders`.`stops`, `transport_orders`.`stop_price`, `transport_orders`.`id` as `id`, `transport_orders`.`transport_mode` as `transport_mode_name`, `statuses`.`status` as `status`, `statuses`.`id` as `status_id`, `transport_orders`.`multishipment` as `multishipment`, `transport_orders`.`total_weight` as `total_weight`, `order_numbers`.`simulation` as `simulated` from `transport_orders` left join `users` on `users`.`id` = `transport_orders`.`user_id` left join `transport_order_price_requests` on `transport_order_price_requests`.`transport_order_id` = `transport_orders`.`id` left join `price_requests` on `transport_order_price_requests`.`price_request_id` = `price_requests`.`id` left join `order_numbers` on `transport_orders`.`order_number_id` = `order_numbers`.`id` inner join
(select transport_order_statuses.transport_order_id, max(transport_order_statuses.id) as last_link_id
from transport_order_statuses
group by transport_order_statuses.transport_order_id) as last_statuses on `transport_orders`.`id` = `last_statuses`.`transport_order_id` inner join `transport_order_statuses` on `last_statuses`.`last_link_id` = `transport_order_statuses`.`id` inner join `statuses` on `transport_order_statuses`.`status_id` = `statuses`.`id` where `transport_orders`.`is_deleting` = 0 and `order_numbers`.`simulation` = 0 order by `transport_orders`.`created_at` desc limit 13 offset 0

The Laravel debugbar tells me that the query is taking more than 9 seconds. As I am using paginate (Length Aware Paginator), it also does a count so that takes another around 6 seconds. When I run the plain query in MySql it takes about 9-10 seconds as well. How can I optimize this query? Note that I don't want to use simplePaginate as it would require a whole lot of refactoring.



via Chebli Mohamed

Error: Sorry, you are not allowed to create resources. [woocommerce_rest_cannot_create]

I tried to post a product using woocommerce rest API using Laravel, in basic authentication i'm using data from env (store url, consumer key, consumer secret). But i want it dynamic, so i get that 3 elements (store url, consumer key, consumer secret) from database. Fyi, i am make some form to post store url, consumer key, consumer secret into database. What i want to ask is when i use data from env for authentication post product there's no problem, but when i use data from database its show error like this: Error: Sorry, you are not allowed to create resources. [woocommerce_rest_cannot_create]. Anyone have a solution? i'm so confused, sorry for my bad english.

Screenshots: this is when i use 3 points for authenticate from env, no problem in this case when i use 3 points for authenticate with method like this (get from database), it will show error error like this if i use method in pict number 2



via Chebli Mohamed

What is the best practice to use Constants in Laravel that leverage syntax checking in VS Code?

I am aware there are already a lot of answers being posted on best practices of using Constants in Laravel. I come from the Java world whereby constants are checked for validity in the editor. In Laravel, using the config/constants.php method,

return [
    'options' => [
        'balance_outstanding' => 0,
        'balance_balance' => 1,
        'balance_partial_balance' => 2,
    ] 
];

Whereby we refer to the constant using Config::get('constants.options.balance_outstanding')) syntax, I cannot seem to trigger the syntax check nor autocomplete. It would be great if we can mouse over and see what the constant real value is. I am using https://marketplace.visualstudio.com/items?itemName=bmewburn.vscode-intelephense-client

So, my question is, what is the best way to define constants in such a way that the editor is smart enough to be aware that its a constant?



via Chebli Mohamed

How to find records by closest data to today

I'm trying to get the closest upcoming match to today, but instead, I get the latest created record with the code I write. How can I change the code to find the date closest to today?

$upcomingMatch = Match::leftjoin('scores', 'matches.id', '=', 'scores.match_id')
    ->where(function ($where) {
        $where->where('matches.away_team_id', '=', '1')
            ->orWhere('matches.home_team_id', '=', '1');
    })
    ->whereNull('scores.id')
    ->latest('matches.match_date')
    ->first();


via Chebli Mohamed

Laravel + Angular api not working properly?

I have developed web app using Angular with backend Laravel. but in my Angular page did not display backend data. I have following data.service.ts

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable({
  providedIn: 'root'
})
export class DataService {

  constructor(private httpClient:HttpClient) { }

  getData() {
    return this.httpClient.get('http://127.0.0.1:8000/api/employees');
  }
}

but I got flowing error message

expected onespace after colon in parameter (typedef-whitespace)
missing whitespace (whitespace)
expected call-signature: 'getData' to have a typedef (typedef)

How could I fix this?



via Chebli Mohamed

Creating array variable in collection loop

I get data from query and running a foreach loop on it.

foreach($result as $data)
{
    $myVar[$data->flag][$data->year]['totalActions'] += $data->totalActions;
}

And getting this error Undefined variable: myVar

When I create a variable before loop like $myVar = []

Then it gives me the error Undefined index: All

Here All is value of $data->flag

How to handle this?



via Chebli Mohamed