I have two tabled called categories and resources table.
Basically each resource has a category and the category id is saved on a column called resource_category_id in resources table.
So in order to setup One To Many relationship between the Models, I did these:
Category:
class Category extends Model
{
protected $table = "categories";
protected $guarded = [];
public function resources()
{
return $this->hasMany(Resource::class);
}
}
Resource:
class Resource extends Model
{
protected $table = "resources";
protected $guarded = [];
public function category()
{
return $this->belongsTo(Category::class, 'resource_category_id');
}
}
And now I want to show all categories and the resources and that have the same resource_category_id like this:
#php($menuCounter = 0)
#foreach($categories as $cat)
<tr>
<td style="text-align:center">{{ ++$menuCounter }}</td>
<td style="text-align:center">{{ $cat->category_name }}</td>
<td>
<ul>
#foreach($category->resources() as $resource)
<li>{{ $ress->resource_name }}</li>
#endforeach
</ul>
</td>
</tr>
#endforeach
But now the categories are all appearing but the resources does not be shown and also no error returns!
So what's going wrong here?
How can I show the resources according to resource_category_id via Eloquent relationships methods?
Instead of:
#foreach($category->resources() as $resource)
do
#foreach($category->resources as $resource)
The first one is loading the builder, the second one the collection.
You can also specify the foreign key for resources relationship in Category Model:
public function resources()
{
return $this->hasMany(Resource::class, 'resource_category_id');
}
Related
Category Model
class Category extends Model
{
use HasFactory;
protected $fillable= ['name','number'];
public function news(){
return $this->hasMany(News::class);
}
News Model
class News extends Model
{
use HasFactory;
protected $fillable= ['cat_id','title','photo','description','author_id','status'];
public function category(){
return $this->belongsTo(Category::class);
}
public function author(){
return $this->belongsTo(Author::class);
}
Author Model
class Author extends Model
{
use HasFactory;
protected $fillable= ['name','status'];
public function news(){
return $this->hasMany(News::class);
}
There is a relationship between the 3 models. And I want to display category name instead of category_id in news-list.blade.php. I am getting a this error.
This is my controller function
public function news_index(){
$news= News::with('category')->get();
return view('News.list',compact('news'));
}
This is my blade page. I got an error when I typed $new->category->name instead of cat_id.
#foreach($news as $new)
<tr>
<th scope="row">{{$loop->iteration}}</th>
<td> {{$new->category->name}}</td>
<td> {{$new->title}}</td>
<td> #if($new->photo)
Görüntüle</td>
#endif
</td>
<td> {{$new->author_id}}</td>
<td> {{$new->description}}</td>
<td> {{$new->status}}</td>
<td>
<a class="btn btn-danger" onclick="return confirm('Silmek istediğinize emin
misiniz?')" href="{{route('news_delete', $new->id)}}"><i class="fa fa-trash"></i></a>
<a class="btn btn-primary" href="{{route('news_update',$new->id)}}"><i class="fa
fa-pen"></i></a>
</td>
</tr>
#endforeach
Here is my news migration table
public function up()
{
Schema::create('news', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('cat_id');
$table->string('title');
$table->string('photo');
$table->longText('description');
$table->unsignedBigInteger('author_id');
$table->boolean('status')->default('1');
$table->foreign('cat_id')->references('id')->on('categories')->onDelete('cascade');
$table->foreign('author_id')->references('id')->on('authors')->onDelete('cascade');
$table->timestamps();
});
}
You need to define your category foreign key explicitly while defining category relationships. Because your category foreign key is not category_id; it's cat_id.
For example, you need to define the category relationship in News model like below:
public function category()
{
return $this->belongsTo(Category::class, 'cat_id');
}
I had the same problem , and i solve it by this :
$new->category->name ?? None'
I guess you need to rewrite you news_index() function.
public function news_index(){
$news = News::with(array('category'=>function($query){
$query->select('id','name');
}))->get();
return view('News.list',compact('news'));
}
i hope this will work. you were not assigning anything to $news variable and passing it to view. $new was null.
<td>{{ $new->category->name ?? 'None' }}</td>
I was having this issue beacuase that name property was associated to a foreign key that could be NULL, so, when you call it throws the error.
You can avoid this specific problem that I have just menctioned like this.
Said by Levis in a comment: For php 8 and above using null safe operator:
$new->category?->name
With this, you can like ignore it if its null and it won't put
anything in that field.
And this one said by abdennour If you want to put some specific value if its null or you're working with PHP below 8:
$new->category->name ?? 'None'
With this, you can avoid if it's null and you're going to put in that field the string None when that value is null.
Check your tables. There has to be a match between the relationships.
Example:
users: id, book_id, name, email
books: id, title, price etc...
In the users table, the book_id, for example 5, must exist in books, otherwise the relationship will be lost and null errors will occur.
Such an ID may not exist. Check the ID column once
I can't access my MODEL field in my database
This is the code that I execute:
#foreach($clients as client)
{{$client->dependents->fname}}
{{$client->dependents->mname}}
{{$client->dependents->lname}}
#endforeach
This code returns an error : Property [fname] does not exist on this collection instance.
When I do this code:
#foreach($clients as client)
{{$client->dependents}}
#endforeach
This code returns a successful array of data.
This is my Client Model:
class Client extends Model
{
protected $guarded = [];
public function dependents() {
return $this->hasMany(Dependent::class);
}
}
And this is my Dependent Model:
class Code extends Model
{
protected $guarded = [];
public function client()
{
return $this->hasOne(Client::class);
}
}
How can I retrieve each field using the eloquent model method?
In order to access the fields on dependents model, you need to make a foreach, because the client model hasMany dependents and when you try to access simply $client->dependents->fname doesn't know which one to access.
So, you need to do the following:
#foreach($clients as $client)
#foreach($client->dependents as $dependent)
{{$dependent->fname}}
{{$dependent->mname}}
{{$dependent->lname}}
#endforeach
#endforeach
It is HasMany relation AND It returns multiple departments so that fname is undefined. Because it has an object of departments, not the department and you are missing $ from #foreach($clients as client).
#foreach($clients as $client)
#foreach($clients->dependents as $department)
{{$dependent->fname}}
{{$dependent->mname}}
{{$dependent->lname}}
#endforeach
#endforeach
Try this, It will work for you. Enjoy!
I'm trying to display a table in my view with contents that consists of information from my Location table (Addr, City, etc...) and Resource table (Name, Descr.), they're linked by ID's through a ResourceLocation Table. Here's what I have so far:
Resource Controller
....
public function resource()
{
$resources = Resource::all();
return view('pages.resource', compact('resources'));
}
public function location()
{
$locations = Location::all
return view (compact('locations'));
}
public function resourcelocation()
{
$resourcelocations = ResourceLocation::all();
return view (compact ('resourcelocations'));
}
...
ResourceLocation Model
/**
* Class ResourceLocation
*/
class ResourceLocation extends Model
{
...
public function resource ()
{
return $this->belongsTo('App\Models\Resource');
}
public function location ()
{
return $this->belongsTo('App\Models\Location');
}
}
Resource Model
/**
* Class Resource
*/
class Resource extends Model
{
...
/** A resource can have many locations */
public function location()
{
return $this->hasMany('App\Models\ResourceLocation');
}
}
Location Model
/**
* Class Location
*/
class Location extends Model
{
...
public function resource()
{
return $this->hasMany('App\ResourceLocation');
}
}
resource.blade.php
<table>
<tr>
<th>Resource Name</th>
<th>Description</th>
<th>Address</th>
<th>City</th>
<th>Zip Code</th>
<th>County</th>
</tr>
#foreach ($resourcelocations as $resourcelocation)
<tr>
<td> {{ $resourcelocation->id }}</td>
<td>
#foreach ($resourcelocation->resources as $resource)
{{ $resource->Name }},
#endforeach
</td>
<td>
#foreach($resourcelocations->locations as $location)
{{ $location->City }}
#endforeach
</td>
</tr>
#endforeach
</table>
I just wanted to add a column or two to see if it was working, but I keep getting an undefined variable on resourcelocations, still trying to wrap my head around laravel and how the relationships work, so maybe my logic is messed up. Any help would be great!
Thanks.
There seems to be some confusion in your relationships. I think it could work with the way you have it but you are making it much more confusing than it needs to be.
First, start with removing the ResourceLocation model. You can relate resources and locations directly without need of the intermediary model (you will still need that table though). This is what's called a belongs-to-many relationship.
I also recommend when you have a relationship which can return many records (for example if a resource can have many locations) you should name the method which relates these locations rather than location.
With all that in mind, your Resource model gets...
public function locations()
{
return $this->belongsToMany('App\Models\Location', 'ResourceLocation');
}
Where I put 'ResourceLocation', that should be whatever you named your pivot table.
Same for your Location model which receives.
public function resources()
{
return $this->belongsToMany('App\Models\Resource', 'ResourceLocation');
}
Now that should be greatly simplified, we just replaced 4 relationship methods and 3 models for 2 relationship methods and 2 models.
Now for your controller, it's much more efficient to use eager loading to grab all your resource locations.
$resources = Resource::with('locations')->get();
And in your view...
#foreach ($resources as $resource)
#foreach ($resource->locations as $location)
<tr>
<td>{{ $resource->id }}</td>
<td>{{ $location->name }}</td>
</tr>
#endforeach
#endforeach
In your Resource Controller you are not passing any resourcelocation variable as I can see only resources has been called. try declaring the variable in array in this line return view('pages.resource', compact('resources'));
To get the first element in hasMany you can try below:
$resource->location()->first();
you can use dd(variable_name) before sending the data to the view to get a better idea of how your data is managed
I have a problem with one to many relationship in Laravel. I cannot retrieve my data from database. My codes are following.
Doctor.php
public function cities()
{
return $this->belongsTo('App\City');
}
City.php
public function doctor()
{
return $this->hasMany('App\Doctor');
}
view
#foreach($doctors as $doctor)
<tr>
<td data-title="ID">{{ $doctor->id }}</td>
<td data-title="Name">{{ $doctor->name }}</td>
<td data-title="Hospital">{{ $doctor->hospital }}</td>
<td data-title="Designation">{{ $doctor->designation }}</td>
<td data-title="City">{{ $doctor->cities->name }}</td> <!-- problem in this line -->
</tr>
#endforeach
When I try to view the data an error has been shown:
ErrorException in 3d7f581c490d492093e6e73f8ebd29525504e56b.php line 46:
Trying to get property of non-object (View: D:\xampp\htdocs\tourisms\root\resources\views\doctors\index.blade.php)
On the belongsTo side of the relationship, when the foreign key name is not specified, it is built using the name of the relationship. In this case, since your relationship is named cities, Laravel will look for the field doctors.cities_id.
If your foreign key is not cities_id, then you need to either change the name of your relationship method, or specify the name of the foreign key:
public function cities() {
return $this->belongsTo('App\City', 'city_id');
}
// or, better:
public function city() {
return $this->belongsTo('App\City');
}
Also, as mentioned by #Christophvh, the naming of your relationships is a little off, but not programmatically incorrect. It makes more sense and is more readable when belongsTo/hasOne relationships are named singular, and belongsToMany/hasMany relationships are named plural.
You are trying to loop a Collection and not an array.
2 solutions:
1)
add ->get(); when you are calling your relationship in your controller
2)
use
#foreach($doctors->all() as $doctor)
instead of
#foreach($doctors as $doctor)
Also a quick tip:
Your naming is not really telling what you are doing. You should swap them around like below. 'A doctor belongs to a city' & 'A city has many doctors'
Doctor.php
public function city()
{
return $this->belongsTo('App\City');
}
City.php
public function doctors()
{
return $this->hasMany('App\Doctor');
}
Ok, can anyone help me with this scenerio? I want to make a loop of Divisions and an inner loop of all the teams in that division using relationships in Eloquent. Been googling and expermenting but can't get the right results.
My tables are as such:
Divisions
division_id INT PK
division_name VARCHAR
...
Teams
team_id INT PK
team_name VARCHAR
...
division_team (pivot table)
id INT PK
division_id INT FK
team_id INT FK
My Models are as such:
DivisionTeamPivot
class DivisionTeamPivot extends \Eloquent {
protected $fillable = [];
protected $table = 'division_team';
public function team(){
return $this->belongsTo('Team');
}
public function division(){
return $this->belongsTo('Division');
}
Divisons
class Division extends \Eloquent {
protected $primaryKey = 'division_id';
public function teams(){
return $this->hasMany('Team','division_team','division_id','team_id');
}
}
Teams
class Team extends \Eloquent {
protected $primaryKey = 'team_id';
public function division(){
return $this->belongsTo('Division','division_team','team_id','division_id');
}
}
My Controller has:
$divisions = DivisionTeamPivot::with('Team','Division')->get();
My View:
<section class="panel">
<header class="panel-heading">
<h5>{{$division->division->division_name}} Division {{$i}}</h5>
</header>
<table class="table">
<thead>
<tr>
<th></th>
<th>Team Name</th>
<th class="center">Total Points</th>
<th class="center">Rank</th>
</tr>
</thead>
<tbody>
#foreach($division->team as $team)
<tr>
<td width="75"><img src="/img/logos/{{team->team_logo}}" width="50"></td>
<td> {{team->team_name}}</td>
<td class="center">1,345</td>
<td class="center">1</td>
</tr>
#foreach
</tbody>
</table>
</section>
What I want to do is loop over the divisions and then sub loop the teams that are in those divisions. I saw someone on here to make a pivot table model but when I use it, it loops over all the same divisions based off the division_id table in the pivot but I get the name. Its creating one team per duplicate division. I need them grouped based on the divisions they are in. And, actually, I still can't get the teams name to show. I also really want the eager loading to be working so I get the most efficient queries I can. Thanks!!
For making the many-to-many relationship you need to use belongsToMany instead of belongsTo in your both models (Division and Team) and you don't need to use another model as DivisionTeamPivot for pivot table. So in Division and Team use belongsToMany method:
// Division Model
public function teams(){
return $this->belongsToMany('Team', 'division_team', 'division_id', 'team_id');
}
// Team Model
public function divisions(){
return $this->belongsToMany('Division', 'division_team', 'team_id', 'division_id');
}
Make the query like this:
$divisions = Division::with('teams')->get();
return View::make('viewname')->with('dvisions', $divisions);
In the view the nested loops could be something like this:
#foreach($divisions as $division)
{{ $division->division_name }}
#foreach($division->teams as $team)
{{ ... }}
{{ $team->team_name }}
#endforeach
#endforeach