Retriving All Polymorphic Relations in Laravel - laravel

I've created polymorphic relations in my project. when i want to retrieve them like below
return view('category.index')->with('categories', Category::all()) ;
It returns the relations when i dd() them. However when I want to access the relation in view
when i call it in view it gives me the following result
{"id":1,"image":"abc\/abc.jpg","imageable_id":6,"imageable_type":"App\\Category","created_at":"2020-07-24T13:37:29.000000Z","updated_at":"2020-07-24T13:37:29.000000Z"}
but when i want to access the id or image index it says
Trying to get property 'id' of non-object (View:
D:\WaheedSindhani\Projects\Menu\menu_proj\resources\
views\category\index.blade.php)
i am not picking it up what is happening here
#if(isset($categories))
#foreach($categories as $category)
<tr>
<th scope="row">{{$loop->index+1}}</th>
<td>{{$category->name}}</td>
<td>{{$category->images->image}}</td>
</tr>
#endforeach
#endif
It says no attribute named image found.
Migration are as below
Images Table
public function up()
{
Schema::create('images', function (Blueprint $table) {
$table->id();
$table->string('image');
$table->unsignedInteger('imageable_id');
$table->string('imageable_type');
$table->timestamps();
});
}
Menus Table
public function up()
{
Schema::create('menus', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->boolean('visible');
$table->integer('priority');
$table->timestamps();
});
}
Categories Table
public function up()
{
Schema::create('categories', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->boolean('visibility');
$table->integer('priority');
$table->timestamps();
});
}
Models are as follow
class Menu extends Model
{
public function images()
{
return $this->morphMany( 'App\Image', 'imageable');
}
}
class Image extends Model
{
protected $guarded = [];
public function imageable(){
return $this->morphTo();
}
}
class Category extends Model
{
protected $guarded = [];
public function images()
{
return $this->morphMany(Image::class, 'imageable');
}
}

your problem occurs because the category->images is a Collection of images, not a single image. Because your relation is one to many, not one to one relationship so the soultion would be to loop over the images using a each loop and then do your work there.
that is why you are getting the error that you are trying to access a prop on a non-object.
#if(isset($categories))
#foreach($categories as $category)
<tr>
<th scope="row">{{$loop->index+1}}</th>
<td>{{$category->name}}</td>
#foreach($category->images as $image)
<td>{$image->name}</td>
#endforeach
</tr>
#endforeach
#endif
and this concept is true for every relationship that has a Many in them, hasMany, belongsToMany, etc...

Related

i am trying to get the name using a relationship

here what I am trying to get the name of the category by using a relationship
here so far what I have done is I have defined a relationship in my product model as such
Public function category()
{
return $this->belongsto(Category::class);
}
I have also stored the field category id
in my products table
Schema::create('products', function (Blueprint $table) {
$table->increments('id');
$table->integer('Category_id');
$table->string('name');
$table->string('code');
$table->string('color');
$table->string('description');
$table->double('price');
$table->integer('quantity');
$table->string('image');
$table->timestamps();
});
also I have defined a relationship in my Category model such as
public function product()
{
return $this->hasmany(Product::class);
}
ALSO I HAVE DEFINED Relationship IN
PRODUCT AS
Public function category()
{
return $this->belongsto(Category::class);
}
in my view I am trying to get the name of the category
#foreach($products as $pro)
<tr>
<td><img src="{{asset('uploads/maj/'.$pro->image)}}" class="img-circle" alt="User Image" width="50" height="50"> </td>
<td>{{$pro->category->name}}</td>
<td>{{$pro->name}}</td>
<td>{{$pro->code}}</td>
<td>{{$pro->color}}</td>
<td>{{$pro->description}}</td>
<td>{{$pro->price}}</td>
<td>{{$pro->quantity}}</td>
I am receiving the error
Trying to get property 'name' of non-object
how can I get the name of the category ??
I am trying to get it like this but this is giving error
{{$pro->category->name}}
the category table row
Schema::create('categories', function (Blueprint $table) {
$table->increments('id');
$table->String('Parent_id');
$table->string('name');
$table->string('status');
$table->timestamps();
});
my laravel version is 7 thanks
Maybe one or more product doesn't have category or category_id is wrong.
you can use condition to check if category is not exist:
{{$pro->category ? $pro->category->name : "no category"}}
or can simply using null coalescing operator:
{{$pro->category->name ?? "no category"}}
if category is required you should prevent it by add table relation/foreign.
try this
Schema::create('products', function (Blueprint $table) {
$table->increments('id');
$table->foreignId('category_id')->nullable()->constrained()->onDelete('cascade');
$table->string('name');
$table->string('code');
$table->string('color');
$table->string('description');
$table->double('price');
$table->integer('quantity');
$table->string('image');
$table->timestamps();
});
in model Product
public function category(){
return $this->belongsTo(Category::class,'category_id','id');
}
thin call products
$products = product::orderBy('created_at','asc')->with('category')->get();
you can chick if has relationship or not
#if(! empty($pro->category)) {{ $pro->category->name }} #else <span>no category</span> #endif
You should try like this way :
(!empty($pro->category)) ? $pro->category->name : 'No category found'
I think You should define foreign key properly because your category_id not follow the coding standard. if you Category Model are in App directory you can use pass namespace like this
Public function category()
{
return $this->belongsto('App\Category','Category_id','id');
}
other wise :
Public function category()
{
return $this->belongsto('App\Models\Category','Category_id','id');
}

How to return name of table of grade when save like json?

I have two tables, users and grades.
users table
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->string('first_name')->nullable();
$table->string('last_name')->nullable();
$table->string('grade_id')->nullable();
}
}
grades table
public function up()
{
Schema::create('grades', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->timestamps();
});
}
I save id of grade with json_encode,
I save in field like this
$user->grade_id = json_encode($request->input('grade_id'));
I want to return the grade name but I did not solve my problem
Controller
public function index()
{
$grades = Grade::all();
return view('index', compact('grades');
}
User.php
public function grade()
{
return $this->belongsTo(Grade::class);
}
index.blade.php
#if(isset(auth()->user()->grade_id) && !empty(auth()->user()->grade_id))
<?php
$grade = json_decode(auth()->user()->grade->name, true);
#foreach($grade as $key=>$item)
<li>
<div class="grade">{{ $grade[$key] }}</div>
</li>
#endforeach
?>
#endif
I get this errpr
Trying to get property of non-object
Bad answer
You save an array of ids in the users table. Then when you do $grade = json_decode(auth()->user()->grade->name) you get something you don't want to have. Indeed, the value of auth()->user()->grade is ["8", "8"], this is not a grade model. Now you should understand why this $grade = json_decode(auth()->user()->grade->name) fail: you're trying to get name property of a non object (as user()->grade is just an array).
To solve it badly (read the next part of my answer) you can just do this in your controller (you shouldn't do any <?php ?> in your view files):
public function index()
{
$grades_ids = json_decode(auth()->user()->grade); // ["8", "8"]
$grades = Grade::whereIn('id', $grades_ids)->get(); // Eloquent collection
return view('index', compact('grades');
}
And use it in your view:
#if($grades->count())
<ul>
#foreach($grades as $grade)
<li>
<div class="grade">{{ $grade->id }}</div>
</li>
#endforeach
</ul>
#endif
Good answer
Here you have a typical many to many relationships. A grade can have multiple users, and a user can have multiple grades. Then you should think of using a pivot table rather than a encoding several grade_id in json.
Create a users table:
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->string('first_name')->nullable();
$table->string('last_name')->nullable();
}
}
Then you create your grades table:
public function up()
{
Schema::create('grades', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->timestamps();
});
}
Then you create the new user_grade_table:
public function up()
{
Schema::create('user_grade', function (Blueprint $table) {
$table->primary(['user_id', 'grade_id']);
$table->unsignedBigInteger('user_id');
$table->unsignedBigInteger('grade_id');
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->foreign('grade_id')->references('id')->on('users')->onDelete('cascade');
});
}
public function down()
{
Schema::table('user_grade', function (Blueprint $table) {
$table->dropPrimary('user_grade_user_id_grade_id_primary');
$table->dropForeign('user_grade_user_id_foreign');
$table->dropForeign('user_grade_grade_id_foreign');
});
Schema::dropIfExists('user_grade');
}
Don't forget to run the migrations. When this is done, you have to update your models, adding the belongs to many on both models.
User model
public function grades()
{
return $this->belongsToMany(Grade::class, 'user_grade', 'user_id', 'grade_id');
}
Same for grade model:
public function users()
{
return $this->belongsToMany(User::class, 'user_grade', 'grade_id', 'user_id');
}
Finally you can use it in your blade file:
#if($grades = auth()->user()->grades)
<ul>
#foreach($grades as $grade)
<li>
<div class="grade">{{ $grade->name }}</div>
</li>
#endforeach
</ul>
#endif

Laravel: Retrieving Data in Loop in a One to Many Relationship

I'm using Laravel 5.8. Here's my code...
CreateSchoolsTable migration
public function up()
{
Schema::create('schools', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->timestamps();
});
}
CreateStudentsTable migration
public function up()
{
Schema::create('students', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('school_id');
$table->string('first_name');
$table->timestamps();
});
}
School model
class School extends Model
{
public function students()
{
return $this->hasMany('App\Student');
}
}
Student Model
class Student extends Model
{
public function school()
{
return $this->belongsTo('App\School');
}
}
Controller
class SchoolsController extends Controller
{
public function index()
{
$schools = School::all();
return view('schools.index', compact('schools'));
}
}
My view: views>schools>index.blade.php
#foreach ($schools as $school)
{{ $school->students->first_name }}
#endforeach
I want to display all the first names in the loop and $school->students->first_name gives me an error.
Property [first_name] does not exist on this collection instance. (View: /Users/philginsburg/Laravel/project1/resources/views/schools/index.blade.php)
When I echo out $school->students it displays an array of the students table, but not sure why I cant loop through with the field name like first_name.
In this case you are dealing with 2 Collections: schools and students (of each school), so you should use 2 different loop to loop through those collections, like this:
#foreach ($schools as $school)
<p>In this school there are those students:</p>
<ul>
#foreach($school->students as $student)
<li>{{ $student->first_name }}</li>
#endforeach
</ul>
#endforeach
The reason is $school->students is array, there is no property called first_name.
you need to
#foreach ($school->students as $student)
{{ $student->first_name }}
#endforeach

Eloquent Relationship returning empty array

I'm New to laravel and I'm trying to achieve something very basic stuff but still getting stuck.
I have two models namely Post.php and Like.php
I'm trying to fetch all the likes linked to a post using eloquent relationship but it is returning an empty array. Here is my code-
Post.php
public function likes(){
return $this->hasMany('App\Like');
}
Route.php
Route::get('/', function(){
$posts = Post::all()->sortByDesc("post_id");
return view('index')->with(['posts' => $posts]);
});
View.blade.php
#foreach($posts as $post)
{{ $post->likes }}
#endforeach
What am I doing wrong here?
Update-
likes table migration
public function up()
{
Schema::create('likes', function (Blueprint $table) {
$table->increments('like_id');
$table->integer('post_id')->unsigned();
$table->integer('user_id')->unsigned();
$table->foreign('post_id')->references('post_id')->on('posts')->onDelete('cascade');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->timestamps();
});
}
Post Migration
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->increments('post_id');
$table->integer('user_id')->unsigned();
$table->string('post_message');
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
});
}
Post Model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
public function user(){
return $this->belongsTo('App\User');
}
public function likes(){
return $this->hasMany('App\Like');
}
}
Laravel expects the primary key to be id, but you are using the custom post_id.
Specify it in your model and adjust the relationship:
class Post extends Model {
protected $primaryKey = 'post_id';
public function likes() {
return $this->hasMany('App\Like', 'post_id');
}
}

Laravel - must return a relationship instance exception handling

I would like to display employee department based on this relation
here is the JobHistory table schema
Schema::create('JobHistories', function (Blueprint $table) {
$table->increments('id');
$table->integer('employees_id');
$table->integer('Jobs_id');
$table->integer('Departments_id');
$table->date('start_date');
$table->timestamps();
});
here is the employee model
public function jobs(){
return $this->hasMany(JobHistory::class,'employees_id','id');
}
public function getDepartment()
{
$dep = JobHistory::where('employees_id', $this->id)->orderBy('start_date', 'desc')->first();
return ($dep) ? $dep->department() : '';
}
here is function on JobHistory Model
public function department()
{
return $this->belongsTo(Department::class, 'Departments_id', 'id');
}
And finally I want to display it on view like this:
#foreach($employee as $row)
<tr>
<td>{{$row->name}}</td>
<td>
{{$row->getDepartment->name or '-'}}
</td>
</tr>
#endforeach
The question is, how to handle exception if an employee does not have any job history yet? I have try using is_null(), empty() and isset() on blade validation. but nothing works.
You can Use ternary operator
Here is solution to your problem
{{isset($row->getDepartment->name) ? $row->getDepartment->name : '-'}}
Hope it will work for you

Resources