Laravel complicated filter query - php

I need to write API query which consists of "status", "category_id", "city_id" fields, and there are a lot of cases:
1) status is an array => ['OPEN','CLOSED'] OR category_id is an array => [1,2,4] AND city_id = 7 (could be any integer)
2) status is an array => ['OPEN','CLOSED'] OR category_id is an integer => 2 AND city_id = 7 (could be any integer)
3) status is a string => 'OPEN' OR category_id is an array => [1,2,4] AND city_id = 7 (could be any integer)
4) status is an array => ['OPEN','CLOSED'] AND city_id = 7 (could be any integer)
5) category_id is an array => [1,2,4] AND city_id = 7 (could be any integer)
6) status is a string => 'OPEN' AND city_id = 7 (could be any integer)
7) category_id is an integer => 1 AND city_id = 7 (could be any integer)
I have already tried to write this query, however, confused in the number of statements (the code is not working correctly, there is also district_id, but for simplicity of example I did not mention it):
$cat = cleanString(request()->get('category_id'));
$status = cleanString(request()->get('status'));
$city = cleanString(request()->get('city_id'));
$dist = cleanString(request()->get('district_id'));
if ($cat != null && $status != null) {
if (is_array($cat) && is_array($status)) {
$issues = $issues->whereIn('category_id', $cat)->orWhereIn('status', $status)->where('city_id', $city)->where('district_id', $dist);
} elseif (is_array($cat)) {
$issues = $issues->whereIn('category_id', $cat)->where('status', $status)->where('city_id', $city)->where('district_id', $dist);
} elseif (is_array($status)) {
$issues = $issues->whereIn('status', $status)->where('category_id', $cat)->where('city_id', $city)->where('district_id', $dist);
} elseif (is_string($cat) && is_string($status)) {
$issues = $issues->where('category_id', $cat)->where('status', $status)->where('city_id', $city)->where('district_id', $dist);
}
} elseif ($cat == "" || $cat == []) {
$issues = $issues->where('status', $status)->where('city_id', $city)->where('district_id', $dist);
} elseif ($status == "" || $status == []) {
$issues = $issues->where('category_id', (int)$cat)->where('city_id', $city)->where('district_id', $dist);
}
$issues = $issues->get();
Is there any way not to use so many if-else cases and make code looks cleaner and work properly?
Thanks everyone for answers in advance!

I wrote better version of query, however the disadvantage is I have to pass status or category_id as an array like this + if city_id AND/OR district_id is null, then no data returns:
{
"city_id" : 5,
"district_id" : 9,
"category_id" : [5,4],
"status" : ["REJECTED"]
}
And here is code:
if ($cat != null && $status != null) {
$issues = $issues->where('city_id', $city)->where('district_id', $dist)
->where(function ($q) {
$q->whereIn('category_id', cleanString(request()->get('category_id')))
->orWhereIn('status', cleanString(request()->get('status')));
});
} elseif ($cat == "" || $cat == []) {
$issues = $issues->where('city_id', $city)->where('district_id', $dist)
->where(function ($q) {
$q->whereIn('status', cleanString(request()->get('status')));
});
} elseif ($status == "" || $status == []) {
$issues = $issues->where('city_id', $city)->where('district_id', $dist)
->where(function ($q) {
$q->whereIn('category_id', cleanString(request()->get('category_id')));
});
}

Force convert to array
$filters = [
'category_id' => (array) cleanString(request()->get('category_id', [])),
'status' => (array) cleanString(request()->get('status', [])),
];
$filters = array_filter($filters);
foreach($filters as $key => $val) {
$issues->orWhereIn($key, $val);
}

Related

Fetch data when you have multiple search queries in laravel

I have this type of modal for search data from the database.
Image
I want to search the data if the user only types company name and CIN or *company name only or
company state and company district user can choose any field. So I want to fetch the data only on selected fields.
Is there any simplest way to do this
I have coded multiple if-else statements.
My Code
else if ($req->state && $req->district) {
$data = tbl_company::query()
->where(
"state",
"LIKE",
"%{$req->state}%"
)->where(
"district",
"LIKE",
"%{$req->district}%"
)
->paginate(100);
}
// Filter using only state and city
else if ($req->city && $req->district && $req->state == null) {
$data = tbl_company::query()
->where(
"city",
"LIKE",
"%{$req->city}%"
)->where(
"district",
"LIKE",
"%{$req->district}%"
)
->paginate(100);
}
// company status only
else if ($req->company_status && $req->city == null && $req->district == null && $req->state == null) {
$data = tbl_company::query()
->where(
"company_status",
$req->company_status
)
->paginate(100);
}
use Conditional Clauses
$data = tbl_company::query()->when($req->state && $req->district, function ($query, $req) {
$query->where("state", "LIKE", "%{$req->state}%")
->where("district", "LIKE", "%{$req->district}%");
})->when($req->city && $req->district && $req->state == null, function ($query, $req) {
$query->where("city", "LIKE", "%{$req->city}%")
->where("district", "LIKE", "%{$req->district}%");
})->paginate(100);
Updates
use loop
$data = tbl_company::query()->where(function ($query)use($req){
foreach ($req->only('state','district','city','company_status') as $filterField=>$filterFieldValue){
if(!empty($filterFieldValue)&&is_array($filterFieldValue)){
$query->wherein($filterField,$filterFieldValue);
}elseif (!empty($filterFieldValue)){
$query->where($filterField, "LIKE", "%{$filterFieldValue}%");
}
}
})->paginate(100);
I found the answer. I solved this problem using Pipeline Design Pattern
$query = tbl_company::query();
if ($req->has('state')) {
$query->whereIn('state', $req->input('state'));
}
if ($req->has('district')) {
$query->whereIn('district', $req->input('district'));
}
if ($req['date_of_registration']['start'] && $req['date_of_registration']['end']) {
$from = Carbon::parse($req['date_of_registration']['start']);
$to = Carbon::parse($req['date_of_registration']['end']);
$query->whereBetween(
DB::Raw("STR_TO_DATE(date_of_registration,'%d-%m-%Y')"),
[$from, $to]
);
}
if ($req['authorized_capital']['start'] && $req['authorized_capital']['end']) {
$query->whereBetween(
"authorized_capital",
[$req['authorized_capital']['start'], $req['authorized_capital']['end']]
);
}
//finally
$data = $query->paginate(100);

PHP - join equal arrays and add count of arrays joined

I have a task on my Laravel project that runs every day and check for expiration on some coupons. If they expire that day, I add them as array to the user table to display them on the admin panel. Problem is, client wants them to be shown joined if they share date and price properties and I'm having some trouble finding the appropriate way to do this. Let me explain:
$coupons = Coupon::where([['date_end', date('Y-m-d')], ['status', '!=', 0]])->get();
foreach ($coupons as $key => $coupon)
{
$user = User::where('id', $coupon->user_id)->first();
$coupon->status = Coupon::EXPIRED;
$coupon->save();
if ($user->expired_coupons == NULL)
{
$coupons_expired = [];
}
else
{
$coupons_expired = json_decode($user->expired_coupons);
}
$last_coupon_expired['date'] = $coupon->date_end;
$last_coupon_expired['quantity'] = 1;
$last_coupon_expired['price'] = $coupon->voucher->available->price_per_meal;
$coupons_expired[] = $last_coupon_expired;
$user->expired_coupons = $coupons_expired;
$user->save();
}
And I'll get something like this in the db:
[{
"date": "2020-05-24",
"quantity": 1,
"price": 5
}, {
"date": "2020-05-24",
"quantity": 1,
"price": 5
}, {
"date": "2020-05-24",
"quantity": 1,
"price": 10
}, {
"date": "2020-05-23",
"quantity": 1,
"price": 5
}]
Which looks like this in my admin panel:
And in this case, the way I'd want it to show would be:
- 2020-05-24 || 2 || 5
- 2020-05-24 || 1 || 10
- 2020-05-23 || 1 || 5
If I didn't need the quantity I could just get rid of the arrays that are exactly equal, but everything I tried to get the thing working as I want to has failed. Any pointers? Thanks.
If it is possible to share the data what you have got $coupons variable. But i tried to solve the problem by grouping the date and price. May be there need to more improvement.
$coupons = Coupon::where([['date_end', date('Y-m-d')], ['status', '!=', 0]])->get();
$coupons_expired = [];
foreach ($coupons as $key => $coupon)
{
$user = User::where('id', $coupon->user_id)->first();
$coupon->status = Coupon::EXPIRED;
$coupon->save();
if ($user->expired_coupons == NULL)
{
$coupons_expired = [];
}
else
{
$coupons_expired = json_decode($user->expired_coupons);
}
if (isset($coupons_expired[$coupon->date_end][$coupon->voucher->available->price_per_meal])) {
$coupons_expired[$coupon->date_end][$coupon->voucher->available->price_per_meal]['quantity']++;
} else {
$coupons_expired[$coupon->date_end][] = [
$coupon->voucher->available->price_per_meal => [
'data' => $coupon->date_end,
'quantity' => 1,
'price' => $coupon->voucher->available->price_per_meal
]
];
}
$user->expired_coupons = $coupons_expired;
$user->save();
}
$mappedData = [];
foreach ($coupons_expired as $data => $dateGroups) {
foreach ($dateGroups as $qty => $coupon) {
$mappedData[] = $coupon;
}
}
I came up with this solution that, for now, meets my needs. Since the date will always be the same for the coupons that expire (being a daily task) I just create an array with all the prices and the amount of times they appear, and then iterate it to make the final array of coupons expired joined by date and price.
foreach ($coupons as $key => $coupon)
{
$coupon->status = Coupon::EXPIRED;
$coupon->save();
$expired_coupon_price['price'] = (string)$coupon->voucher->available->price_per_meal;
$expired_coupons_prices[] = $expired_coupon_price;
}
$array_prices_unique = array_count_values(array_column($expired_coupons_prices, 'price'));
foreach ($array_prices_unique as $key => $price)
{
$last_coupon_expired['date'] = date('Y-m-d');
$last_coupon_expired['quantity'] = $price;
$last_coupon_expired['price'] = (float) key($array_prices_unique);
$coupons_expired_today[] = $last_coupon_expired;
next($array_prices_unique);
}
if ($user->expired_coupons == NULL)
{
$coupons_expired_from_user = [];
}
else
{
$coupons_expired_from_user = json_decode($user->expired_coupons);
}
$user->expired_coupons = array_merge($coupons_expired_from_user,$coupons_expired_today);
$user->save();
}

how to grouping correctly on laravel-- SQLSTATE[42803]: Grouping error: 7 ERROR

please help me I have a code like this but there is a problem in the code group by
public function table(Request $request)
{
$order = $request->input('columns');
$tahun_st = date('Y');
if($order[9]['search']['value']){
$tahun_st = $order[9]['search']['value'];
}
if($tahun_st == null || $tahun_st == ''){
$tahun_st = date('Y');
}
$data = DB::table('pegawais')->select('pegawais.*')
->selectRAW('sum(surat_tugas_nominatifs.jml_hari) as jumlah_hari')
->selectRAW('sum(surat_tugas_nominatifs.tiket + surat_tugas_nominatifs.taksi_tujuan + surat_tugas_nominatifs.taksi_awal + surat_tugas_nominatifs.trans_short_dist + surat_tugas_nominatifs.transport_lokal :: DOUBLE PRECISION) AS transport')
->selectRAW('sum(COALESCE(surat_tugas_nominatifs.lama_inap * surat_tugas_nominatifs.cost_inap)) as penginapan')
->selectRAW('SUM (CASE WHEN surat_tugass.jenis_st_id = 5 THEN COALESCE (surat_tugas_nominatifs.uang_rapat * (( 100 - surat_tugas_nominatifs.pajak ) / 100 :: DOUBLE PRECISION )) WHEN surat_tugass.jenis_st_id = 2 THEN COALESCE ((surat_tugas_nominatifs.fb + surat_tugas_nominatifs.fd ) * (( 100 - surat_tugas_nominatifs.pajak ) / 100 :: DOUBLE PRECISION )) WHEN surat_tugass.jenis_st_id = 3 THEN surat_tugas_nominatifs.fb_luar_kota ELSE surat_tugas_nominatifs.jml_hari * surat_tugas_nominatifs.harian END) AS harian')
->leftjoin('surat_tugas_pesertas','surat_tugas_pesertas.pegawai_id', 'pegawais.id')
->leftJoin('surat_tugas_nominatifs', function($join) {
$join->on('surat_tugas_nominatifs.peserta_id', 'surat_tugas_pesertas.id')
->where('surat_tugas_nominatifs.jml_hari', '!=' , 0);
})
->leftJoin('surat_tugass','surat_tugas_pesertas.surat_tugas_id', 'surat_tugass.id')
->leftJoin('view_latest_jabatan_pegawai', 'view_latest_jabatan_pegawai.pegawai_id', 'pegawais.id')
->whereRAW("date_part('year', surat_tugass.tgl_awal) = ". $tahun_st)
->where('surat_tugass.cetak_stat', true)
->where('surat_tugass.jenis_st_id', '!=', 10)//jika bukan narasumberr
->groupBy('pegawais.id');
if(!auth()->user()->can('rekap surat tugas all')){
$unit_kerja_org = DB::table('ktus')->select('*')->where('pegawai_id', auth()->user()->pegawai_id)->first();
// dd($unit_kerja_org);
$data = $data->where('view_latest_jabatan_pegawai.org_unit_kerja_id', $unit_kerja_org->organisasi_id);
}
$action = [];
$dataTable = Datatable::create($data)
->setId('pegawais.id')
->editColumn('action', function ($data) use($request, $tahun_st) {
return '<a title="Manage" href="'.route($this->route_list.'.list', ['id' => $data->id, 'tahun' => $tahun_st]).'" class="btn shoot btn-icon-only blue tooltips">
<i class="fa fa-tasks"></i>
</a>';
})
->editColumn('pegawai_nama', function ($data) use($request) {
return $data->nama;
})
->filterColumn('tahun', function ($query, $key) {
return $query->whereRAW("date_part('year', surat_tugass.tgl_awal) = ".$key);
})
->editColumn('tahun', function ($data) use($request) {
})
->editColumn('transport', function ($data) use($request) {
if(Helper::convert_number($data->transport)){
return Helper::convert_number($data->transport);
}else{
return '-';
}
})
->editColumn('uk', function ($data) use($request) {
// return $data->organisasi_id;
})
->editColumn('penginapan', function ($data) use($request) {
if(Helper::convert_number($data->penginapan)){
return Helper::convert_number($data->penginapan);
}else{
return '-';
}
})
->editColumn('harian', function ($data) use($request) {
if(Helper::convert_rupiah($data->harian)){
return Helper::convert_number($data->harian);
}else{
return '-';
}
})
->editColumn('jml_hari', function ($data) use($request) {
if($data->jumlah_hari){
$jumlah_hari = $data->jumlah_hari;
}else{
$jumlah_hari = 0;
}
return $jumlah_hari.' hari';
})
->editColumn('total', function ($data) use($request) {
$total = 0;
$total = $data->penginapan + $data->harian + $data->transport;
if($total != 0 ){
return Helper::convert_number($total);
}else{
return '-';
}
})
->defaultAction($action, ['route' => $this->route, 'title' => $this->title, 'param-model' => 'vendor']);
if ($request->has('dateFilter')) {
$date = Carbon::createFromTimestamp($request->input('dateFilter'));
} else {
$date = Carbon::now();
}
$response = $dataTable->make(true);
return response()->json($response);
}
here I have the code as above but to edit the column number of days and the total can not be filtered. SQLSTATE [42803] error: Grouping error: 7 ERROR: column "surat_tugas_nominatifs.jml_day" must appear in the GROUP BY clause or be used in an aggregate function LINE 1: ... is_st_id "! = $ 3 group by" pegawais ". "id" order by "jml_hari" ... ^ (SQL: select "pegawais". *, sum (surat_tugas_nominatifs.jml_hari) as NUMBER_DAY, sum (surat_tugas_nominatifs.tiket + surat_tugas_nominatifs.taksi_tuju + surat_tugas_nominatifs.jml_hari) as Quantity_day, sum (surat_tugas_nominatifs.tiket + surat_tugas_nominatifs.taksi_tujuan + surat_tugas_nominatifs.jml_hari) as Quantity_day, sum (surat_tugas_nominatifs.tiket + surat_tugas_nominatifs.taksi_tuju + surat_tugas_nominatifs.jml_hari) asas_day, letter sumas .transport_lokal :: DOUBLE PRECISION) AS transport, sum (COALESCE (surat_tugas_nominatifs.lama_inap * surat_tugas_nominatifs.cost_inap)) as lodging, SUM (CASE WHEN surat_tugass.jenis_st_id = 5 THEN COALESCE (surat_tugas_nominatifs. * report) / 100 :: DOUBLE PRECISION)) WHEN surat_tugass.type_st_id = 2 THEN COALESCE ((surat_tugas_nominatifs.fb + surat_tugas_nominatifs.fd) * ((100 - surat_tugas_nominatifs.pajak) / 100 :: DOUBLE PRECISION)) WHEN sEC urat_tugass.jenis_st_id = 3 THEN surat_tugas_nominatifs.fb_luar_kota ELSE surat_tugas_nominatifs.jml_hari * surat_tugas_nominatifs.harian END) AS daily, "pegawais". "id" from "pegawais" left join "letters_certification_signs" "" "letter" officer "officer" officer "officer" officer "officer" officer "officer" officer "officer" officer "officer" officer "officer". . "id" left join "surat_tugas_nominatifs" on "surat_tugas_nominatifs". "particip_id" = "surat_tugas_pesertas". "id" and "surat_tugas_nominatifs". "jml_day"! = 0 left join "surat_tugasass" on "surat_tugas_pesertas". "id" and "surat_tugas_nominatifs". "number of days"! "surat_tugass". "id" left join "view_latest_jidang_pgawai" on "view_latest_jidang_pegawai". "employee_id" = "pegawais". "id" where date_part ('year', surat_tugass.tgl_awal) = 2020 and "surat_tugass". 1 and "surat_tugass". "Type_st_id"! = 10 groups by "pegawais". "Id" order by "jml_hari" asc limit 20 offset 0)

Join 3 tables codeigniter php

I have 3 tables guest_user_info,pg_company,user_profile.
In guest_user_info have 2 columns:
g_uid | company_id
In pg_company have 2 columns:
company_id | user_id
In user_profile have 2 columns:
id |user_email
Here i want to get user_email from user_profile.i have g_uid value (in guest_user_info table).i want company_id from guest_user_info and get the company_id and match with pg_company table,there i can get user_id.then match with that user_id with id in user_profile table.at last i need user_email from user_profile table
Well its a simple one, you just need to join using active query in CodeIgniter.
$this->db->select("UP.id", "UP.user_email");
$this->db->from("guest_user_info AS GU");
$this->db->join("pg_company AS PC", "PC.company_id=GU.company_id");
$this->db->join("user_profile AS UP", "UP.id=PC.user_id");
$this->db->where("GU.g_uid", $guid);
$query = $this->db->get();
return $query->result();
In above code, $guid you have to provide which you have.
Also please take a look at these links:
https://www.codeigniter.com/userguide3/database/query_builder.html
https://www.codeigniter.com/userguide2/database/active_record.html
You get so many things after reading this.
Check bellow code it`s working fine and common model function also
supported more then one join and also supported multiple where condition
order by ,limit.it`s EASY TO USE and REMOVE CODE REDUNDANCY.
================================================================
*Album.php
//put bellow code in your controller
=================================================================
$album_id='';//album id
//pass join table value in bellow format
$join_str[0]['table'] = 'pg_company';
$join_str[0]['join_table_id'] = 'pg_company.company_id';
$join_str[0]['from_table_id'] = 'guest_user_info.company_id';
$join_str[0]['join_type'] = '';//set join type
$join_str[1]['table'] = 'user_profile';
$join_str[1]['join_table_id'] = 'user_profile.id';
$join_str[1]['from_table_id'] = 'guest_user_info.user_id';
$join_str[1]['join_type'] = '';
$selected ="guest_user_info.*,user_profile.user_name,pg_company.name";
$condition_array=array('guest_user_info.g_uid' => $g_uid);
$albumData= $this->common->select_data_by_condition('guest_user_info', $condition _array, $selected, '', '', '', '', $join_str);
//call common model function
if (!empty($albumData)) {
print_r($albumData); // print album data
}
=========================================================================
Common.php
//put bellow code in your common model file
========================================================================
function select_data_by_condition($tablename, $condition_array = array(), $data = '*', $sortby = '', $orderby = '', $limit = '', $offset = '', $join_str = array()) {
$this->db->select($data);
//if join_str array is not empty then implement the join query
if (!empty($join_str)) {
foreach ($join_str as $join) {
if ($join['join_type'] == '') {
$this->db->join($join['table'], $join['join_table_id'] . '=' . $join['from_table_id']);
} else {
$this->db->join($join['table'], $join['join_table_id'] . '=' . $join['from_table_id'], $join['join_type']);
}
}
}
//condition array pass to where condition
$this->db->where($condition_array);
//Setting Limit for Paging
if ($limit != '' && $offset == 0) {
$this->db->limit($limit);
} else if ($limit != '' && $offset != 0) {
$this->db->limit($limit, $offset);
}
//order by query
if ($sortby != '' && $orderby != '') {
$this->db->order_by($sortby, $orderby);
}
$query = $this->db->get($tablename);
//if limit is empty then returns total count
if ($limit == '') {
$query->num_rows();
}
//if limit is not empty then return result array
return $query->result_array();
}

Sort available carriers based on cart products

I need to implement a simple functionnality to my Prestashop (v1.6.1.0):
Based on the cart content (product references) I need to sort carriers that will be available for the user on the 4th "shipping" page/tab.
As an example: I have 3 carriers, but one of theme has to be removed only if one of the cart's product reference starts with a 1 (it means it's fresh food and can't be shipped via this carrier).
How can I do that?
Override function getAvailableCarrierList from Carrier class.
Edit the final loop:
if ($product->width > 0 || $product->height > 0 || $product->depth > 0 || $product->weight > 0)
{
foreach ($carrier_list as $key => $id_carrier)
{
$carrier = new Carrier($id_carrier);
// Get the sizes of the carrier and the product and sort them to check if the carrier can take the product.
$carrier_sizes = array((int)$carrier->max_width, (int)$carrier->max_height, (int)$carrier->max_depth);
$product_sizes = array((int)$product->width, (int)$product->height, (int)$product->depth);
rsort($carrier_sizes, SORT_NUMERIC);
rsort($product_sizes, SORT_NUMERIC);
if (($carrier_sizes[0] > 0 && $carrier_sizes[0] < $product_sizes[0])
|| ($carrier_sizes[1] > 0 && $carrier_sizes[1] < $product_sizes[1])
|| ($carrier_sizes[2] > 0 && $carrier_sizes[2] < $product_sizes[2]))
{
$error[$carrier->id] = Carrier::SHIPPING_SIZE_EXCEPTION;
unset($carrier_list[$key]);
}
if ($carrier->max_weight > 0 && $carrier->max_weight < $product->weight * $cart_quantity)
{
$error[$carrier->id] = Carrier::SHIPPING_WEIGHT_EXCEPTION;
unset($carrier_list[$key]);
}
//Here goes the magic
foreach ($cart->getProducts(false, $product->id) as $cart_product) {
$aProduct = new Product($cart_product['id_product']);
if (substr($aProduct->reference, 0, 1) == 1) {
unset($carrier_list[$key]);
}
}
}
}
return $carrier_list;
Still better, no need to override whole function:
public static function getAvailableCarrierList(Product $product, $id_warehouse, $id_address_delivery = null, $id_shop = null, $cart = null, &$error = array())
{
$carrier_list = parent::getAvailableCarrierList($product, $id_warehouse, $id_address_delivery, $id_shop, $cart, &$error);
if (is_null($cart))
$cart = Context::getContext()->cart;
if ($product->width > 0 || $product->height > 0 || $product->depth > 0 || $product->weight > 0)
{
foreach ($carrier_list as $key => $id_carrier)
{
//Here goes the magic
foreach ($cart->getProducts(false, $product->id) as $cart_product) {
$aProduct = new Product($cart_product['id_product']);
if (substr($aProduct->reference, 0, 1) == 1) {
unset($carrier_list[$key]);
}
}
}
}
return $carrier_list;
}
Untested.

Categories