Can someone show me how to write this query in Eloquent?
SELECT * FROM `projects` WHERE `id`='17' OR `id`='19'
I am thinking
Project::where('id','=','17')
->orWhere('id','=','19')
->get();
Also my variables (17 and 19) in this case are coming from a multi select box, so basically in an array. Any clues on how to cycle through that and add these where/orWhere clauses dynamically?
Thanks.
You could do in three ways. Assume you've an array in the form
['myselect' => [11, 15, 17, 19], 'otherfield' => 'test', '_token' => 'jahduwlsbw91ihp'] which could be a dump of \Input::all();
Project::where(function ($query) {
foreach(\Input::get('myselect') as $select) {
$query->orWhere('id', '=', $select);
}
})->get();
Project::whereIn('id', \Input::get('myselect'))->get();
$sql = \DB::table('projects');
foreach (\Input::get('myselect') as $select) {
$sql->orWhere('id', '=', $select);
}
$result = $sql->get();
The best approach for this case is using Laravel's equivalent for SQL's IN().
Project::whereIn('id', [17, 19])->get();
Will be the same as:
SELECT * FROM projects WHERE id IN (17, 19)
This approach is nicer and also more efficient - according to the Mysql Manual, if all values are constants, IN sorts the list and then uses a binary search.
In laravel 5 you could do it this way.
$projects = Projects::query();
foreach ($selects as $select) {
$projects->orWhere('id', '=', $select);
}
$result = $projects->get();
This is very useful specially if you have custom methods on your Projects model and you need to query from variable. You cannot pass $selects inside the orWhere method.
public function getSearchProducts($searchInput)
{
$products = Cache::rememberForever('getSearchProductsWithDiscountCalculationproducts', function () {
return DB::table('products_view')->get();
});
$searchProducts = $products->filter(function ($item) use($searchInput) {
return preg_match('/'.$searchInput.'/i', $item->productName) || preg_match('/'.$searchInput.'/i', $item->searchTags) ;
});
$response = ["status" => "Success", "data" => $searchProducts ];
return response(json_encode($response), 200, ["Content-Type" => "application/json"]);
}
use filter functionality for any customize situations.
Related
I recently wanted to sort parent elements of a collection by using their relationship values so I came across something like this and It works. Do you think this is a suitable method or am I making this overcomplicated?
Basically, I want to sort the Events by their date
Events have one to many with Slots
Any review on this would be appreciated
Cheers
$events = Event::with(['slots' => function ($q) {
$q->orderBy('date');
$q->orderBy('start_time');
}])->active()->get();
$slotArray = [];
foreach($events as $event){
foreach ($event->slots as $slot) {
$slotArray[$slot->id] = [ 'id' => $event->id, 'start_date' => $slot->date, 'start_time' => $slot->start_time];
}
}
//Sort the Array of IDS
usort($slotArray, array($this,"sortByStartDate"));
//Find the New Set of IDS sorted by the Start Date
$sortedEventIDs = [];
foreach($slotArray as $value) {
array_push($sortedEventIDs, $value['id']);
}
$sortedEvents = $events->sortBy(function($model) use ($sortedEventIDs){
return array_search($model->getKey(), $sortedEventIDs);
});
Sort Function
function sortByStartDate($a, $b){
return $a['start_date'] > $b['start_date'];
}
There is an SQL approach, that would look something like this. Create an subselect, fetch the date you want to use and order by it.
Event::with(['slots' => function ($q) {
$q->orderBy('date');
$q->orderBy('start_time');
}])
->addSelect([
'date' => Comment::selectRaw('MAX(start_date)')
->whereColumn('events.id', 'comments.event_id'),
])->orderBy('date');
Simply use Laravel relation and do the same, not as performance optimized but very straight forward aproeach.
$events = Event::with(['slots' => function ($q) {
$q->orderBy('date');
$q->orderBy('start_time');
}])->active()->get();
$events->sortBy(function ($event) {
return $event->slots()->max('start_date');
});
You can use orderBy() function:
$events = Event::orderBy('start_time', 'DESC')->active()->get();
and for the IDs, you can use sortKeys():
$sorted = $events->sortKeys();
$sorted->all();
I'm working on a small project using laravel and i would like to know how can i use WHERE clause for apartment this is my code
$buildings = Building::with('apartment')->get();
i have already tried :
$buildings = Building::with('apartment')->where('name','=',5)->get();
but it applies for Building not for apartment.
how can i apply WHERE clause for apartment ?
You can apply a Closure to with(...) if you pass in an array using the following syntax:
Model::with(['relation_name' => function ($query) { ... }])
In your case, what you're looking for is:
$buildings = Building::with(['apartment' => function ($apartments) {
$apartments->where('name', 5); // if you don't pass an operator, it's assumed to be '='.
}])->get();
You can also write it like this using PHP 7.4 shorthand closures.
$buildings = Building::with(['apartment' => fn($apartments) => $apartments->where('name', 5)])->get();
https://laravel.com/docs/7.x/eloquent-relationships#constraining-eager-loads
Try this
$buildings = App\Building::with(['apartment' => function ($query) {
$query->where('name', 5); .
}])->get();
I have column named flag and I want to update it if value is 1 to null and if value is null to 1 so far is easy to update this column but issue comes where I send multiple data to controller and not only one.
code
public function flagmultiplemessage(Request $request){
$ids = $request->input('ids');
DB::table('messages')->whereIn('id', $ids)
->whereNotNull('messages.flag')->update(['flag' => null])
->whereNull('messages.flag')->update(['flag' => '1']);
}
with function above i get:
message Call to a member function whereNull() on integer
dd
code above is something like this:
ids = [11, 12, 3]
database = [
11->flag = 1,
12->flag = null,
3->flag = 1,
]
the result of code above most change my database like:
database = [
11->flag = null,
12->flag = 1,
3->flag = null,
]
any idea why i get error?
it occurred because you called whereNull method on update method.
You should run 3 separate query like this.
public function flagmultiplemessage(Request $request){
$ids = $request->input('ids');
DB::transaction(function () use ($ids) {
DB::table('messages')->whereIn('id', $ids)
->whereNotNull('messages.flag')->update(['flag' => 0]);
DB::table('messages')->whereIn('id', $ids)
->whereNull('messages.flag')->update(['flag' => 1]);
DB::table('messages')->whereIn('id', $ids)
->where('messages.flag', 0)->update(['flag' => null]);
});
}
but for better performance I suggest you use boolean for flag column and use this simple query
DB::table('messages')->whereIn('id', $ids)->update(['flag' => DB::raw('!flag')]);
The main reason for the error is that the update() method is not chainable
Alternatively, You can do the update in one query by using the mysql Case statement.
public function flagmultiplemessage(Request $request) {
$ids = $request->input('ids');
DB::table('messages')->whereIn('id', $ids)
->update(['flag' => DB::raw('case when flag is null then 1 else null end') ]);
}
You can do this
DB::table('messages')->whereIn('id', $ids)->where(function ($query) {
$query->whereNotNull('messages.flag')->update(['flag' => null])
->orWhereNull('messages.flag')->update(['flag' => '1']);
})
I have the following query in my controller.
$items = Item::with(['subitems' => function($query) {
$query->where('language_id', '=', 1);
}])->get();
This is correctly getting me all items including subitems that have a language id of 1.
There are two things I would like to do with this though
Firstly, I need to return all subitems that have a distinct 'ref_id' value.
Secondly, I would like to give preference to the language id 1 but if none exist, use any language id.
So for example, I know this code won't work, but the sort of thing I am looking for is:
$items = Item::with(['subitems' => function($query) {
$subItems = $query->where('language_id', '=', 1)
->where('ref_id', 'is', 'distinct');
if($subItems->count() <= 0) {
$subItems = $query->where('ref_id', 'is', 'distinct');
}
}])->get();
Is this possible or is it a bit too complicated for Query Builder? Even if one of the two requests was possible, that would be great.
Try this:
$items = Item::with(['subitems' => function($query) {
$join = Subitem::select('ref_id', DB::raw('MIN(language_id) language_id'))
->groupBy('ref_id');
$sql = '(' . $join->toSql() . ') subitems_distinct';
$query->join(DB::raw($sql), function($join) {
$join->on('subitems.ref_id', 'subitems_distinct.ref_id')
->on('subitems.language_id', 'subitems_distinct.language_id');
});
}])->get();
We can use the fact that your preferred language_id is the lowest value and select the minimum.
I have an Item table, Meta table and a Item_Meta table which has all meta records for Items. One Item has many Meta records.
Item_meta has the following columns:
Item_id | Meta_id | Value
Lets say I have a requirements:
Requirement 1 - ['Meta_id' => 1, 'value' => 'new']
Requirement 2 - ['Meta_id' => 3, 'value' => 'LCD']
I need to build a query get all items, which have meta_id with id 1 equal to new, and meta_id with id 3 equal to LCD.
So if an item does not have one of this metas (or one of metas has wrong value) it should not be returned.
You can filter your models on relation's attributes using Eloquent's whereHas() method. In your case the following code should do the trick:
$items = Item::whereHas('metas', function($query) {
$query->where('Meta_id', 1);
$query->where('value', 'new);
})
->whereHas('metas', function($query) {
$query->where('Meta_id', 3);
$query->where('value', 'LCD);
})
->get();
I assumed that your item->meta relation is called metas.
You could also use another form of using whereHas() where you provide number of matching related records. The code will be a bit more complex but it will result in less subselects in the executed query:
$items = Item::whereHas('metas', function($query) {
$query->where('Meta_id', 1);
$query->where('value', 'new);
$query->orWhere(function($query2) {
$query2->where('Meta_id', 3);
$query2->where('value', 'LCD);
};
}, '=', 2)
->get();
I have tried the first approach from the previous answer before asking the question, but it failed so I thought it had a mistake. But after seeing and that answer it seemed that I don't understand something. So I digged inside of Laravel Eloquent internals and here is what I found:
Eloquent Build class "::where" method changes $this->query property before returning the instance. Here is the code:
public function where($column, $operator = null, $value = null, $boolean = 'and')
{
if ($column instanceof Closure) {
$query = $this->model->newQueryWithoutScopes();
call_user_func($column, $query);
$this->query->addNestedWhereQuery($query->getQuery(), $boolean);
} else {
call_user_func_array([$this->query, 'where'], func_get_args());
}
return $this;
}
Take notice of "$this->query->addNestedWhereQuery($query->getQuery(), $boolean);" on the 6th line.
The Builder class "::whereHas" method does not modify "$this->query" property.
public function whereHas($relation, Closure $callback, $operator = '>=', $count = 1)
{
return $this->has($relation, $operator, $count, 'and', $callback);
}
So, what it has to do with my problem. I have created a query like this:
$query = Item::where('active',1);
Then I added the conditions:
if($meta){
$query->whereHas('metas', function($query) {
$query->where('Meta_id', 1);
$query->where('value', 'new);
})
->whereHas('metas', function($query) {
$query->where('Meta_id', 3);
$query->where('value', 'LCD);
})
}
and then query was performed:
$query->get();
The mistake was related to ::whereHas method, what I had to do was assign whereHas result to the variable:
if($meta){
$query = $query->whereHas('metas', function($query) {
$query->where('Meta_id', 1);
$query->where('value', 'new);
})
->whereHas('metas', function($query) {
$query->where('Meta_id', 3);
$query->where('value', 'LCD);
})
}
So thats all. Always check with internals if something works unexpectadely