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');
}
Related
I want to get department_name from department table
with
table department = id, department_name, total_employee
table employee = id, employee_name, id_department, email, telephone, gender, status
I tried
model.Employee
public function department()
{
return $this->belongsTo(Department::class);
}
controllers.EmployeeControllers
public function index()
{
$data_employee = Employee::with('department')->get();
return view ('employee.index', compact('data_employee '));
}
with view
#forelse ($data_employee as $item)
<tr>
<td class="text-center">{{ $item->employee_name}}</td>
<td class="text-center">{{ $item->department->department_name}}</td>
<td class="text-center">{{ $item->email}}</td>
<td class="text-center">{{ $item->telephone}}</td>
</tr>
#endforelse
But then it said
Attempt to read property "department_name" on null
What do I do wrong.
First of all you need to write your relationship properly.
public function department()
{
// You have to provide correct model name here.
return $this->belongsTo(Department::class);
}
Secondly Eloquent determines the foreign key name by examining the name of the relationship method and suffixing the method name with _id. So, in your case, Eloquent assumes that the Employee model has a department_id column. But, the foreign key on the Phone model is not department_id , you may pass a custom key name as the second argument to the belongsTo method
public function department()
{
return $this->belongsTo(Department::class, 'id_department');
}
Source here
Please replace model.Employee
public function department()
{
return $this->belongsTo(Department::class, 'id_department');
}
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 have two table as sbj_topics and difficulty_level_sbj_topic so, I want to define relationship b\w them to fetch records, so to make relationship I have done this,
SbjTopic.php:
public function difficulty_level_sbj_topic() {
return $this->hasMany('App\DiffiLvlSbjTopic');
}
And in DiffiLvlSbjTopic.php:
protected $table = 'difficulty_level_sbj_topic';
public function sbj_topics() {
return $this->belongsTo('App\SbjTopic');
}
After that I returned the data to a view as:
$easy = DiffiLvlSbjTopic::where(['subject_id' => $id, 'difficulty_level_id' => 2])->get();
return view('diffi_lvls.show', compact('easy'));
Then in the view I done this:
#foreach($easy as $easy)
{{ $easy->sbj_topics }}
#endforeach
but the page is blank, and when I do this {{ $easy->sbj_topics->sbj_topic_name }} trying to get property of undefined! comes.
The main purpose of creating relationship is to display Subject Topic Name because I have foreign key as sbj_topic_id in difficulty_level_sbj_topic table so if anyone has any other idea to do this without relationship that will be awesome.
Break this down:
SbjTopic - has many difflevels
a difflevel belongs to aSbjTopic
With this understanding, I can see you are getting the difflevels (DiffiLvlSbjTopic). This is actually what you are passing to your blade.
So first off: complete your relationship by specify the foreign keys. i.e:
In the SbjTopics model:
public function difficulty_level_sbj_topic() {
return $this->hasMany('App\DiffiLvlSbjTopic', 'subject_id');
}
with this, you know that in the 'difficulty_level_sbj_topic' you must have the column subject_id.
Now define the reverse relationship in your DiffiLvlSbjTopic model:
public function sbj_topics() {
return $this->belongsTo('App\SbjTopic', 'subject_id');
}
With all these in place in your controller or route all you need to do is fetch the DiffiLvlSbjTopic model properties. For instance:
public function index () {
$easy = DiffiLvlSbjTopic::all();
return view('diffi_lvls.show', compact('easy'));
}
Finally in your view:
#foreach($easy as $difflevel)
<div>{{ $difflevel->sbj_topics->name }} </div>
#endforeach
That's it.
Your both variables should not be $easy it can be something like $easy as $easySingle. And add a loop inside like
#foreach($easy as $easySingle)
foreach ($easySingle->sbj_topics as $topic) {
$topic->property;
}
#endforeach
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 two models: MenuCategory and MenuItem, I want to display MenuItem data on my blade page along with its MenuCategory. I know its possible to do this by adding it to the return data in my controller however I would like to do it leveraging Eloquent instead, however I receive errors.
Here are my codes:
MenuCategory model
public function items()
{
return $this->hasMany('App\MenuItem');
}
MenuItem model
public function category()
{
return $this->belongsTo('App\MenuCategory');
}
Controller
public function show($id)
{
$item = MenuItem::findOrFail($id);
return view('menu.admin.single', compact('item'));
}
Blade Page
{{ $item->category->name }}
UPDATE:
Table menu_item
id
name
menu_category_id
Table menu_category
id
name
When using all the above I get the following error:
Trying to get property of non-object
This error is due to the naming convention of Eloquent.
Provide the optional foreign key variable in your relationship method to make it work, ie.
$this->belongsTo('App\MenuCategory', 'menu_category_id');
Probably every Item doesn't contain a related category but to make sure you may try something like this, it'll try to retrieve the name only if there is a related category is available:
{{ $item->category ? $item->category->name : 'No Name or empty string' }}
Alternatively you may try something like this:
$item = MenuItem::has('category') // check if there is a related category
->with('category') // if yes then load it with that category
->findOrFail($id);
You used a different foreign key than Laravel expect so explicitly mention it like:
public function category()
{
return $this->belongsTo('App\MenuCategory', 'menu_category_id', 'id');
}