Linking Multiple Tables in Laravel using Eloquent - php

I have 3 tables user table, countries table, personal_details table. The structure is as follows
Users:
Schema::create('users', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('role');
$table->string('email')->unique();
$table->integer('terms');
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
Countries:
Schema::create('countries', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('countrycode');
$table->string('countryname');
$table->string('code');
$table->string('flag');
$table->timestamps();
});
Personal Details:
Schema::create('personal_details', function (Blueprint $table) {
$table->bigIncrements('id');
$table->integer('user_id');
$table->string('first_name');
$table->string('last_name');
$table->string('sex');
$table->date('date_of_birth');
$table->string('country');
$table->string('freelancer_type');
$table->text('about_me');
$table->timestamps();
});
On the welcome page i need to display users profiles including country and associated flag. here is the code im using
Route
Route::get('/', function () {
$category = \App\Category::all();
$user = \App\User::all()->where('role', '==', 'Freelancer');
$post = \App\Post::paginate(3);
return view('welcome', compact('category', 'user', 'post'));
});
and the View
#foreach($user as $users)
<div class="col-lg-3 md-6 xs-6" style="text-align: center">
<div class="card-deck">
<div class="card shadow p-3 mb-5 bg-white rounded">
<div class="card-body">
<img src="/profile_images/{{$users->profileimage->image}}"
style="width: 100px; height: 100px; border-radius: 50%">
<p><span style="font-weight: 900; color: #009dba">{{$users->personaldetails->first_name}} {{$users->personaldetails->last_name}}</span>
<br/>
<span style="font-size: 11px">
{{$users->expertise->profession}}</span>
</p>
<p style="font-size: 11px">{{$users->personaldetails->country}},
ZAR{{$users->expertise->hourly_rate}}/hr</p>
<hr>
<p style="font-size: 11px">{{str_limit($users->personaldetails->about_me, $limit = 80, $end =
'...')}}</p>
{{$users->personaldetails->country->flag}}
<div style="padding-top: 10px"></div>
<a href="/users/{{$users->id}}">
<button>View Profile</button>
</a>
</div>
</div>
</div>
</div>
#endforeach
I am receiving the error Trying to get property 'flag' of non-object. Please help

In this line {{$users->personaldetails->country->flag}} you are calling for relational data. Your relational data is working in chain. First $user is calling relation of personal_details table. In the personal_details table you have stored user_id so the relationship is working. But when you are chaining countries table using personaldetails there will be no result as no relationship exists. You can see that your countries table holds information of only about country, no id of personal_details is stored as foreign key in your countries table. If you want to retrieve data through relations you must store id of personal_details table as foreign key in countries table. So if you store personal_detail_id in your country table, there should be no problem.
Your countries table should look like the following:
Schema::create('countries', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('personal_detail_id');
$table->string('countrycode');
$table->string('countryname');
$table->string('code');
$table->string('flag');
$table->timestamps();
});

Related

How to return specific assaing value from model when foreign key null Laravel

when a foreign key value is null I want to return a specific value from the model because when I delete the primary key id row and set a null value on the foreign key shows error. how to can I do it please anybody help me?
Here Is My Country Migration Table:
public function up()
{
Schema::create('countries', function (Blueprint $table) {
$table->id();
$table->string('name', 60)->nullable();
$table->string('country_code', 60)->nullable();
$table->string('capital', 120)->nullable();
$table->string('region', 120)->nullable();
$table->string('currency_code', 120)->nullable();
$table->string('currency_name', 120)->nullable();
$table->string('currency_symbol', 120)->nullable();
$table->string('language_code', 120)->nullable();
$table->string('language_name', 120)->nullable();
$table->bigInteger('flag')->unsigned()->nullable();
$table->foreign('flag')->references('id')->on('media_files')->onDelete('cascade')->onUpdate('cascade');
$table->string('dialling_code', 10)->nullable();
$table->integer('status')->default(0)->unsigned();
$table->timestamps();
});
}
Here Is My City migration Table:
Schema::create('cities', function (Blueprint $table) {
$table->id();
$table->string('name')->nullable();
$table->string('zipcode')->nullable();
$table->string('order')->default(null)->nullable();
$table->foreignId('country_id')->nullable()->constrained("countries")->cascadeOnUpdate()->nullOnDelete();
$table->timestamps();
});
City Model:
class City extends Model
{
use HasFactory;
public function country(){
return $this->belongsTo(Country::class,'country_id');
}
}
Frontend Blade:
<tbody>
#foreach($CityList as $City)
<tr>
<td><input type="checkbox" name="id[]"></td>
<td>{{$City->id }}</td>
<td>{{$City->name }}</td>
<td>{{$City->zipcode }}</td>
<td>{{$City->country->name }}</td>
<td>{{$City->country->countrycode }}</td>
<td>{{$City->order }}</td>
<td>{{$City->created_at->diffForHumans()}}</td>
<td>
<i class="fa fa-edit" style="font-size: 17px;"></i>
<button href="{{ route('dashboard.city.delete',$City->id) }}" type="button" value="{{ $City->id }}" class="btn btn-danger delete" data-toggle="tooltip" title="Delete">
<i aria-hidden="true" class="fa fa-trash"></i>
</button>
</td>
</tr>
#endforeach
</tbody>
I can suggest a few ways to solve this
First: Make a default value for the relation, like here
public function country()
{
return $this->belongsTo(...)->withDefault(['name' => 'No country']);
}
Second: Make a mutation in City model to find the name of the country
protected function countryName(): Attribute
{
return Attribute::make(
get: fn ($value) => $this->country-> name ?? 'Not country',
);
}
Notes: This way works only for laravel 9.x +, for older versions
please read this article
You can do this: <td>{{$City->country ? $City->country->name : 'No country found'}}</td>
And make sure you are including countries when fetching cities.

Can't get the model relationship right. It said property doesn't exist in Eloquent builder instance

Something is wrong with my codes. I knew my concept is right in my own thinking but not working....I want to take out the videos that logged in user liked.
This is my liked table and it stored amv_id and user_id
Schema::create('like_videos', function (Blueprint $table) {
$table->id();
$table->foreignId("amv_id");
$table->foreignId("user_id");
$table->timestamps();
});
This is my amv table and it stored everything of videos
Schema::create('amvs', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->string('desc');
$table->integer('view');
$table->integer('like');
$table->integer('dislike');
$table->integer('category_id');
$table->foreignId('user_id');
$table->string('video');
$table->string('thumb');
$table->timestamps();
});
This is my user table and it stored user infos
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->integer('sub');
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->integer('suspend');
$table->rememberToken();
$table->timestamps();
});
This is my controller codes
public function likedvideo() {
$id = auth()->user()->id;
$auth = auth()->user();
$liked = like_video::with('amvs')->where("user_id", "=", $id)->latest();
return view("amvs.likedvideos", [
'liked' => $liked,
'auth' => $auth,
]);
}
I used model relationship on Amv Model
public function amvs() {
return $this->hasMany('App\Models\like_video');
}
This is my view file
#foreach ($liked->amvs as $amv)
<div class="col">
<a href="{{url("amvtube/watch/$amv->id")}}" class="text-decoration-none">
<div class="card mb-2 rounded-0" style="width: 18rem;">
<img src="{{asset('/image/'.$amv->thumb)}}" alt="thumbnail" width="286px" height="161px">
<div class="card-body">
<h5 class="card-title">{{Str::limit($amv->title, 40, '...')}}</h5>
<span class="card-text">{{$amv->user->name}} / Genre: {{$amv->category->name}}</span> <br>
<span class="text-muted">
{{$amv->view}} View {{$amv->created_at->diffForHumans()}}
</span>
</div>
</div>
</a>
</div>
#endforeach
Updated answer:
Add this to your Contoller:
public function likedvideo() {
$id = auth()->user()->id;
$data["auth"] = auth()->user();
$data["liked"] = Amv::with('liked_videos')->where("user_id", "=", $id)->get();
return view("amvs.likedvideos",$data);
}
This to Amv model:
public function liked_videos() {
return $this->hasMany('App\Models\like_video', 'amv_id', 'id');
}
IN VIEW:
var_dump($liked);die();
#foreach ($liked as $amv)
<div class="col">
<a href="{{url("amvtube/watch/$amv->id")}}" class="text-decoration-none">
<div class="card mb-2 rounded-0" style="width: 18rem;">
<img src="{{asset('/image/'.$amv->thumb)}}" alt="thumbnail" width="286px" height="161px">
<div class="card-body">
<h5 class="card-title">{{Str::limit($amv->title, 40, '...')}}</h5>
<span class="card-text">{{$amv->user->name}} / Genre: {{$amv->category->name}}</span> <br>
<span class="text-muted">
{{$amv->view}} View {{$amv->created_at->diffForHumans()}}
</span>
</div>
</div>
</a>
</div>
#endforeach
The foriegn key in your like_videos is wrong.
The format that Laravel looks for by default is table name with id appended.
Schema::create('like_videos', function (Blueprint $table) {
$table->id();
$table->foreignId("amvs_id");
$table->foreignId("user_id");
$table->timestamps();
});
mention the error laravel app is showing?
possible that your users table has id and you're using foreignId('user_id') which model can't find so use same name as id() field with your foreignId() fields or make relations as:
$table->unsignedBigInteger('user_id');
then connect with foreign:
$table->foreign('user_id')->references('id')->on('Users');
MODIFY TABLE SCHEMA LIKE THIS:
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->integer('sub');
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->integer('suspend');
$table->rememberToken();
$table->timestamps();
});
Schema::create('amvs', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->string('desc');
$table->integer('view');
$table->integer('like');
$table->integer('dislike');
$table->integer('category_id');
$table->foreignId('user_id')->contrained('users');
$table->string('video');
$table->string('thumb');
$table->timestamps();
});
Schema::create('like_videos', function (Blueprint $table) {
$table->id();
$table->foreignId("amv_id")->constrained('amvs');
$table->foreignId("user_id")->constrained('users');
$table->timestamps();
});``

I want to pass a value from one table to another in Laravel

I am trying to solve a problem, but I don't have so much depth to solve it
I have 2 tables
Book Table
Schema::create('books', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->string('about');
$table->text('content');
$table->string('image');
$table->integer('author_id');
$table->timestamps();
});
Authors Table
Schema::create('authors', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->string('about');
$table->string('image');
$table->timestamps();
});
I connect both using one-many relationship
My Book.php Model have this
public function authors()
{
return $this->belongsTo(Author::class);
}
My Book.php Model have this
public function books()
{
return $this->hasMany(Book::class);
}
I am able to save the author's id into book table
MY PROBLEM
I want to show the author's name and book name on the front end, so I tried this, but not working
#foreach($books as $book)
<div class="col-md-3">
<div class="home-catalog-image">
<img src="{{ asset('/storage/'.$book->image) }}">
</div>
<p class="author">{{ $book -> author_id }}</p>
<h1 class="book-title">{{ $book -> name }}</h1>
</div>
#endforeach
I am unable to show the author's name with the $book -> author_id, I know this approach is wrong but I don't know what to. Please I need help. Thanks.
Use the relation to show the author name, but more important preload (lazy load) all the Authors before sending $books to the view using with() method
Controller
$books = Books::query()->with('authors')->get(); //or paginate
View
#foreach($books as $book)
<div class="col-md-3">
<div class="home-catalog-image">
<img src="{{ asset('/storage/'.$book->image) }}">
</div>
<p class="author">{{ $book->authors->name }}</p>
<h1 class="book-title">{{ $book -> name }}</h1>
</div>
#endforeach
As i commented, you should rename the relation from authors() to author() since each book has only one author
BelongsTo means that author should be singular
public function author()
{
return $this->belongsTo(Author::class);
}
And in this view
{{ $book->author->name }}
You can see the documentation for the reference.

laravel Many To Many relationship with inner relation

I have some problem to get information about item. I read a lot of information on forums stakoverflow. Maybe i can not find the correct information. Maybe someone knows about that hove to solve the problem
I have 4 tables
public function up()
{
Schema::create('db_items', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
});
}
public function up()
{
Schema::create('db_item_weapons', function (Blueprint $table) {
$table->increments('id');
$table->integer('item_id')->unsigned();
$table->foreign('item_id')
->references('id')->on('db_items')
->onDelete('cascade');
$table->integer('grade_id')->unsigned();
$table->foreign('grade_id')
->references('id')->on('db_item_grades')
->onDelete('cascade');
$table->string('hand')->nullable();
$table->string('name')->nullable();
$table->text('description')->nullable();
$table->string('icon')->nullable();
$table->string('p_atak')->nullable();
$table->timestamps();
});
}
public function up()
{
Schema::create('db_item_categories', function (Blueprint $table) {
$table->increments('id');
$table->string('name')->nullable();
$table->timestamps();
});
}
public function up()
{
Schema::create('db_item_db_item_category', function (Blueprint $table) {
$table->increments('id');
$table->integer('item_id')->unsigned()->index();
$table->foreign('item_id')
->references('id')->on('db_items')
->onDelete('cascade');
$table->integer('category_id')->unsigned()->index();
$table->foreign('category_id')
->references('id')->on('db_item_categories')
->onDelete('cascade');
$table->timestamps();
});
}
And 3 models
class DbItem extends Model
{
function weapon()
{
return $this->hasOne(DbItemWeapon::class, 'item_id');
}
function categories()
{
return $this->belongsToMany(DbItemCategory::class,'db_item_db_item_category','item_id','category_id');
}
}
class DbItemWeapon extends Model
{
function DbItem()
{
return $this->belongsTo(DbItem::class);
}
}
class DbItemCategory extends Model
{
function items()
{
return $this->belongsToMany(DbItem::class,'db_item_db_item_category','category_id','item_id')->with('weapon');
}
}
When i try to get some inforamtion it wotrks for example
#foreach($categories as $category)
<li>
<a class="uk-accordion-title" href="#">{{ $category->name }}</a>
<div class="uk-accordion-content">
#foreach( $category->items as $item)
<p>{{ $item->id }}</p>
#endforeach
</div>
</li>
#endforeach
i got the categories wtith their items and i can view the items id which contains in categoryes but if i want to see more information, its not work
$item->weapon->name
Maybe some of the items does not have a weapon, check for the weapon's existence first:
#foreach($categories as $category)
<li>
<a class="uk-accordion-title" href="#">{{ $category->name }}</a>
<div class="uk-accordion-content">
#foreach( $category->items as $item)
#php
$weapon = $item->weapon;
#endphp
<p>{{ $item->id }}</p>
<p>{{ $weapon ? $weapon->name : null }}</p>
#endforeach
</div>
</li>
#endforeach

How to make pagination by $category->companies in Laravel

I listed my category companies and i want to paginate by them. How can i do it?
This is my view:
#foreach ($category->companies as $singleCompany)
<div class="col-sm-12 col-lg-4 col-md-6">
<!-- product card -->
<div class="product-item bg-light">
<div class="card">
<div class="card-body">
<h4 class="card-title">{{$singleCompany->name}}</h4>
#foreach ($singleCompany->categories as $singleCategories)
<ul class="list-inline product-meta">
<li class="list-inline-item">
<i class="fa fa-folder-open-o"></i>{{ $singleCategories->name }}
</li>
</ul>
#endforeach
</div>
</div>
</div>
</div>
#endforeach
My controller looks like this:
$companies = Company::filterByRequest($request)->paginate(9);
$category = Category::find($id);
My category schema:
if(! Schema::hasTable('categories')) {
Schema::create('categories', function (Blueprint $table) {
$table->increments('id');
$table->string('name')->nullable();
$table->string('icon')->nullable();
$table->timestamps();
$table->softDeletes();
$table->index(['deleted_at']);
});
My company schema:
if(! Schema::hasTable('companies')) {
Schema::create('companies', function (Blueprint $table) {
$table->increments('id');
$table->string('name')->nullable();
$table->string('city_id')->nullable();
$table->string('categories')->nullable();
$table->string('address')->nullable();
$table->text('description')->nullable();
$table->string('logo')->nullable();
$table->timestamps();
$table->softDeletes();
$table->index(['deleted_at']);
});
}
Pivot table for company_category
if(! Schema::hasTable('category_company')) {
Schema::create('category_company', function (Blueprint $table) {
$table->integer('category_id')->unsigned()->nullable();
$table->foreign('category_id', 'fk_p_91029_91033_company__5a12afe2d2772')->references('id')->on('categories')->onDelete('cascade');
$table->integer('company_id')->unsigned()->nullable();
$table->foreign('company_id', 'fk_p_91033_91029_category_5a12afe2d27f0')->references('id')->on('companies')->onDelete('cascade');
});
Can i use somehow $category->companies to paginate my companies? Thank you for help.
Sorry I don't know if $category->companies would be possible in this case.
You might want to try this code.
$companies = Company::leftJoin('category_company', 'companies.id',
'=', 'category_company.company_id')
->where('category_id', $id)
->paginate(9);
This code will left join the table companies and category_company.
It will also be able to get the companies that has the chosen category id.
The result is also ready for pagination in your blade.
If you want pagination for category you have to use paginate() for category.
Try changing your get category query by this
$category = Category::where('unique_id', $id)->paginate(9);
Then you can use {{ $category->render() }} where you need pagination
$category->companies will return an Eloquent collection with all companies and not an instance of LengthAwarePaginator.
$companies will return an instance of LengthAwarePaginator, so iterate over it.
In comments, you've said you want to load companies of specified category. If you've defined the belongsToMany() relationship already, use whereHas() to filter by category:
$companies = Company::filterByRequest($request)
->whereHas('categories', function($q) use($categoryId) {
$q->where('id', $categoryId);
})
->paginate(9);
Then display companies:
#foreach ($companies as $singleCompany)
{{ $singleCompany->name }}
#endforeach
And add pagination links:
{{ $companies->render() }}
https://laravel.com/docs/5.5/pagination

Categories