Laravel 5.3 access hasone in elequant from view - laravel

I'm trying to access a relations table from a collection of data passed in from the controller. I am able to iterate the collection in my view but I am unable to access the relationship data.
There are 2 tables:
stocks (default model)
stock_datas (has a foreign key stock_id which is already setup)
Controller:
public function getstock() {
return view('vehicles.getstock', ['stock' => \App\Stock::all()]);
}
Model (App\Stock) and then (App\StockData)
// From stock model:
public function stockdata() {
return $this->hasOne('App\StockData');
}
// Stock Data model:
public function stock() {
return $this->belongsTo('App\Stock');
}
View (loop):
#foreach ($stock as $k => $v)
{{ print_r($v->stockdata()->get())->year }}
#endforeach
When I try the query below, I get a
Undefined property: Illuminate\Database\Eloquent\Collection::$year (View: F:\websites\tempsite\resources\views\vehicles\getstock.blade.php)
However, year is a column in the stock_datas table.
I am also able to print_r data from the \App\StockData() table so the reference to the table is correct as doing print_r(\App\StockData::all()) from the controller does return all the rows as expected.
What am I doing wrong?

Since it's one to one relation, you should do it like this:
#foreach ($stock as $v)
{{ $v->stockdata->year }}
#endforeach

First one You have to change {{ print_r($v->stockdata()->get())->year }} this line, remove print_r. Next one in foreach loop you can do something like this
#foreach($stock as $one)
{{ $one->stockadata()->first()->year }}
#endforeach
For better solution you should check if isset $one->stockadata()->first()
and after that call ->year. Finally code should be like this
#foreach($stock as $one)
{{ isset($one->stockadata()->first()) : $one->stockadata()->first()->year : 'Default' }}
#endforeach

When calling get() method on any relationship You will always receive collection, no matter what relationship You have.
There are at least two (2) ways to solve Your problem:
1. $v->stockdata->year
2. $v->stockdata()->first()->year
I would suggest You to use first one, because Your stockdata has 1:1 relationship.
Good luck!

For example:
Stock.php model
class Stock extends Model
{
protected $primaryKey = 'id';
function stockdata() {
return $this->hasOne('App\StockDatas', 'id', 'stock_id');
}
public function getStock(){
return Stock::with('stockdata')->get();
}
}
In contriller
public function getstock(Stock $stock) {
return view('vehicles.getstock', ['stock' => $stock->getStock]);
}
view
#foreach ($stock as $k => $v)
{{ $v->stockdata->year }}
#endforeach

Related

Laravel Eloquent "With" and sub "With" relationship query -> pass Column Value as Where clause

I have 3 Models "Category" (tableName = 'categories'), "Brand" ('brands'), "Item" ('items')
Can I pass parent column value (e.g. categories) to use it in the Where clause?
Simple example:
Category::with(['brands' => function ($q) {
$q->with(['items' => function ($query) use ($localWhereHas) {
$query->whereColumn('category_id', 'categories.id');
}]);
}]);
Relations are:
Category Model:
public function brands(): BelongsToMany
{
return $this->belongsToMany(Brand::class, 'category_brands')->withPivot('is_visible', 'addon_price');
}
Brand Model:
public function items(): HasMany
{
return $this->hasMany(Item::class, 'brand_id');
}
Item Model:
public function category(): BelongsTo
{
return $this->belongsTo(Category::class, "category_id");
}
The main idea is that I need the structure to be nested like this Category->Brands->Items
The backup plan is to fetch All needed Categories and Foreach them to get as many as categories I have all Brands->Items, using categoryId ($category->category_id) .... but I don't like it
No, you can't pass it directly because it is not the same context.
If you want to have a display like this :
Category
-brand
-item
Then you should maybe just group your items by brand :
$categories = Category::with('items.brand')->get();
#foreach($categories as $category)
{{ $category->name}}
#foreach($category->items->groupBy('brand_id') as $brand_id => $items)
{{ $items->first()->brand->name }}
#foreach($items as $item)
{{ $item->name }}
#endforeach
#endforeach
#endforeach

accessing collections within collections laravel 5

I have a table of "rosters" that's pretty much strictly foreign keys. It acceses the "schools" table, "courses" table, and "students" table. So essentially, a 'student' takes a 'course' at a 'school'. My RostersController has this
public function show($id)
{
$roster = Roster::where('course_id', $id);
return view('roster')->with('roster', $roster);
}
My Roster Model is:
public function students()
{
return $this->hasMany('App\Student');
}
My student Model is:
public function roster()
{
return $this->belongsTo('App\Roster');
}
my view is this:
#foreach ($roster as $child)
<p>{{$child->id}}</p>
<p>{{$child->students->first_name}}</p>
#endforeach
The rosters table just saves the student_id rather than all of the student's data that is already in the 'students' table. So i'm trying to access the students table from this relation but when i run this, it tells me that anything related to the students table is 'not on this collection'. I know that I could do things this way if i was working with a hasOne relationship, but how can i accomplish this with a hasMany to output the students table value in each row?
You should try this
public function show($id)
{
$roster = Roster::with('students')->where('course_id', $id);
return view('roster')->with('roster', $roster);
}
Try this
Roster.php
public function show($id)
{
$roster = Roster::with('students')->where('course_id', $id)->get(); // load the students
return view('roster')->with('roster', $roster);
}
On the view
#foreach ($roster as $child)
<p>{{$child->id}}</p>
<p>
<!-- Loop through the stundents since this returns an collection of students and not just one -->
#foreach($child->students as $student)
{{$student->first_name}} <br>
#endforeach
</p>
#endforeach
Check this for more information on eager loading
The $child->students is a collection. So, you need to use another foreach loop inside the first one.
Your code should look like this:
#foreach ($roster as $child)
<p>{{$child->id}}</p>
#foreach($child->students as $student)
<p>{{$student->first_name}}</p>
<p>{{$student->age}}</p>
<p>{{$sutdent->another_column_in_students_table}}</p>
#endforeach
<p>{{$child->any_other_column_in_roster_table_if_needed}}</p>
#endforeach
So, your first issue is, that
$roster = Roster::where('course_id', $id);
will just return a QueryBuilder instance, you have to use
$roster = Roster::where('course_id', $id)->get();
then for sure, students is a collection, you have to iterate over it like this:
#foreach ($child->students as $student)
{{ $student->yourProperty}} <br>
#endforeach
Update:
I saw you know already about that when to use get() in query laravel 5

How to retrieve user name from user table by using data (user_id) from another table having relationship

I have two models
User.php
public function opportunities()
{
return $this->hasMany('App\Opportunity');
}
Opportunity.php
public function user()
{
return $this->belongsTo('App\User');
}
I have user_id column in opportunities table and inserted user id (from user table using Auth) every time user posts record.
Now i need a view to return "this post is posted this user".
First I find the post id by
$posts = Opportunity::find($id);
$posted_by = User::find($posts->user_id);
return view('opportunity.detail')->with('post', $posts, 'posted_by', $posted_by);
I have rendered user name by {{$posted_by->name}}
But I got undefined constant in the view file $posted_by while $post is fine. Am I doing it in right way or not? I am passing two array variable to the post and its not working. Any help will be appreciated.
Your controller could look like:
return view('opportunity.detail', [
'post' => Opportunity::find($id);
]);
In the view to show user name:
Post {{ $post->title }} posted by {{ $post->user->name }}
https://laravel.com/docs/5.5/eloquent-relationships#relationship-methods-vs-dynamic-properties
If for some reason you want to use ->with(), do this:
->with(['post' => $posts, 'posted_by' => $posted_by]);
Or:
->with('post', $posts)->with('posted_by', $posted_by);
You can put this
public function getUserName() {
return User::where('id', $this->user_id)->first()->name;
}
in your Opportunity.php model and call it in you view
#foreach ($posts as $post)
{{ $post->getUserName() }}
#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 access relation

I want to access a relation of the model when I get all the results but I keep getting the following error:
Undefined property: Illuminate\Database\Eloquent\Collection::$voornaam
Code:
- Model : Selectie.php
public function User()
{
return $this->hasMany('User', 'id', 'user_id');
}
- Controller
$selectie = Selectie::where('wedstrijd_id', '=', $id)->get();
return View::make('base.match.show')->with('selectie', $selectie);
- View
#foreach($selectie as $sel)
{{ $sel->user->voornaam }}
#endforeach
You have One to Many Relation in Selectie model. That means , $sel->user returns Collection Array , you cant reach array attributes like that.
#foreach($selectie as $sel)
#foreach($sel->user as $user)
{{ $user->voornaam }}
#endforeach
#endforeach
Try like this , otherwise you have to change your Selectie Model - User Model Relation type with One-To-One

Resources