So, I've been trying to watch and read eloquent relationships from laracasts. Unfortunately I still don't quite get how to translate database relationships to eloquent relationships (hasOne, belongsTo, hasMany, etc).
Let's say I have an Account and Customer tables. Account table has a "Customer_id" foreign key which references to the "id" on Customer table. Let's assume it's a one-to-many relationship. How should I put it on my models on laravel?
Which table should contain the "hasMany" and which one should have the "belongsTo"?
Just think about how you would say it. In your case it sounds like a Customer has many Accounts and an Account belongs to one Customer.
So you would put the hasMany() in your Customer model and the belongsTo() in your Account model.
class Customer extends Model {
public function accounts() {
return $this->hasMany('App\Account');
}
}
class Account extends Model {
public function customer() {
return $this->belongsTo('App\Customer');
}
}
You can read more about Laravel database relationships here.
Related
I have two migration tables and two models
1)User.
2)Subscription.
in subscriptions Model i write one method called user() which has hasMany relationship and in Users model it will contain subscriptions() method which have belongs() relationship.
in user table id acts as an primary key and in subscription table sub_id acts as a foriegn key,for example if the user subscribed to any subscription the user id will store in the sub_id in the subscription table upto this it's working fine.
$is_subscription=Subscription::where('sub_id',$user->id)->value('sub_id');
from the above code i am able to get the value but now what i want is is there any better way to write the query based on models ,please help me to write this one..
According to your descriptions, I believe this is what you have:
class User extends Model
{
public function subscriptions()
{
return $this->hasMany(Subscription::class);
}
}
class Subscription extends Model
{
public function user()
{
return $this->belongsTo(User::class);
}
}
So you want to check whether an user has any subscriptions. You can do one of the followings:
$user->subscriptions()->exists();
// Or
$user->subscriptions->isNotEmpty();
You can use pluck() method:
$is_subscription=Subscription::where('sub_id',$user->id)->pluck('sub_id');
You can find details on the methods that are available for collection using the Laravel Documentation
In my application, a model Device has a many-to-many relationship with model Task.
A combination of Device and Task could be assigned to a various number of model User.
example: Device A has a Task Check something and this should be done by User Frank and Steven.
From my point of view, this should be a "standard problem", but so far I could not find a proper solution.
Right now, I use following workaround:
a) added an unique ID id to the device_task pivot table
b) query id from the pivot table
c) create a new table device_task_user which contains user_id and device_task_id
b) use query builder to get/add users
But I am really not happy with this approche.
Would it be possible, that the pivot table also extends Model and then have a one-to-many relationship with User?
Or would you suggest to add a json colum to the pivot table and store the users there?
Any idea would be very welcome!
Would it be possible, that the pivot table also extends Model
Yes, it's possible. From the docs:
If you would like to define a custom model to represent the intermediate table of your relationship, you may call the using method when defining the relationship. All custom models used to represent intermediate tables of relationships must extend the Illuminate\Database\Eloquent\Relations\Pivot class
You also can create a new hasMany() and belongsTo() relationships between Task and Device models and use them as well as existing belongsToMany relationship. And you'll need to define a new relationship between pivot model and User model to be able to get data by device, task or user.
Modify many-to-many relationship to hold an extra field user_id
class Device extends Model
{
public function tasks()
{
return $this->belongsToMany(
Task::class,
'device_task',
'device_id',
'task_id'
)->withPivot('user_id');
}
}
And when updating do like this in controller
$device->tasks()->attach([$taskId]=>['user_id']=>$userId);
And of-course you need DeviceTask model and also a has-many relationship between User model and DeviceTask model to get user's task
I've got a Company model in which I would like to define two relationships with the User model:
public function users(){
return $this->hasMany('App\User');
}
public function administrator(){
return $this->hasOne('App\User', 'superuserid');
}
I have a superuserid field in my companies table in the database, which is a foreign key to the id of the users table.
I just want to know if this is at all a good strategy or even possible?
Yes, it is a good strategy and it is possible.
In your model you can define as much relations as your model needs. And those relations can be of different types (hasOne, hasMany, belongsTo, etc).
In your case, since the company has multiple users and belongs to a super user, we have two different relations, so, obviously, we need to create two methods in the model to represent these two relations.
Another example: the relation between you and your father. Let's say that there is this implementation of a User model:
class User extends Model
{
public function children()
{
return $this->hasMany(User::class, 'id_parent');
}
public function dad()
{
return $this->belongsTo(User::class, 'id_parent')->where('gender', 'male');
}
}
Here a User can has many children but belongs to just one dad.
I am using laravel 5.1. The scenario is as follows(this is an example. The real scenario is similar to this example)
I have 3 models
College
Student
Teacher
A college can have many students but a student can belong to only 1 college.
A college can have many teachers but a teacher can belong to only 1 college.
I want to establish relationships between these tables in laravel.
One of the methods for this is to place a college_id foreign key on the Students and Teachers table. But in my case, this foreign key will be null a lot of times. So rather than have separate columns in 3-4 tables with mostly null values, I wanted to explore the option of having a polymorphic relationship for College table.
This is what I tried:
The example given in the laravel docs(link below) depict a one-to-many relationship whereas my scenario is more of a many to one relationship.
http://laravel.com/docs/5.1/eloquent-relationships#polymorphic-relations
As given in the example, having collegeable_id and collegeable_type columns on the College table would not have fulfilled my requirement as a college can contain many students/teachers so I created a pivot table:
Schema::create('collegeables', function (Blueprint $table) {
$table->integer('college_id')->unsigned();
$table->integer('collegeable_id')->unsigned();
$table->string('collegeable_type');
});
And I have the following models
College Model:
namespace App;
use Illuminate\Database\Eloquent\Model;
class College extends Model
{
public function students()
{
return $this->morphedByMany('App\Student', 'collegeable');
}
}
Student Model:
namespace App;
use Illuminate\Database\Eloquent\Model;
class Student extends Model
{
public function college()
{
return $this->morphOne('App\Colleges', 'collegeable');
}
}
With this arrangement, I am able to store students using College model instance like this
$college = \App\College::find(1);
$student = new \App\Student;
$student->name = 'John Doe';
$college->students()->save($student);
But when I try to retrieve a College model instance using a student model instance as specified below, it gives me an error:-
public function index()
{
return \App\Student::find(1)->college;
}
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'colleges.collegeable_id'
This is kind of expected as morphOne works with columns in a table I suppose.
If I change the morphOne function in Student Model to morphToMany, the code starts working and I am able to retrieve values as well. But that make this relationship a many to many which again is not what I want.
So my question is this:-
Is their a morphSomething function I can use in the student model to be able to retrieve values for the student's college while maintaining the relationship as a one-to-many?
Any help would be really appreciated. Thanks.
There's no reason to use Polymorphic relationships here. Instead, just add a foreign key to your colleges table on both your students and teachers tables. Like this:
colleges
id
name
teachers
id
name
college_id
students
id
name
college_id
Then your models can use the belongsTo() and hasMany() relations, like so:
class College extends Model {
public function students() {
return $this->hasMany(App\Student::class);
}
public function teachers() {
return $this->hasMany(App\Teacher::class);
}
}
class Teacher extends Model {
public function colleges() {
return $this->belongsTo(App\College::class);
}
}
class Student extends Model {
public function colleges() {
return $this->belongsTo(App\College::class);
}
}
Polymorphic one-to-many relations are for the opposite of this relationship where you have a model that can only be related to a single record, but that record can be many different models.
Edit: To further explain why a polymorphic relationship isn't needed here, let's take a look at where it would be needed. Say you have a simple CRM style website. There are Customers and Projects and you want to have Comments on both. In this case, you would make Comments a polymorphic relationship because Comments belong to a single Customer or a single Project, but not both.
Your relationship is the exact opposite. In your case, Students and Teachers belong to a college. If you were to follow the previous example's pattern, a college would have belonged to a single student or teacher.
I had a similar need and managed to improvise in another way, taking advantage of morph's table structure.
You will need a Collegeable class to be Pivot (https://laravel.com/docs/9.x/eloquent-relationships#defining-custom-intermediate-table-models)
And then the magic:
public function college(){
return $this->hasOneThrough(Colleges::class,
Collegeable::class,
'collegeable_id',
'id',
'id',
'college_id',
);
}
And on the Collegeable Pivot class:
namespace App\Models;
use Illuminate\Database\Eloquent\Relations\Pivot;
class Collegeable extends Pivot
{
protected $table = 'collegeables';
}
I have generate the following database table and need to create model form them.
Creating a model seems to be an easy task, but I am confused how should i define the relationship between two tables. In users table RoleId is foreign key. My question is where and how should I define the relationship (in User model or Role model). Should I use hasOne, hasMany, or belongsTo
In your User model
public function roles()
{
return $this->hasOne('Role', 'id', 'RoleId');
}
In your Role model
public function users()
{
return $this->belongsTo('User', 'RoleId', 'id);
}