Assigning a variable to each row from a Get query - laravel

In my controller, I'm selecting all rows from a table, lets call it Users.
$users = User::get();
Let's say I want to assign a variable to each row from the Users table, that determines how old they were 10 years ago
I'm assuming I have to use a foreach
foreach ($users as $user) {
$decadeAgo = $user->age - 10;
}
Now in my blade, how can I display each user row, while also displaying the $decadeAgo variable?

try this as official laravel suggestion for blade templates:
#foreach ($users as $user)
<p>{{ $user->age - 10 }}</p>
#endforeach

You can iterate over the results and address each object by reference:
foreach ($users as &$user) {
$user->decadeAgo = $user->age - 10;
}
Then, in your blade template you will have access to the element you created on the $user object.
{{ $user->decadeAgo }}

Related

How to included joined data in a loop

I am displaying a list on my blade view which contains data from the display table: name, school and IP.
The school is saved as a school id in this table.
The Schools table contains the list of ids and related schools.
I want to use the school names from the schools table and display them on my blade view.
I can get this data separately.
This gets all the data from the display table
$records = DB::table('display')->paginate(10);
This gets all the school name from the schools table.
$schools = DB::table('schools')
->join('display', 'schools.id', '=', 'display.school')
->select('schools.name')
->get();
To display the data from the display table I'm using a foreach loop.
#foreach ($records as $record)
{{ $record->name }}
{{ $record->school }}
{{ $record->ip }}
#endforeach
I don't know how to insert the school name into the space where currently $record->school appears. $record->school displays the school ID, but I want to display the school name which is saved in the school table.
Display model
public function school()
{
return $this->belongsTo('App\School');
}
School model
public function display()
{
return $this->hasMany('App\Display');
}
If you have models and Eloquent relations, you can simply use it:
Controller
$records = Display::with('school')->paginate(10);
Blade view
#foreach ($records as $record)
{{ $record->name }}
{{ $record->school->name }} <!-- school name via relation -->
{{ $record->ip }}
#endforeach
Display Model
class Display extends Model
{
public function school()
{
return $this->hasOne('App\School');
}
}
You really should be using Eloquent as it makes life so much easier. However, using DB, you need code similar to below, where you are joining schools as a relationship to display.
$records = DB::table('display')
->join('schools', 'schools.id', '=', 'display.school')
->paginate(10);
#foreach ($records as $record)
{{ $record->name }}
{{ $record->schools->name }}
{{ $record->ip }}
#endforeach

Laravel array shows as null before data array

I have a user that has many properties. This is user should also be able tp view the offers bet on his properties.
So have the relationship set.
User.php
public function properties(){
return $this->hasMany('App\Property');
}
Property.php
public function offers(){
return $this->hasMany('App\Offer');
}
Then in my controller this is what I have:
public function my_offers(){
$properties = Property::whereUserId(Auth::id())->get();
return view('pages.seller.offers.index', compact('properties'));
}
Then I go to my views like this:
#if($properties)
<ul>
#foreach($properties as $property)
<li>{{$property->offers->offer_message}}</li>
#endforeach
</ul>
#endif
When I view the page I see the below error:
Property [offer_message] does not exist on this collection instance.
But this property exists in my table.
If I change my list item to the one below I can see the array:
<li>{{$property->offers}}</li>
I also see that before and after the array with the data, there are two empty arrays as the image shows below:
Is there anything that I didn't correctly?
If not all the properties have offers, then you should check that before the <li>, besides that, offers is a collection, you need to loop through it, that's why you get the error.
#if($properties)
#php ($i = 1)
<ul>
#foreach($properties as $property)
#if ($property->offers)
#foreach ($property->offers as $offer)
<li>Offer {{ $i++ }}: {{$offer->offer_message}}</li>
#endforeach
#endif
#endforeach
</ul>
#endif
If you want to get only de properties that have offers (Querying Relationship Existence):
$properties = Property::whereUserId(Auth::id())->has('offers')->get();
And you should probably eager load that relationship:
$properties = Property::whereUserId(Auth::id())->has('offers')->with('offers')->get();

How to display records in view based on their first letter?

In my controller I am passing to a view a bunch of categories in alphabetical order like this :
public function index()
{
$categories = Category::orderBy('name', 'asc')->get();
return view('categories')->with('categories',$categories);
}
In my view, I want to display in separate columns corresponding to letters from the alphabet each of these categories, so in column "A" I will have all categories starting with A and so on.
Is it possible to filter the results in the view by letter in order to achieve this, and if yes, how can it be done?
You can group the list of categories by first letter in your controller and then pass the result to your view, here is how to do:
Controller:
public function index() {
$categories = Category::orderBy('name', 'asc')->get();
$groups = $categories->reduce(function ($carry, $category) {
// get first letter
$first_letter = $category['name'][0];
if ( !isset($carry[$first_letter]) ) {
$carry[$first_letter] = [];
}
$carry[$first_letter][] = $category;
return $carry;
}, []);
return view('categories')->with('groups', $groups);
}
View:
#foreach($groups as $letter => $group)
<ul>
<li>{{ $letter }}</li>
#foreach($group as $category)
<li>{{ $category['name'] }}</li>
#endforeach
</ul>
#endforeach
Here is a working example using array_reduce (it's the same as Collection::reduce function above)
In your view instead of using foreach use for and conditionally check the first letter of every current item with the first character of its previous item:
<h4>{{$categories[0]->name[0]}}</h4>
#for($i = 0; $i < count($categories); $i++)
#if($i > 0 && $categories[$i]->name[0] != $categories[$i-1]->name[0])
<h4>{{$categories[$i]->name[0]}}</h4>
#endif
.....
#endfor
Another fact used in this solution that you can access a character in a string by its index in that string. i.e we accessed the first character by its index 0 in the category name string.
If you want to load from database only categories with a specified first letter:
$categories = Category::where('name', 'like', 'A%')->orderBy('name', 'asc')->get();
If you want to load all categories and then filter them, use filter() method:
#foreach ('ABCDEFGHIJKLMNOPQRSTUVWXYZ' as $letter)
#foreach ($categories->filter(function($i) use($letter) { return starts_with($i->name, $letter); }) as $category)
{{ $category->name }}
#endforeach
#endforeach

How to pass variable from foreach to view in laravel 5.4?

I want to count each location in my Job table by using location_id in my job table with id in location table. below code, I can count result correctly but I don't know how to pass this variable to the view. Please help?
//my code
public function index(){
$location = Location::all();
$count_location = [];
foreach ($location as $locations){
$count_location = Job::where('location_id', $locations->id)->count();
}
}
Use withCount() and view() to pass location with counted jobs to the view:
public function index(){
return view('view.name', [
'locations' => Location::withCount('jobs')->get()
]);
}
In the view:
#foreach ($locations as $location)
{{ $location->name }} has {{ $location->jobs_count }} jobs
#endforeach
You can return the collection of locations to the view and then loop through each object in the collection like so:
return view('index', [
'locations'=> $locations,
]);
Then in your index.blade.php you can use something like a #foreach or #forelse loop
#foreach ($locations as $location)
{{ $location->id }}
#endfoeach
EDIT
From the looks of it you would be better off defining a relationship between locations and jobs (i.e. a "many to many" or "one to many" relationship). this would allow you to get the counts for jobs at given locations very easily like so:
$location->jobs->count()
Eloquent relationships are explained in the documentation here
https://laravel.com/docs/5.5/eloquent-relationships
It would be more efficient if construct your query to fetch the count of related models instead of looping through all the results.
Have a look at Counting Related Models in the documentations.
For example, to get the count of all jobs related to a location, you could do:
$locations = App\Location::withCount('jobs')->get();
foreach ($locations as $location) {
echo $location->jobs_count;
}
You need to adjust the code according to your models structure.
Do this
public function index(){
$locations = Location::all();
return view('index', compact('locations'));
}
In your Location model make a relationship by adding this
public function jobs(){
return $this->hasMany(Job::class);
}
In your index view do this
#foreach ($locations as $location)
{{$location->jobs->count}}
#endforeach
Please note that Job should be there in your your model

laravel-dompdf how to get multiple records into the data array

I have this code to try to generate a report on all records in a table:
$items = Line::all();
$data = $items->toArray();
$pdf = PDF::loadView('pdf.catalogue', $data);
return $pdf->stream();
How do I access the array in my Blade template? I have tried
#foreach ($data as $item)
but that does not work.
How you usually pass these variables into blade is by a named array, meaning you would assign it as so.
$data['items'] = $items->toArray();
In your template you should have the variables $items containing the array.
#foreach($items as $item)
...
#endforeach

Resources