I have some doubts about how to design a model whith a relation bewteen itself.
In my case, I have a users table with id and coach_id. All users has an id (obviously) but users with role Runner has also coach_id referred to an user with role Coach.
First step is how to create the key on laravel table migration and then, how to add correct relation in User model.
First, make sure that coach_id can be NULL:
$table->unsignedInteger('coach_id')->nullable();
Use unsignedBigInteger if model id use big integers.
Then define a foreign key:
$table->foreign('coach_id')
->references('id')
->on('users')
->onDelete('set null');
Use set null instead of cascade because you don't want delete related users when coach is deleted.
And set up one-to-many relation in User model:
public function coach() {
return $this->belongsTo(self::class);
}
From Laravel > 7 you can use shortcut in migration:
$table->foreignId('coach_id')
->nullable()
->constrained('users')
->onDelete('set null');
Related
How I can implement Unary Many-to-Many Relation with Eloquent models
Ex: If there's a relation that User can send request friend to one or more user
I know that I have to create new model like user-request-user for example,, Primary Keys for new model will be [user1_id , user2_id] that's what I think
but how to implement this relation then ..
yes dear it is possible in just like ordinary many to many relationship but with a little difference.
first step for many to many relation is create pivot table so you create migration for pivot table. pivot table is belongs to two table in normal many to many relation but this pivot table is belongs to a single table.if you create pivot table name "friend_request_user", so here is the migration
public function up()
{
Schema::create('friend_request_user', function(Blueprint $table)
{
$table->integer('user_id')->unsigned()->index();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->integer('request_user_id')->unsigned()->index();
$table->foreign('request_user_id')->references('id')->on('users')->onDelete('cascade');
$table->timestamps();
});
}
now you should have two models one "User" and other as you already have "user-request-user". both models should point to same table which is "users". by default User model is point to users table but you write a property $table for pointing "users" table for "user-request-user" model so
protected $table = 'users';
in User model you just write a simple method as write in any other many to many relation... so
public function request(){
return $this->belongsToMany('App\user-request-user', 'friend_request_user','user_id', 'request_user_id');
}
first parameter of "belongsToMany" function is relational model, 2nd is pivot table name, 3rd is foreign key and 4th is other key use in pivot table. we write these parameters just because not follows the laravel syntax in this case. this is all, now just call this function like
Auth::user()->request;
you may also like to use opposite of function which can write on other model "user-request-user" but this is just for your need.
public function nameOfFunction(){
return $this->belongsToMany('App\User', 'friend_request_user', 'request_user_id', 'user_id');
}
Cake newb here.
I have two tables. Users and Events. An user can subscribe to Multiple events.
What is the best way to implement this?
Do I have to create another table and link them or is there any other better approach.
If I do create a new table, how do i link them in cake model?
As said by jQuery.PHP.Magento.com you should use HABTM relationship but the name of the third table should be events_users because the table names should be in alphabetical order.
From the doc:
Table names are in alphabetical order by convention. It is possible to
define a custom table name in association definition.
You should use HABTM relationship.
Reason
See users will subscribe to Multiple events and
One event have multiple users subscribed for.
So this is two way relationship. Therefore you need following tables
users : To store user's data,
events : To store user's data,
events_users : To store Which user joined Which event and Vice versa(Events with n number of users)
So users_events will have 2 fields user_id , event_id , both are foreign keys and here you dont need primary key in HABTM relationship.
I know you can define table relationships fairly easy with $this->belongs_to(), $this->has_many() etc, but what i don't understand is how the relationship table is created; the table that binds the two tables together (i forgot what the term is called).
Let's say i'm creating a users table. I want that user to belong to a certain "Role". There are multiple roles, and every role can have multiple users. I will need to also create a roles table for that. So far, so good.
But after reading the documentation, it says i should add the $this->belongs_to() in the model, not the migration itself. When, and how is the relationship table created? If i create the roles and users tables, and add $this->belongs_to('roles') to the users model, and $this->has_many('users') to the roles model, will the middle table be created automatically?
When creating a migration you can specify foreign keys on your tables,
i.e.
public function up()
{
Schema::table('roles', function(Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned();
//rest of fields then...
$table->foreign('user_id')->references('id')->on('users');
});
}
This will create a foreign key on the user_id column on the roles table.
The benefits of foreign keys is that when an update or delete is made the foreign key table will be automatically updated or "cascaded" great description found here
As described on the Laravel documentation you could also specify your cascading on update using the following syntax
$table->foreign('user_id')
->references('id')->on('users')
->onDelete('cascade');
I would do a bad job of trying to explain it better than the documentation does so please have a read through the "Relationships" section of the Eloquent ORM documentation to see how its done.
It looks like a few of the initial questions were never answered, i.e. "When, and how is the relationship table created" & "will the middle table be created automatically":
As far as I am aware, these tables need to be created manually. So create the migration file like so:
Laravel 5
php artisan make:migration create_role_user_table
Laravel 4
php artisan migrate:make create_role_user_table
Note that the names are singular, and are presented in alphabetical order.
Then in the migration something like:
public function up()
{
Schema::create('role_user', function($table) {
$table->increments('id');
$table->integer('role_id');
$table->integer('user_id');
$table->timestamps();
});
}
Hope that helps. I'm not sure if the timestamps are needed in Pivot Tables or not, so please experiment.
Though its an old Post, I though I can contribute something updated. For Laravel5, Jeffrey Way has developed a package Laravel5 Generators-extended which enhance the generator capability of php artisan for
make:migration:schema
make:migration:pivot
make:seed
For many-to-many relation between users and role, you can just use
php artisan make:migration:pivot users role
and it will generate the required migration class. You don't need to code manually for this.
As far as I know, no relationship table will be created. What you will need to do is have a role_id on your users table, so that when you create a user, the ID of the role will be stored there. This will enable you do select all users where role_id == '1' or whatever it may be.
For example:
$admins = User::where('role_id', '=', 1);
Where on the ROLES table the record with ID='1' is admin.
So again to answer your question, no relationship table is created, instead the relationship exists within your two tables in the form of a role_id column for each user. Out of interest, are you using foreign keys?
If you want to have a relationships table you could create one called user_roles or something and store the role_id and user_id in there, however I think its easier to use the above method as then you can use all the Laravel/Eloquent goodness.
Hope this helps :)
This video helped me.
https://laracasts.com/series/laravel-5-fundamentals/episodes/14
What was surprising for me was that only one side of the relationship needs pointer_id in migration table, not both. For example, if we have Author with many Articles, we only add
$table->integer('author_id')
to article migration and thats it.
I know this is an old post but as I had the same question in mind. I've found the solution in the Laravel manual (5.0) where it is described that for this particular many-to-many relationship you can create the table manually and then declare the type of relationship into Model in this way:
return $this -> belongsToMany('App\<Model>', '<table_created_manually>');
or if you want to use specific associated keys:
return $this -> belongsToMany('App\<Model>', '<rel_table1_table2>' '<table1>_id', '<table2>_id');
Hope this can help.
EDIT, I am rewriting the question for more clarity.
I have a "profile" model that has a belongs to relationship to a "user" model.
A certain user exists already. Later he creates a profile. The profile controller takes care of creating a new entry, but then needs to update a profile_id field as part of the associated user. I was under the impression that saveAll could take care of all the associations but it is not working?
What is the easiest/CakePHP standard way to do something like this? Thanks!
saveAll() creates new records. So you can't use it to update an already existing record in the Users table. As Anh Pham already mentioned, you've got your associations wrong. A Profile belongs to a User, and a User has one Profile. By having a profile_id field in your Users table, you're doing it the other way around.
So remove the profile_id field from the Users table, add a user_id field to the Profiles table, and update your model associations in user.php & profile.php.
To save a new Profile for an existing User, you can then either query the user id for the current User, or for example retrieve it through Auth, and add it manually to $this->data prior to calling the save() method of your Profile method.
You shouldn't have a profile_id field in the users table, you should have user_id field in profile table (the foreign key is similar to hasMany relationship). I'm surprised that the app still works http://book.cakephp.org/view/1041/hasOne
Also, I usually don't have hasOne relationship. If User hasOne Profile, then just include all fields in the profiles table into users table, unless there's some reason not to do it. But again, it's just my preference.
i think i have all 'baked' all my relationships correctly but my 'related' table shows id's instead of values.
my db has 3 tables. candidates, qualificationlookups, qualifications.
qualificationlookups, links candidates to qualifications using the id of the candidate and the id of the qualification.
in my view view, for 'candidates', i have a 'related qualificationlookups' table. (generated by baking a candidate hasmany qualificationlookups and a qualificationlookups belongsto candidate relationship)
in my edit view, for 'qualificationlookups', i can correctly set up the candidates and qualifications fields as dropdowns so i know 'qualificationlookups's relationships are fine.
So how do i ask cakephp to list the name of the qualification (from 'qualifications' table) in the 'related qualificationlookups' table on a candidate's page?
i must be missing something...
could someone please point me in the right direction?
Thanks, Vauneen
Whenever CakePHP automagically fetches lists from your tables, it uses the id key for the value and the $displayField for the text.
If your table has a name or title field, CakePHP automatically displays it as the display field. So, either rename the field that you want as your display field (say, candidate_name to just name) or set the $displayField variable in your model:
class Candidate extends AppModel {
var $displayField = 'candidate_name';
}
HTH.
If there is no other data being stored in the qualificationlookups table, change the relationship to candidates -> HABTM -> qualifications.
To do this, you first need to drop the qualificationlookups table. Create a new table called candidates_qualifications with two indexes, candidate_id and qualification_id.
In your Candidate and Qualification models, define a HABTM Relationship. You do not need to make a new CandidatesQualification Model, cake will do it on the fly.