I find the pivot tables pretty complicated and I don't see what to do next or what I am doing wrong, I've found some tutorials but didn't help me in my needs.
I have a projects and users with a many-to-many relation.
One project hasMany users and One user hasMany projects.
What I have now leaves projects without a relationship to a user.
This is what I have so far:
Projects table
class CreateProjectsTable extends Migration {
public function up()
{
Schema::create('projects', function(Blueprint $table)
{
$table->increments('id');
$table->string('name');
$table->date('completion_date');
$table->integer('completed')->default(0);
$table->integer('active')->default(0);
$table->timestamps();
});
}
Users table
class CreateUsersTable extends Migration {
public function up()
{
Schema::create('users', function(Blueprint $table)
{
$table->increments('id');
$table->integer('company_id');
$table->integer('project_id');
$table->integer('usertype_id')->default(0);
$table->string('username');
$table->string('password');
});
}
Project User table (pivot)
class CreateProjectUsersTable extends Migration {
public function up()
{
Schema::create('project_users', function(Blueprint $table)
{
$table->increments('id');
$table->integer('project_id')->references('id')->on('project');;
$table->integer('user_id')->references('id')->on('user');;
});
}
User model
public function projects() {
return $this->belongsToMany('App\Project', 'project_users', 'user_id', 'project_id');
}
Project model
public function users() {
return $this->belongsToMany('App\User', 'project_users', 'project_id', 'user_id');
}
Project controller
public function index(Project $project)
{
$projects = $project->with('users')->get();
dd($projects);
$currenttime = Carbon::now();
//return view('project.index', array('projects' => $projects, 'currenttime' => $currenttime));
return view('user.index', compact('projects'));
}
The relationship in your User model is not correct. You have to swap the keys.
public function projects() {
return $this->belongsToMany('App\Project', 'project_users', 'user_id', 'project_id');
}
Edit regarding latest comment:
Don't think about the pivot table, as long as you have your relations setup correctly, which I believe they are, Laravel handles all of that for you.
Now $projects->users does not make any sense because projects does not have users. projects is just a collection of Project. Each Project within that collection will have a users relation. You would have to iterate through the collection to view each Project's users.
foreach($projects as $project) {
foreach($project->users as $user) {
echo $user;
}
}
Related
I've got a problem with relations in Laravel 9.14 Eloquent.
I have two models File and Project with coresponding tables in MySql database files and projects.
Project migration
Schema::create('projects', static function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('code');
$table->string('theme');
$table->foreignId('discipline_id')->constrained('disciplines');
$table->foreignId('user_id')->constrained('users');
$table->string('external_id');
$table->foreignId('preview')->nullable()->constrained('files');
$table->date('publish_date');
$table->timestamps();
});
File migration
Schema::create('files', static function (Blueprint $table) {
$table->id();
$table->string('original_name');
$table->string('extension');
$table->string('mime_type');
$table->integer('size')->unsigned();
$table->timestamps();
});
Project has field which is related to the File model called 'preview'. Project, basically can have only one preview file. So I did these relatioins in models:
class Project extends Model
public function preview(): BelongsTo
{
return $this->belongsTo(File::class, 'preview', 'id');
}
class File extends Model
public function previewProject(): HasOne
{
return $this->hasOne(Project::class, 'preview', 'id');
}
When i try to get preview of a project this way (controller method):
public function index(): Factory|View|Application
{
$userId = auth()->user()->id;
$projects = User::find($userId)->projects()->with(['user', 'preview'])->get();
//dd($projects->first()->user);
ddd($projects->first()->preview);
return view('user.index', [
'projects' => $projects
]);
}
Instead of File model object I get only integer id of File. Queries, however, look right:
queries image
What is the problem here?
There is no error, the integer your are getting is the value of the attribute but by "chance" both your attribute and relation have the same name.
Either change the relation name:
class Project extends Model
public function previewFile(): BelongsTo
{
return $this->belongsTo(File::class, 'preview', 'id');
}
public function index(): Factory|View|Application
{
$projects = auth()->user()->projects()->with(['user', 'previewFile'])->get();
//dd($projects->first()->user);
ddd($projects->first()->previewFile);
return view('user.index', [
'projects' => $projects
]);
}
Or change the attribute name
Schema::create('projects', static function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('code');
$table->string('theme');
$table->foreignId('discipline_id')->constrained('disciplines');
$table->foreignId('user_id')->constrained('users');
$table->string('external_id');
$table->foreignId('preview_id')->nullable()->constrained('files');
$table->date('publish_date');
$table->timestamps();
});
class Project extends Model
public function preview(): BelongsTo
{
return $this->belongsTo(File::class, 'preview_id', 'id');
}
I'm trying to create a system to log all bookings for a few airbnb hosts, at first I had two models Home and Guest, where a home can have many guests and a guest could book for many homes,
then I thought about creating a guest_home pivot table to link both tables... then things got complicated in my head, what about a Booking model, and (have that booking model act as a pivot table ?) , to me doing new Booking() seemed better than attaching ids to home model?
How could you guys go about this, it's making my brain malt right now...
I thought of doing something like this in my BookingController:
public function createBooking(Request $request)
{
$guestIds = Guest::latest()->take(3)->pluck('id');
$home = Home::findOrFail($request->input('home_id', 2));
$booking = new Booking();
$booking->home_id = $home->id;
$booking->guests()->attach($guestIds);
$booking->save();
return response()->json([
'booking' => $booking,
]);
}
Should I create home_guest pivot table, is a pivot table even needed? what models would I link, please bear with me, so far this is what I got:
Models
class Guest extends Model
{
public function bookings()
{
return $this->belongsToMany('App\Models\Home', 'bookings', 'guest_id', 'home_id');
}
}
class Home extends Model
{
public function guests()
{
return $this->belongsToMany('App\Models\Guest', 'bookings', 'home_id', 'guest_id');
}
public function bookings()
{
return $this->hasMany('App\Models\Booking');
}
}
class Booking extends Model
{
//Is Booking needed or I could make a pivot table like home_guest called 'bookings' ?
public function guests()
{
return $this->belongsToMany('App\Models\Guest', 'booking_guest', 'booking_id', 'guest_id');
}
}
Migrations:
Schema::create('bookings', function (Blueprint $table) {
$table->increments('id');
$table->unsignedInteger('home_id')->index();
$table->foreign('home_id')->references('id')->on('homes')->onDelete('cascade')->onUpdate('cascade');
$table->unsignedInteger('guest_id')->nullable()->index();
$table->foreign('guest_id')->references('id')->on('guests')->onDelete('cascade')->onUpdate('cascade');
$table->timestamps();
});
Schema::create('homes', function (Blueprint $table) {
$table->increments('id');
$table->unsignedInteger('host_id')->index();
$table->foreign('host_id')->references('id')->on('hosts')->onDelete('cascade')->onUpdate('cascade');
$table->string('fullAddress')->unique();
$table->integer('rooms')->unique();
$table->timestamps();
});
Schema::create('guests', function (Blueprint $table) {
$table->increments('id');
$table->string('fullName')->unique();
$table->string('identificationType')->unique();
$table->text('country')->nullable();
$table->timestamps();
});
So, I'm trying to create a relationship where users can follow other users or follow categories.
My intuition says that what I've done so far is not the right way of doing things. I'm especially confounded by how to create the follower - followee relationship.
TABLES:
Users
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('email');
$table->string('password');
$table->string('first_name');
});
}
Categories
public function up()
{
Schema::create('categories', function (Blueprint $table) {
$table->increments('id');
$table->string('category');
});
}
Follows
public function up()
{
Schema::create('follows', function (Blueprint $table) {
$table->increments('id');
$table->integer('follower_id');
$table->integer('followee_id')->nullable();
$table->integer('category_id')->nullable();
});
}
MODELS:
User
class User extends Model implements Authenticatable
{
public function follows()
{
return $this->hasMany('App\Follow');
}
}
Category
class Category extends Model
{
public function follows()
{
return $this->hasMany('App\Follow');
}
}
Follow
class Follow extends Model
{
public function post()
{
return $this->belongsTo('App\User');
}
public function source()
{
return $this->belongsTo('App\Category');
}
}
According to your scenario, it is recommended that you use Polymorphic Many To Many relationship.
Schema:
users
id - integer
...
categories
id - integer
...
followables
user_id - integer
followable_id - integer
followable_type - string
Models:
User:
public function followers()
{
return $this->morphToMany(User::class, 'followables');
}
public function following()
{
return $this->morphedByMany(User::class, 'followables');
}
Category:
public function followers()
{
return $this->morphToMany(User::class, 'followables');
}
Then you can create the relationship like:
When following an User:
$user->followers()->create(['user_id' => 12])
When following a Category:
$category->followers()->create(['user_id' => 25])
Hope it helps.
I have tables in my database schema as follows,
Is it pivot table?
How can I define relationship in eloquent model?
class Role extends Model {
public $timestamps = false;
public function permissions() {
return $this->hasMany('App\Models\RolePermission', 'permissions_id');
}
}
Is this correct way to define relationship? Please help me to understand.
and
class RolePermission extends Model {
public $timestamps = false;
public function role() {
return $this->belongsTo('App\Models\Role', 'roles_id');
}
}
The problem is that you need to name your table permission_role to follow the design pragma.
Role Schema
Schema::create('roles', function(Blueprint $table){
$table->increments('id');
$table->string('name');
$table->timestamps();
});
Permission schema
Schema::create('permissions', function(Blueprint $table){
$table->increments('id');
$table->string('name');
$table->timestamps();
});
Then you just need the permission_role table:
Permission_Role schema
Schema::create('permission_role', function(Blueprint $table){
$table->increments('id');
$table->integer('permission_id')->unsigned();
$table->foreign('permission_id')->references('id')->on('permissions')->onDelete('cascade');
$table->integer('role_id')->unsigned();
$table->foreign('role_id')->references('id')->on('roles')->onDelete('cascade');
});
Then you just set up your models like this:
class Role {
public function permissions() {
return $this->hasMany(App\Permission::class);
}
}
Then of course your permission class
class Permission {
public function role() {
return $this->belongsToMany(App\Role::class);
}
}
its a many to many relationship bond together by a pivot table Permission_Role. there for each table belongsToMany not hasOne or hasMany
class Role {
public function permissions() {
return $this->belongsToMany(App\Permission::class);
}
}
class Permission {
public function role() {
return $this->belongsToMany(App\Role::class);
}
}
hi I'm trying to use many to many polymorphic but somehow it doesnt work I attach my code can you find out what I do wrong?
my migration :
Schema::create('stickers', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('type');
$table->timestamps();
});
Schema::create('stickables', function (Blueprint $table) {
$table->integer('sticker_id')->nullable();
$table->integer('stickable_id');
$table->string('stickable_type');
$table->primary(['sticker_id', 'stickable_id', 'stickable_type']);
$table->foreign('sticker_id')
->references('id')->on('stickers')
->onDelete('cascade');
$table->timestamps();
});
and my models
Trip model:
public function stickables()
{
return $this->morphToMany(Stickable::class, 'stickable');
}
Stickable model:
public function trips()
{
return $this->morphedByMany(Trip::class, 'stickable');
}
controller:
public function store(Request $request)
{
$trip = new Trip();
$trip->name = $request->name;
$trip->desc = $request->desc;
$trip->creator_id = Auth::user()->id;
$trip->save();
$tags=$request->tags;
$trip->stickables()->attach($tags);
$trip->save();
return redirect('/trip');
}
Here is how you should define your relationship:
Trip Model:
public function stickers()
{
return $this->morphToMany(Sticker::class, 'stickable');
}
Sticker Model:
public function trips()
{
return $this->morphedByMany(Trip::class, 'stickable');
}
You don't need a model for your relationship (Stickable).You should create a model for stickers and define your relationship on that.
Stickable can refer to Trip or any other type of model you need to create a relationship with stickers. However in your code you have a stickable method on the Trip model, which does not make sense.
Eloquent Many to Many Polymorphic Relationships