Laravel Relation with Pivot Table, Relationships? - laravel

I have a User-Tables aswell as an "Adress" Table. They can enter multiple Adresses to choose from when checking out.
Now I want to be able to have one adress set as the standard invoice adresse and another one as the standard invoise adress. I thought about doing it using a pivot table, containing the following:
Schema::create('users_adresses_pivot', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users');
$table->integer('invoice_adress_id')->unsigned();
$table->foreign('invoice_adress_id')->references('id')->on('adresses');
$table->integer('delivery_adress_id')->unsigned();
$table->foreign('delivery_adress_id')->references('id')->on('adresses');
$table->timestamps();
});
However I'm not sure if thats the right way. It looks a bit like a bad practice to me. If I choose this option how do I set the Relations? Because I would need two Relations from User to Adresses. I already got one in order to foreach through them in a view. So If I replaced that with the Pivot Relation I could only get the standard invoice & delivery adresses instead of the others too. Any idea?
This is my current Relationship:
User.php:
public function adresses()
{
return $this->hasMany('App\Adress');
}
Adress.php:
public function user()
{
return $this->belongsTo('App\User');
}

IMHO dont use a pivot table, you dont need a many to many, this is a simple one to many relationship (one user has many addresses).
In the address table you just need to add two columns: "user_id" and "type".
The relations you wrote are good.

Related

Laravel 5.7 - Users/followers pivot table to create a follower (user) to Bug relationship

This app has a Bug model and a User model. Users can "follow" Bugs. This seems like a pivot table. What's the simplest way to implement this with a migration and Model relationship? I'm thinking along the lines of a followers table:
Schema::create('followers', function (Blueprint $table) {
$table->increments('id');
$table->uuid('bug_id');
$table->uuid('user_id');
$table->index(['bug_id', 'user_id']);
$table->timestamps();
$table->softDeletes();
});
Where I'm mostly stumped is the followers relationship in the Bugs Model. This is where I'm currently at:
public function followers()
{
return $this->belongsToMany(User::class, 'followers', 'bug_id', 'user_id');;
}
This really doesn't seem right. New to eloquent pivot tables, so really appreciate the help!
You are looking for a many-to-many relationship which requires an intermediary table bug_follower just as you created one and you also need to create a relationship from Bug to Follower as you did, but also create the relationship from Follower to Bugs. You are on the right track.
Overall you will have 2 models: Bug, Follower.
You will also have 3 tables: bugs, followers, bug_follower
And 2 relationships from Bug and Follower to each other
EDIT: This is how your relationship needs to look like:
public function followers()
{
return $this->belongsToMany(User::class, 'followers', 'bug_id', 'user_id');
}
You can check more about subject in the docs.

Laravel - Many To Many Relationship Setup

I am using Laravel 5 and am trying to get my head round relationships.
I have 2 tables, students and rooms. Each room can have many students, and each student can have many rooms.
Would this be a Many to Many relationship in both directions? Would I need a pivot table to achieve this?
Yes, what you describe is a many-to-many relationship, and for that you'll need a pivot table.
Your three tables would look like this: (this might look different from your actual tables)
students
id (primary key)
name
age
rooms
id (primary key)
room_size
bedroom_count
Note: by default, the name of the pivot table is composed of both model names (in singular form), in alphabetical order. So in this case: Student + Room = room_student.
room_student (pivot table)
room_id (foreign key to 'rooms')
student_id (foreign key to 'students')
Pivot table migration:
class CreateRoomStudentTable extends Migration
{
public function up()
{
Schema::create('room_student', function (Blueprint $table) {
$table->unsignedInteger('room_id');
$table->unsignedInteger('student_id');
// Primary key
$table->primary(['room_id', 'student_id']);
// Both foreign keys
$table->foreign('room_id')
->references('id')
->on('rooms')
->onDelete('cascade');
$table->foreign('student_id')
->references('id')
->on('students')
->onDelete('cascade');
});
}
// ...
Room and Student models:
class Room extends Model {
// ...
public function students()
{
$this->belongsToMany(App\Student::class);
}
}
class Student extends Model {
// ...
public function rooms()
{
$this->belongsToMany(App\Room::class);
}
}
Would this be a Many to Many relationship in both directions?
yes you need to Many to Many relationship in both directions
Would I need a pivot table to achieve this?
yes
you can see more about Many to Many relationship here
Yes you can implement many to many relationship and you will definitely need pivot table for implementing many to many relationship.
In this case you can create pivot table like room_student and add the room_id and student_id columns in it. then just use define relationship using belongsToMany method in your models and remember to use the attach method whereever you want to attach the functionality.
You need a pivot table.
About that, you can find out more from here:
ManyToManyRelationship

belongsTo not returning results as desired

I would like to a user be able to only have one distrito (it means district in Portuguese). A distritocan have more than one user. It's a fairly simple relationship but the problem comes when you have a third table called distritosthat it's only job is to translate numbers into strings (I don't know the name of such tables).
Distrito table
$table->increments('id');
$table->string('distrito');
e.g.
ID DISTRITO
1 - Aveiro
2 - Beja
3 - ...
User tables
$table->string('name');
$table->string('last_name');
$table->string('profile_picture')->default('default.jpg');
$table->string('userProfile')->default('');
$table->float('stars')->default(0);
distrito_user table this table will reference where the user live
$table->integer('user_id'); //id of the user
$table->integer('distrito_id'); //Id of the district where the user lives
User's model
public function distritoUtilizador(){
return $this->belongsTo(DistritoUser::class);
}
DistritoUser's model
protected $table = 'distrito_user';
Calling the eloquent model
$user = Auth::user();
dd($user->distritoUtilizador);
It returns null.
First question: Is this the correct way to solve my problem (the user lives somewhere and I need to fill that location)?
If this is the right way to solve my problem: Why it's not returning the desired results?
For a simple one to many, just store the foreign key to distrito on the user model, no need for intermediate tables.
$table->increments('id')->unsigned();
$table->string('name');
$table->string('last_name');
$table->string('profile_picture')->default('default.jpg');
$table->string('userProfile')->default('');
$table->float('stars')->default(0);
$table->integer('distrito_id')->unsigned();
$table->foreign('distrito_id')->references('id')->on('distrito');
and get rid of the distrito_user table altogether. now use has this method:
public function distrito(){
return $this->belongsTo(Distrito::class, 'id');
}
while distrito has:
public function users(){
return $this->hasMany(User::class);
}
also change distrito migration to:
$table->increments('id')->unsigned();

Laravel Eloquent Relationship Many to Many Naming Convention

I am creating a purchased table in my application. So I have 2 tables : User and Product. Its a many to many relationship.
I know we have to create a new table for this. The naming convention for table is plural as users and products.
How would we call this purchase table? user_product or users_products?
Also I think I would need a model for this correct? If I do need a model should the naming convention for this model be User_Product?
From the documentation:
As mentioned previously, to determine the table name of the relationship's joining table, Eloquent will join the two related model names in alphabetical order. However, you are free to override this convention. You may do so by passing a second argument to the belongsToMany method
In your case, Laravel assumes that your joining table would be named product_user. No extra model is needed:
User.php
class User extends Model
{
//...
public function products()
{
return $this->belongsToMany(Product::class);
}
//...
}
Product.php
class Product extends Model
{
//...
public function users()
{
return $this->belongsToMany(User::class);
}
//...
}
And your schemas would look like so:
users table migration
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
//...
});
products table migration
Schema::create('products', function (Blueprint $table) {
$table->increments('id');
//...
});
product_user table migration
Schema::create('product_user', function (Blueprint $table) {
$table->integer('product_id');
$table->integer('user_id');
//...
});
About the naming Convention, thats just something that will make your code more readable i think, so you can name it as you like(in case you are new and learning , my opinion is that its better to avoid being stuck in conventions at first , im still learning my self)
anyway a pivot model is not required, unless you simply need some custom behaviour
I think this would help you
class User extends Model
{
/**
* The products that belong to the shop.
*/
public function products()
{
return $this->belongsToMany('App\Products');
}
}
you can do this : $user->products or to query $product->users, or both.
Now, with such declaration of relationships Laravel “assumes” that pivot table name obeys the rules and is user_product. But, if it’s actually different (for example, it’s plural), you can provide it as a second parameter:
return $this->belongsToMany('App\Products', 'products_users');
If you want to know how to manage these you can find more in here

Many to Many relationship works one way

I have a User and a Quiz models. I have many-to-many relationship defined between them in the following way:
User model
public function subscriptions()
{
return $this->belongsToMany(Quiz::class, 'subs_users', 'user_id', 'quiz_id')->withTimestamps()->withPivot('accepted');
}
Quiz model
public function subscribers()
{
return $this->belongsToMany(User::class);
}
Pivot table
Schema::create('subs_users', function (Blueprint $table) {
$table->integer('user_id')->unsigned();
$table->integer('quiz_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->foreign('quiz_id')->references('id')->on('quizzes')->onDelete('cascade');
$table->primary(['user_id', 'quiz_id']);
$table->boolean('accepted')->index();
$table->timestamps();
});
When I call $quiz->subscribers, it returns a collection of users as expected. However, $user->subscriptions always returns an empty array. Why is that?
Edit
It seems, that replacing this line in Quiz
return $this->belongsToMany(User::class);
with
return $this->belongsToMany(User::class, 'subs_users', 'quiz_id', 'user_id')->withTimestamps()->withPivot('accepted');
Solves the issue, but I still can't understand why the first variant does not work.
Look at this:
public function subscriptions()
{
return $this->belongsToMany(Quiz::class, 'subs_users', 'user_id', 'quiz_id')->withTimestamps()->withPivot('accepted');
}
You mixed the foreign key with other key: user_id and quiz_id.
Remember when doing many to many relation that: first of foreign key's declared in belongsToMany is a key related to the current model.
Replacing belongsToMany() relationship in Quiz model with following:
return $this->belongsToMany(User::class, 'subs_users');
Solves the issue. It seems, that when a non-standard name is used for the pivot table, both sides must explicitly state it. In other words, 'subs_user' pivot table name must be present in belongsToMany() relationship declarations in both models.

Resources