Creating a relationship from Pivot Table Field - laravel

I cannot find a solution, likely to how I am phrasing the question. I have a model called Invoice and it has the following relationship:
public function manifests(){
return $this->morphedByMany(carrier_manifest::class, 'invoiceable')->withPivot(['amount','rate_id','notes']);
}
As you can see, in the pivot, I have a table called rate_id. I would like to be able to add a relationship to another model based on the value of the rate_id (the model just being called ChargeRates). Is there a way I can do this in order to access a field in the ChargeRates model called label?

You'd want to actually implement the pivot table as a model if it has relationships and functionality on its own.
From a database concern, a many to many relationship between Table A and Table B is really just a one-to-many relationship between Table A and the pivot table and a one-to-many relationship between Table B and the pivot table.
Therefore, implementing your relationships with a pivot model using hasMany or morphMany is a way for you to accomplish what you're after.

Related

Laravel - Eloquent Models Relations, polymorphic or not?

I have this schema
All the relations here must be one-to-zero/one.
A user can be either an employee or a customer. The user_type ENUM gives me the type so I know where to go from there.
Then an employee can be either basic or a manager. The employee_type discriminator let's me know that.
How am I supposed to build the Eloquent Model relations?
Let's say I have a user that is an employee. I need to get it's common fields from the users table but also need to get common fields from employees table. Do I need to hard code, and know that when user_type=emp I need to select from the employees table? What if I need to add another user type later?
UPDATE
Would it make sense to change my schema into something simpler?
My problem is that by using, as suggested, polymorphic relations I would end up to something like this:
$user = new User::userable()->employable()->...
Would a schema in which I drop the employees table and have employee_managers and employee_basics linked straight to the users table?
this is an polymorphic relationship. but if you want to be easy, you need to fix some things.
in the table employees
- user_id
- employable_id
- employable_type enum(Manager, Basic) # References to the target model
.... this last two are for the polymorphic relation, this is the nomenclature
in the basics and managers table you could delete the user_id field, but you need an id field as increments type
and now in the model Employee you need to make this function
public function employable(){
return $this->morphTo();
}
I hope this works :)

Laravel - Database relationships

Let's consider a simple scenario of 'Company' and 'Employee' models.
A company has many employees. Now, when I map this relationship in Laravel, what is the correct approach from the following?
Approach 1:
Employee belongsTo() Company and Company hasMany() Employee
Approach 2:
Company belongsToMany() Employee and Employee hasOne() Company
Basically, what is the difference between belongsTo()-hasMany() and belongsToMany()-hasOne()?
There are three different approaches, in your question you're mixing them up a little. I'll go through all of them.
Many-to-many
A many-to-many relationship would mean, in your example, that a company can have multiple employees and that an employee can work for multiple companies.
So when you're using the belongsToMany() method on a relation, that implies you have a pivot table. Laravel by default assumes that this table is named after both other tables, e.g. company_employee in the example. Both the Company model and the Employee model would then have belongsToMany() relations.
Many-to-one
However, using hasMany() means that it's a one-to-many relationship. If we look at the example again, a company might have many employees but each employee would only be able to be employed by one company.
In the models, that means the Company would have a hasMany() method in its relationship declaration, while the Employee would have a belongsTo() method.
One-to-one
Finally, hasOne() means that it's a one-to-one relationship. What it would mean in your example is that each company may only have one employee. Since the inverse of hasOne() is also belongsTo(), in this scenario, too, every employee could be employed by only one company.
The Company model would then have a hasOne() relationship method, with the Employee having a belongsTo() method.
In practice, you almost always want to construct a database that is as close to reality in its representation as possible. What relationships you use depends on what your case looks like. In the example, I would guess that you want a many-to-one approach, with a foreign key on the employees table, that references the id on the companies table. But ultimately, that's up to you. Hope that helped. :)

Conditional Relationship in laravel Eloquent

Let I have 3 table named user, admin, post
My post table structure is
-id
-poster_id
-poster_type //if value is 1 then poster_id will be releted with user table. if value is 2 then poster_id releted with admin table.
Now How writte belongsTo relationship with two table based on poster_type value
I want to do in Post model like this
public function Author(){
return $this->belongsTo('User', 'poster_id')->where('poster_type', '1') //poster_type is the field of post table.
}
First of all, you are talking about a Polymorphic relationship, supported by eloquent. You should take a look at the documentation.
http://laravel.com/docs/eloquent#polymorphic-relations
Second, you are mixing Eloquent relationships with special data recovery functions, and that's something you should avoid. I suggest you split the relationship itself from the data recovery function.
Also, if you want to go one step further, keep the relationship in the model, and split the data recovery functions into a repository object.

Dynamically set the table name in a "has many" relation model

In my database schema, I have multiple tables that hold generic data for objects, for instance I have a user table and a user_data, post table and post_data, and so. these *_data tables all hold a foreign key to the object and a pair of key-value. now in my laravel models I would like to have a single data models for these tables (rather than a model for every single one) and represent the has_many relation in a dynamic way where somehow I can define the table name according to the parent model. I think the parent model would have something like:
return $this->hasMany('data');
but I don't know how to express the inverse relation nor how to tell laravel which *_data table to use. so my question is, is it possible? and if so, how?
You have two options.
Either create a model for each data_* table and use the relation as stated with $this->hasMany('data'); and $this->belongsTo('User'); in the data table and the user table.
Or you can use Polymorphic relations, I personally prefer the polymorphic relations solution, more neat.

Eloquent hasManyThroughOne

Laravel 4.1 introduced the hasManyThrough relationship. This assumes 2 relating hasMany relationships. I however would like to retrieve the hasMany relationships of a belongsTo relationship instead.
Project (id, contact_id, ...)
Contact (id, ...)
Address (id, contact_id, ...)
For each project, I would like to get all addresses.
I managed to do this using a belongsTo() relationship and some additional table joining. However, a belongsTo relationship binds a single object, instead of an array.
So my thoughts are I either need to:
... be able to override the LIMIT 1 behavior on belongsTo relationships
... or be able to override the hasManyThrough to work with a belongsTo as intermediate relationship.
It sounds like you are trying to set up a many-to-many relationship between Projects and Contacts, with a one-to-one relationship between Address and Contact. If that is the case you will need to create a pivot table "project_contact" with columns "project_id" and "contact_id" as well as any other columns (timestamps(), etc). Then you can set a "belongsToMany('Project')" relationship on the Contacts.
I'm not sure if that is what you're after, but it solves the problem as I understand it.

Resources