Laravel dynamic queries with premade string - php

How to insert strings as query in Laravel? I have to handle a dynamic value for "book formats" (such as "pdf", "epub", "physical", "") and this formats are separated by comma. Here is my code:
$formats_sql = '';
$format_filter_count = 0;
$format_filter = explode(',', $format_filter);
foreach ($format_filter as $format_filter_tmp) {
if ($format_filter_count == 0) {
$formats_sql .= "where('format', '=', '{$format_filter_tmp}')";
} else {
$formats_sql .= "->orWhere('format', '=', '{$format_filter_tmp}')";
}
$format_filter_count += 1;
}
if ($price_filter == 'paid') {
$books = Book::where('book_id', '=', $category_book->book_id)->$formats_sql->where('sell_price', '>', '0')->where('status', '=', '1')->get();
}
But makes this problem:
Undefined property: Illuminate\Database\Eloquent\Builder::$where('format', '=', 'pdf')->orWhere('format', '=', 'epub')

Your over complicating this. You should be using whereIn where you need to search for an array of values.
You whole code above can be condensed to:
if ($price_filter == 'paid') {
$formats = explode(',', $format_filter);
Book::where('book_id', $category_book->book_id)->whereIn('format', $formats)->where('sell_price', '>', '0')->where('status', '1')->get();
}

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);

Fetch posts that have a tag that the user has as well

In a Laravel app, I'm trying to implement a structure where posts are fetched that have one or more of the tags that the user has access to. I wrote the code below to do that:
$query = new Posts();
if (count(Auth::user()->tags) > 0) {
$query = $query->whereHas('tags', function ($q) {
$i = 0;
foreach (Auth::user()->tags as $tag) {
if ($i == 0) {
$q->where('title', '=', $tag->title);
} else {
$q->orWhere('title', '=', $tag->title);
}
$i++;
}
});
}
$posts = $query->where('isTemplate', true)->orderBy($key, $order)->paginate(15);
This works, but feels off. So I'm wondering if there's a better way to do this?
#user4992124, Will this help you.
$query = Posts::query()
->where('isTemplate', true)
->orderBy($key, $order);
if (Auth::user()->tags->isNotEmpty()) {
$tags = Auth::user()
->tags
->pluck('title')
->toArray();
$query = $query->whereIn('tags', $tags);
}
$posts = $query->paginate(15);

Get data whereBeetween two coloms

I'm using Laravel 5.5.
I have Table centrals with Model Centrals
and table like this
my Controller
$from = $request->year_from;
$to = $request->year_to;
$month_from = $request->month_from;
$month_to = $request->month_to;
$param = $request->get('parameters_id', []);
$search = Centrals::whereIn('parameters_id', $param)
->where('type', 'Monthly')
->where('year', $from)
->whereBetween('months_id', [$month_from, $month_to])
->orderBy('year')
->get();
now how i get data
example request:
$request->year_from = 2016;
$request->month_from = 1; /* 1 =Jan*/
$request->year_from = 2018;
$request->month_from = 3; /* 3 =Mar*/
The following should do the trick:
$search = Centrals::whereIn('parameters_id', $param)
->where('type', 'Monthly')
->where(function($q) use ($yearFrom, $monthFrom) {
$q->where('year', '>', $yearFrom);
$q->orWhere(function($q2) use ($yearFrom, $monthFrom) {
$q2->where('year', $yearFrom);
$q2->where('month', '>=', $monthFrom);
});
})
->where(function($q) use ($yearTo, $monthTo) {
$q->where('year', '<', $yearTo);
$q->orWhere(function($q2) use ($yearTo, $monthTo) {
$q2->where('year', $yearTo);
$q2->where('month', '<=', $monthTo);
});
})->get();

SQL: Query returns 1 using count

I have a query in PHP(MySQL). I am fetching records from a table and returning them to a datatable.
The problem is it always returns 1 when I use count() with the query.
However, if I count the elements of the array, then the result is as expected. It returns all 8 records.
Following is my code:
public function job_order_detail_del($arr=array()) {
$count = 0;
$start = isset($arr['start'])?$arr['start']:0;
$length = isset($arr['length'])?$arr['length']:0;
$search = isset($arr['search'])?$arr['search']:'';
$orderBy = isset($arr['orderBy'])?$arr['orderBy']:'';
$orderDir = isset($arr['orderDir'])?$arr['orderDir']:'';
$aufnr = isset($arr['aufnr'])?$arr['aufnr']:0;
$aufpl = isset($arr['aufpl'])?$arr['aufpl']:0;
$type = isset($arr['type'])?$arr['type']:'';
$whr = array('h.stats' => '', 'h.bukrs' => Session::get('company'), 'h.delstats' => '');
if ($aufnr > 0)
$whr['a.aufnr'] = $aufnr;
if ($aufpl > 0)
$whr['a.aufpl'] = $aufpl;
$a = DB::table('zpp_afpo_h as h')
->leftjoin('zpp_afpo as a ', function($join) {
$join->on('a.aufnr', '=', 'h.aufnr')
->where('a.bukrs', '=', Session::get('company'))
->where('a.stats', '=', '');
})
->leftjoin('zpp_afvc as b ', function($join) {
$join->on('a.aufnr', '=', 'b.aufnr')
->on('a.aufpl', '=', 'b.aufpl')
->where('b.bukrs', '=', Session::get('company'))
->where('b.stats', '=', '');
})
->leftjoin('zpp_afru as c ', function($join) use($type) {
$join->on('c.aufnr', '=', 'b.aufnr')
->on('c.rueck', '=', 'b.rueck');
})
->where('c.type', '=', $type)
->where('c.bukrs', '=', Session::get('company'))
->where('c.stats', '=', '')
->where('c.delstats', '=', '')
->select('h.idat2', 'a.matnr', 'b.arbpl', 'a.gamng as total', 'b.rueck', 'h.priority', 'b.vornr', 'b.prev_startper', 'b.scrap', 'h.dispatch_date', 'h.order_start_dt', 'h.requirement_dt', 'h.ktxt', 'c.rmzhl', 'c.budat', 'c.aufnr', 'c.rework_lmnga', DB::raw('sum(c.lmnga) as sum_cnfrm'));
if ($aufnr == '') {
$a->where('h.idat2', '=', '0000:00:00');
}
$a->where($whr)
->groupby('b.rueck')
->groupby('c.rmzhl')
->groupby('c.counter');
if($orderBy!=''){
$a->orderBy($orderBy,$orderDir);
}
if($search!=''){
$dt_srch = implode('-',array_reverse(explode('-',$search)));
$a->where(function($query) use ($search,$dt_srch){
$query->where('c.aufnr','LIKE','%'.$search.'%')
->orWhere('a.matnr','LIKE','%'.$search.'%')
->orWhere('c.budat','LIKE','%'.$dt_srch.'%')
->orWhere('b.arbpl','LIKE','%'.$search.'%')
->orWhere('a.gamng','LIKE','%'.$search.'%');
});
}
if($length>0){
$get_rec = $a->skip($start)->take($length)->get();
}else{
$get_rec = $a->get();
$count = count($get_rec);
// $count = $a->count(); //Problem is here
return $count;
}
$arr = array();
foreach($get_rec as $l){
if($length>0 || Input::get('open') == 1 || Input::get('open') == 2){
$arr = DB::table('maras')
->where('matnr','=',$l->matnr)
->where('bukrs','=',Session::get('company'))
->where('stats','=','')
->where('delstats','=','')
->select(DB::raw('GROUP_CONCAT(distinct(matnr)) as mat'),DB::raw('GROUP_CONCAT(distinct(mdesc)) as mat_desc'))
->groupby('matnr')
->first();
$l->matnr = $arr->mat;
$l->mat_desc = $arr->mat_desc;
}
}
return $get_rec;
}
Please let me know the problem. Thanks in advance.
You are using count on groupBy element and count is returning only the grouped count. That's why it is returning only single row or 1. You could count the returned collections in this case like-
$count = $get_rec->count();

Laravel: Join Closure Inside where closure. Eloquent

I'm trying to select some registries in my "properties" table using a filter search function.
In my controller I receive the filters and process them with an advanced where, inside it I need to look registries related by other table when the filter "room" is used. For this I'm trying to do a join inside the where closure, but the join is not working at all, the search is done ignoring the join.
Controller:
$filter_type= Input::has('filter_type') ? Input::get('filter_type') : NULL;
$filter_val= Input::has('filter_val') ? Input::get('filter_val') : NULL;
$state= NULL;
$sub_category= NULL;
$cat_operation= NULL;
$room= NULL;
if($filter_type == 'state'){
$state = $filter_val;
}
if($filter_type == 'sub_category'){
$sub_category = $filter_val;
}
if($filter_type == 'cat_operation'){
$cat_operation = $filter_val;
}
if($filter_type == 'room'){
$room = $filter_val;
}
$properties = Property::where(function($query) use ($state, $sub_category, $cat_operation, $room){
if (isset($state)){
$query->where('state_id', $state);
}
if (isset($sub_category)){
$query->where('sub_category_id', $sub_category);
}
if (isset($cat_operation)){
$query->where('cat_operation_id', $cat_operation);
}
if(isset($room)){
$query->join('properties_control', function($join) use ($room)
{
if($room == 5){
$join->on('properties.id', '=', 'properties_control.property_id')
->where('properties_control.category_feature_item_id', '=', 75)
->where('properties_control.category_feature_item_value', '>=', $room);
}else{
$join->on('properties.id', '=', 'properties_control.property_id')
->where('properties_control.category_feature_item_id', '=', 75)
->where('properties_control.category_feature_item_value', '=', $room);
}
});
}
})->paginate(20);
The join statement is not running at all.
It's possible include a join closure in a where closure like I am trying to do here? There is another way to accomplish this?
The main reason why your join closure is not working, is because it is enclosed in an advanced where closure.
Here's the laravel (right) way to write the code above:
$filter_type= Input::get('filter_type',null);
$filter_val= Input::get('filter_val',null);
//Start the query builder
$queryProperties = Property::newQuery();
//Switch on type of filter we received
switch($filter_type)
{
case 'state'
$queryProperties->where('state_id',$filter_val);
break;
case 'sub_category':
$queryProperties->where('sub_category_id', $filter_val);
break;
case 'cat_operation':
$queryProperties->where('cat_operation_id', $filter_val);
break;
case 'room':
$queryProperties->join('properties_control', function($join) use ($filter_val)
{
if($room == 5){
$join->on('properties.id', '=', 'properties_control.property_id')
->where('properties_control.category_feature_item_id', '=', 75)
->where('properties_control.category_feature_item_value', '>=', $filter_val);
}else{
$join->on('properties.id', '=', 'properties_control.property_id')
->where('properties_control.category_feature_item_id', '=', 75)
->where('properties_control.category_feature_item_value', '=', $filter_val);
}
});
break;
}
$properties = $queryProperties->paginate(20);

Categories