Laravel query with multiple wheres depending on conditions - laravel

I'm new to Laravel and I'm trying to build a query.
I want to add multiple where by condititions, but I can't achieve it.
If I do it, it works:
$query = Frete::all();
//or
$query = Frete::where('estado_destino_id', '=', $request->destino);
But, what I want is to set multiple where based on some conditions, something like this:
public function fretes(Request $request){
$query = Frete::all();
if ($request->destino){
$query->where('estado_destino_id', '=', $request->destino);
}
if ($request->veiculo){
$query->where('veiculo_id', '=', $request->veiculo);
}
$query->get();
return response()->json($query);
}
The above code returns all table and it is ignoring wheres.
I also tried this $query = DB::table('fretes'); instead of $query = Frete::all();
This way, JSON returned is:
{
"connection": {},
"grammar": {},
"processor": {},
"bindings": {
"select": [],
"from": [],
"join": [],
"where": [
1
],
"having": [],
"order": [],
"union": []
},
"aggregate": null,
"columns": null,
"distinct": false,
"from": "fretes",
"joins": null,
"wheres": [
{
"type": "Basic",
"column": "estado_destino_id",
"operator": "=",
"value": 1,
"boolean": "and"
}
],
"groups": null,
"havings": null,
"orders": null,
"limit": null,
"offset": null,
"unions": null,
"unionLimit": null,
"unionOffset": null,
"unionOrders": null,
"lock": null,
"operators": [
"=",
"<",
">",
"<=",
">=",
"<>",
"!=",
"<=>",
"like",
"like binary",
"not like",
"ilike",
"&",
"|",
"^",
"<<",
">>",
"rlike",
"regexp",
"not regexp",
"~",
"~*",
"!~",
"!~*",
"similar to",
"not similar to",
"not ilike",
"~~*",
"!~~*"
],
"useWritePdo": false
}
I've seen many posts and I've tried to implement it without success.

The all() method doesn't return a query. It executes SELECT * FROM table and returns the results. You need to start a new query then add the conditions to it Frete::query();
public function fretes(Request $request){
$query = Frete::query();
if ($request->destino){
$query->where('estado_destino_id', '=', $request->destino);
}
if ($request->veiculo){
$query->where('veiculo_id', '=', $request->veiculo);
}
$results = $query->get();
return response()->json($results);
}

use here conditional-clauses
public function fretes(Request $request){
$query = Frete::when($request->destino,function($q,$request) {
return $query->where('estado_destino_id', '=', $request->destino);
})->when($request->veiculo,function($q,$request) {
return $query->where('veiculo_id', '=', $request->veiculo);
})->get();
return response()->json($query);
}
Sometimes you may want clauses to apply to a query only when something
else is true. For instance you may only want to apply a where
statement if a given input value is present on the incoming request.
You may accomplish this using the when method.

Related

Format array output to be readable by chartjs in Laravel

This is my query to get the product name and total quantity sold.
$prd = DB::table('order_details')
->join('products', 'order_details.product_id', '=', 'products.id')
->select('products.name', DB::raw('SUM(quantity) as quantity'))
->groupBy('products.name')
->orderBy('quantity', 'desc')
->get();
return $prd;
This is the output.
[
{
"name": "PINK",
"quantity": "22"
},
{
"name": "WHITE",
"quantity": "14"
},
{
"name": "RED",
"quantity": "13"
}
]
But I need it to be in this format. For it to work with chartjs.
{
"PINK": 22,
"WHITE": 14,
"RED": 13
}
This is what I've so far. I tried to use collection map. But I'm not sure how to return the quantity portion. Any pointers?
return $prd->groupBy('name')->map(function ($item, $key) {
return ''; // what should I return here to get the qty?
});
Current half baked output
{
"PINK": "",
"WHITE": "",
"RED": "",
}
You can use pluck() instead of get() for this:
$prd = DB::table('order_details')
->join('products', 'order_details.product_id', '=', 'products.id')
->select('products.name', DB::raw('SUM(quantity) as quantity'))
->groupBy('products.name')
->orderBy('quantity', 'desc')
->pluck('name', 'quantity');

Is it possible to apply condition inside the map function of Laravel?

I wanted to apply some condition in foodOrders. Is it possible to apply condition inside map function that acts as where $foodOrder->foodOrders->where('invoice_id',null)->get();
public function getTableList(Request $request){
$skip =$request->skip;
$limit=$request->limit;
$totaltable = Table::get()->count();
$table = Table::skip($skip)->take($limit)->orderBy('id', 'DESC')->get();
$table->map(function($foodOrder){
$foodOrder->foodOrders;
});
}
Below is the output that this query returns. But I only want the data with null invoice_id
{
"success": true,
"message": "Lists of Table.",
"data": [
{
"id": 2,
"table_number": "TN02",
"food_orders": [
{
"id": 16,
"food_items_id": 1,
"table_id": 2,
"invoice_id": null,
"quantity": 2,
"price": "2000.00"
},
{
"id": 17,
"food_items_id": 2,
"table_id": 2,
"invoice_id": null,
"quantity": 3,
"price": "150.00"
}
]
},
{
"id": 1,
"table_number": "TN01",
"created_at": "2020-10-25 10:44:31",
"updated_at": "2020-10-25 10:44:31",
"food_orders": [
{
"id": 14,
"food_items_id": 1,
"table_id": 1,
"invoice_id": 39,
"quantity": 1,
"price": "2000.00"
}
]
}
]
}
Not the best approach, bu this should do the trick
$table->map(function($foodOrder){
$foodOrder->foodOrders=$foodOrder->foodOrders()->where('invoice_id',null)->get();
});
Note the scopes, you need them to apply where condition. And we say = so the further changes are propagated.
I think what you need to use is a filter and not a map. Or am I wrong ?
You can filter out the whitelisted records for the food_orders.
$table->map(function($record){
$record->food_orders = collect($record->food_orders)
->filter(fn($foodOrder) => is_null($foodOrder->invoice_id));
return $record;
});
From the output data you have shown above it seems that the food_orders is a hasMany relation on the model, so it would be easy to filter out the relation when eager loading
Assuming that Table model has a relation defined for food_orders
class Table extends Model
{
public function food_orders()
{
return $this->hasMany(FoodOrder::class);
}
//... rest of the class code
}
You can constrain the related models when eager loading
$table = Table::with([
'food_orders' => fn($query) => $query->whereNull('invoice_id')
])
->skip($skip)
->take($limit)
->orderBy('id', 'desc')
->get();

Laravel : Search Query filter

I have searchDetails array in my search. I have done all other search and get data on filter, Problem is that when i search with stone_min, stone_max I get data if there is only one searchDetails array, if there is two data it is return null. How can i do this ? I want search with stone_min, stone_max for particular product_id.
what i try :
Example for data to search :
{
"limit": 1000,
"offset":0,
"user_id": "",
"min_price": "",
"max_price": "",
"searchDetails": [
{
"product_id": "1",
"attributeId": [],
"is_exclude": "no",
"stone_min": "5",
"stone_max": "15"
},
{
"product_id": "2",
"attributeId": [],
"is_exclude": "no",
"stone_min": "100",
"stone_max": "500"
}
]
}
My query for getting all data
$searchablePost = Post::with(['product','postattribute.attribute.category','user.userDetails'])
->whereIn('product_id', $userApprovalProductIDs)
->where('status', 'Active')
->whereIn('demand_or_supply', $demand_or_supply);
Search for min-max stone :
if (count($searchDetails) > 0) {
$j = 0;
foreach ($searchDetails as $value) {
if (strtolower(trim($value['is_exclude'])) == "no") {
$searchablePost = $searchablePost->where(function ($query) use ($value) {
if ($value['stone_min'] && $value['stone_max']) {
if (isset($j) && $j == 0){
$query->where('stone_min', '>=', $value['stone_min'])->where('stone_max', '<=', $value['stone_max'])->where("product_id", (int)$value['product_id']);
} else {
$query->where('stone_min', '>=', $value['stone_min'])->where('stone_max', '<=', $value['stone_max'])->where("product_id", (int)$value['product_id']);
}
}
});
}
}
}
$searchedPost = $searchablePost->offset($offset)->limit($limit)->orderBy('id','desc')->get();
If you want to search between stone_min and stone_max for particualar product then do:
$request = json_decode($request->searchDetails, true);
$stoneMinMax = collect($request)->pluck('stone_min', 'stone_max');
Product::where(function($q) use($productId) ($stoneMinMax){
$q->where('product_id', $productId)
->whereBetween('stone_column', $stoneMinMax->toArray());
})->get();

Related $query->with but "pick properties as"

I am using Laravel 5.5.13.
I am trying to fetch all Extensions but with certain extra properties based on their relations.
My goal is to get data like this, I am trying to get the latest_comment_date, thumbs_count, and thumbs_yes_count:
[
{
"id": 3,
"name": "Pull Refresh",
"created_at": "2017-11-10 06:04:44",
"updated_at": "2017-11-10 06:04:44",
"latest_comment_date": "2017-11-10 05:46:25",
"thumbs_count": 10,
"thumbs_yes_count": 2
}
]
I tried this:
return Extension::with([
'comments' => function($query) { // rename to 'latest_comment_date'
$query->orderBy('created_at', 'desc')->take(1);
},
'thumbs' => function($query) { // rename to 'thumbs_count'
$query->count();
},
'thumbs' => function($query) { // rename to 'thumbs_yes_count'
$query->where('like', '=', true)->count();
}
])->get();
This gives me data like this:
[
{
"id": 3,
"name": "Pull Refresh",
"created_at": "2017-11-10 06:04:44",
"updated_at": "2017-11-10 06:04:44",
"comments": [
{
"id": 10,
"body": "heck ya baby",
"displayname_id": 2,
"extension_id": 3,
"created_at": "2017-11-10 18:31:31",
"updated_at": "2017-11-10 18:31:31"
}
],
"thumbs": []
}
]
May you please help me to "pick as" stuff as I showed at top most?
For counting you should use withCount like so:
return Extension::withCount(
'thumbs',
'thumbs as thumbs_yes_count' => function($query) {
$query->where('like', '=', true);
})->get();
Reference: Counting related models
And for taking latest comment, you should create extra relationship like so:
public function latestComment()
{
return $this->hasOne(Comment::class)->orderBy('created_at', 'desc');
}
so the whole code would look like this:
return Extension::with('latestComment')->withCount(
'thumbs',
'thumbs as thumbs_yes_count' => function($query) {
$query->where('like', '=', true);
})->get();

Filter results from a laravel collection based on the related record

I'm using https://github.com/nicolaslopezj/searchable in my Laravel Project.
I have a Hotel object with a many to many relationships with Users.
I can query the relationship using this:
protected $searchable = [
'columns' => [
'hotels.nombre' => 10
],
'joins' => [
'hotel_user' => ['hotels.id' , 'hotel_id'],
'users' => ['hotel_user.user_id', 'users.id']
]
];
The search returns something like this (json format)
[
{
"id": 3,
"nombre": "Paradisus Playa del Carmen La Esmeralda",
"url_foto": "uploads/hotel/3/1484747239.jpg",
"website_url": "https://www.melia.com/es/hoteles/mexico/playa-del-carmen/home.htm",
"updated_at": "2017-01-18 13:47:44",
"relevance": 60,
"users": [
{
"id": 1,
"first_name": "Alex",
"last_name": "Angelico",
"formatted_name": "Alex",
"company": "ConexionBIZ",
"title": "Director",
"picture_url": "https://media.licdn.com/mpr/mprx/0_FIUn3Wf5E4OMEwzR5feW3o7IoRSveSkR5W7d3oxczOM5BdPUwDws7EIJXvDEIE5c6HMeaSSFgb19",
"created_at": "2017-01-17 12:00:00",
"updated_at": "2017-01-18 13:50:19",
"pivot": {
"hotel_id": 3,
"user_id": 1,
"created_at": null,
"updated_at": null
}
}
]
},
I want to filter all the hotels belonging to some particular user.
I tried:
$result = \App\Hotel::search($request->get('q'))->with([
'users' => function($q) use ($user_id) {
$q->where('users.id', '<>', $user_id);
},
])->get();
But this returns the hotel without the related user. I need to remove the HOTEL (not just the USER) from the results.
How can I do this?
Thanks a lot!
The with() method is actually ran as a second query after the Hotel collection is retrieved and is used for lazy loading.
What you're looking for is the whereHas() which will filter the current model results based on a related model.
$result = \App\Hotel::search($request->get('q'))
->whereHas('users', function($q) use ($user_id) {
$q->where('users.id', '<>', $user_id);
})
->get();
That will return all Hotel models that have users that don't match $user_id.
If you need to load the users too then:
$result = \App\Hotel::search($request->get('q'))
->with('users')
->whereHas('users', function($q) use ($user_id) {
$q->where('users.id', '<>', $user_id);
})
->get();
That will load all Hotel models that have at least 1 user not matching $user_id but the $result->first()->users collection can still contain users with that id. To not return any Hotel models that have $user_id and to not return any users in the related collection you would combine both methods:
$result = \App\Hotel::search($request->get('q'))
->with(['users' => function($q) use ($user_id) {
$q->where('users.id', '<>', $user_id);
}])
->whereHas('users', function($q) use ($user_id) {
$q->where('users.id', '<>', $user_id);
})
->get();

Resources