Laravel - Passing array of data to view and accessing array elements conditionally - laravel

Suppose I design an email template notifying about the interview scheduled for 3 candidates to a recruiter, so in that case I send candidates array of 3 elements as a variable to my template. How do I access individual candidates name in that case?

you only need to pass parameters as you would for any other, with
$candArr = Candidates::where('something','value')->get();
return view('email')->with('candidates',$candArr);
Or
$candArr = Candidates::where('something','value')->get();
return view('email',compact('candArr'));
and then in view
#foreach($candArr as $key)
{{$key->name}}
#endforeach
Hope it helps!

Related

How can i sort a laravel's elequent list by another ids

I have a challenge that if I want to sort the records when getting using Laravel's ORM based on a list of IDs, how should I do it?!!!!!!!
I mean :
Suppose we have a table called users, which contains 100 records and each record has a unique ID.
We also have an array of IDs.
$ids = [4,1,2,3]
Now I want to get the list of users, but only the users who are first in the ids array and secondly according to the same order as they are listed in this array.
User::whereIn('id' , $Ids)->sortBy('id',$ids)->get();
Can you think of a solution to do this?
User::whereIn('id' , $Ids)->sortBy('id',$ids)->get();
The collections sortBy() function can take a custom call back this way:
$users = User::whereIn('id', $Ids)->get()
->sortBy(function($user, $key) use($ids) {
return array_search($user->id, $ids);
});
This will sort your collection according to the given array.
You can also reference the docs for more information.
Note that the sortBy() function must act upon a collection, which means that the get() function must come before it.

Laravel 7 API Resource showing only data that contains relationship

This my code stored in my API Controller:
return ApartmentResource::collection(Apartment::with(['sponsors'])->paginate(5));
It shows all Apartments, someone have the sponsor array empty, someone not.
How i can show only the Apartments that actually have sponsors?
You can use the has() method
https://laravel.com/docs/9.x/eloquent-relationships#querying-relationship-existence
return ApartmentResource::collection(Apartment::has('sponsors')->with(['sponsors'])->paginate(5));
with() simply eager loads the sponsors: https://laravel.com/docs/9.x/eloquent-relationships#eager-loading
use array_filter()
example:
$result = array_filter($array);
array_filter() remove empty array elements from array.

Livewire and Eloquent - Sums of multiple columns in filtered collection

quite a noob in Laravel and Livewire, I guess if there is a better way to accomplish what I have here:
I have some checkboxes in a Livewire view that allow the user to dynamically choose how to filter the data being shown in a HTML table.
On the controller I have an eloquent query that retrieves a subset of the records in the db whenever a checkbox changes state.
Like this (I tried to simplify the structure):
$filtered_items = Item::select('item_color', 'item_quantity', 'item_value')
->whereIn('item_color', [ /* array controlled by checkboxes values in view */ ])
->get();
I need to also show the sums of some columns for that specific filter setup.
As I don't want to make new queries, I try to work on the already available collection with a ->sum() for each column I want to sum:
$sums['item_quantity'] = $filtered_items->sum('item_quantity');
$sums['item_value'] = $filtered_items->sum('item_value');
It works as intended, as I have an array with the sums, but I was wondering if there is a better way to do this, or even write a function to get more columns sum at once, maybe passing an array.
Thanks for any idea or link!
Here is an example of a single query for all sums (two in this example)
$filtered_items = \DB::table('items')
->selectRaw('SUM(item_quantity) as sum_quantity, SUM(item_value) as sum_value')
->whereIn('item_color', [ /* array controlled by checkboxes values in view */ ])
->first();
The advantage is that it will return one entry/row instead of a collection of all the items which is way faster.

SOLVED: Looking for a smarter way to sync and order entries in Laravel/Eloquent pivot table

In my Laravel 5.1 app, I have classes Page (models a webpage) and Media (models an image). A Page contains a collection of Media objects and this relationship is maintained in a "media_page" pivot table. The pivot table has columns for page_id, media_id and sort_order.
A utility form on the site allows an Admin to manually associate one or more Media items to a Page and specify the order in which the Media items render in the view. When the form submits, the Controller receives a sorted list of media ids. The association is saved in the Controller store() and update() methods as follows:
[STORE] $page->media()->attach($mediaIds);
[UPDATE] $page->media()->sync($mediaIds);
This works fine but doesn't allow me to save the sort_order specified in the mediaIds request param. As such, Media items are always returned to the view in the order in which they appear in the database, regardless of how the Admin manually ordered them. I know how to attach extra data for the pivot table when saving a single record, but don't know how to do this (or if it's even possible) when passing an array to attach() or sync(), as shown above.
The only ways I can see to do it are:
loop over the array, calling attach() once for each entry and passing along the current counter index as sort_order.
first detach() all associations and then pass mediaIds array to attach() or sync(). A side benefit would be that it eliminates the need for a sort_order column at all.
I'm hoping there is an easier solution that requires fewer trips to the database. Or am I just overthinking it and, in reality, doing the loop myself is really no different than letting Laravel do it further down the line when it receives the array?
[SOLUTION] I got it working by reshaping the array as follows. It explodes the comma-delimited 'mediaIds' request param and loops over the resulting array, assigning each media id as the key in the $mediaIds array, setting the sort_order value equal to the key's position within the array.
$rawMediaIds = explode(',', request('mediaIds'));
foreach($rawMediaIds as $mediaId) {
$mediaIds[$mediaId] = ['sort_order' => array_search($mediaId, $rawMediaIds)];
}
And then sorted by sort_order when retrieving the Page's associated media:
public function media() {
return $this->belongsToMany(Media::class)->orderBy('sort_order', 'asc');
}
You can add data to the pivot table while attaching or syncing, like so:
$mediaIds = [
1 => ['sort_order' => 'order_for_1'],
3 => ['sort_order' => 'order_for_3']
];
//[STORE]
$page->media()->attach($mediaIds;
//[UPDATE]
$page->media()->sync($mediaIds);

Laravel Form Model Binding with Relationships

Is it possible to bind a form with a model that has relationships? For example I have a Order model that has a one to many with a Details model. That would save a lot of time with
#foreach($order->details as $detail)
{{ Form::text('product_name', Input::old('product_name') ? Input::old('product_name') : detail->product_name)
#endforeach
For a one-to-one relation it's possible to use something like this:
Form::text('detail[product_name]')
In this case $order->detail->product_name will be populated in the given text box if an instance of Order model is bound to the from using Form::model($order) with the related model Detail but it may not possible for one-to-many because simply there will be a collection and you need a loop.
To complete the answer of #WereWolf..
Make an array of product_name detail_names
Input class allow you to access nested array by dot notation, eg: orders.1.product_name
Don't forget the second argument of Input::old() or Input::get()
is the default value, so you can specify the DB value and avoid conditional test..
.
Form::text('detail_names['.$detail->id.']', Input::old('detail_names.'.$detail->id, $detail->product_name))
In your controller, something like that:
foreach(Input:get('detail_names') as $id => $product_name)
{
//...
}
Hope this will help you to save a bit of time.

Resources