Conditional Relationship in laravel Eloquent - laravel

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.

Related

When/why use the hasMany and belongsTo

In Laravel it is possible to use the hasMany() and belongsTo() methods in the Model to specify the relation between tables. This for one-to-many relations.
However in the migration files, this relation is also specified for the database by the
$table->foreign('userId')->references('id')->on('users')
Why does it to be specified double in Laravel?
Why does Laravel doesn't fetch the relationship from the database, and do we have to specify it double?
Laravel offers hasMany() and belongsTo() etc for quicker access to parent/child records between tables on the model level. For instance, you may access the child record with ->{attr}, which makes the child record as if an attribute of the parent record.
It also comes with other benefits, such as eager loading of child record by providing the relationship parameter into ->with() function.
In comparison, the usage of relation in migration files are to enforce relationship between tables on database level.

Creating a relationship from Pivot Table Field

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.

how do I make relationships for 4 tables including pivot table

I have many to many relationships. Imagine I have 3 tables. Something like this :
users.
roles.
role_user.
(This example is also provided in laravel's docs).
Now I'm doing this : $user->roles() which returns roles with Pivot attributes . but what I actually want to do is move forward and also get the appropriate data from the 4th table. something like this $user->roles()->types(); and the difficult thing is that this types() belongs to pivot table.
Do you know how to do this kind of thing ? where Do I write types() function?
Assuming your "Roles" model has the relationship set you may try
$user->roles()->with("types")
Source docs: https://laravel.com/docs/5.7/eloquent-relationships#eager-loading

Laravel5: How are Eloquent model relationships expressed in the database?

There's a missing link I fail to understand.
I use migrations to create database tables and I define the relationships there. meaning.. if I have a person table and a job table and I need a one to many relationship between the person and jobs, I'd have the job table contain a "person_id".
When I seed data or add it in my app, I do all the work of adding the records setting the *_id = values etc.
but somehow I feel Laravel has a better way of doing this.
if I define that one to many relationship with the oneToMany Laravel Eloquent suports:
in my Person model.....
public function jobs()
{
return $this->hasMany('Jobs);
}
what's done on the database level? how do I create the migration for such table? Is Laravel automagically doing the "expected" thing here? like looking for a Jobs table, and having a "person_id" there?
Yep, Laravel is doing what you guess in your last paragraph.
From the Laravel documentation for Eloquent Relationships (with the relevant paragraph in bold):
For example, a User model might have one Phone. We can define this
relation in Eloquent:
class User extends Model {
public function phone()
{
return $this->hasOne('App\Phone');
}
}
The first argument passed to the hasOne method is the name of the
related model. Once the relationship is defined, we may retrieve it
using Eloquent's dynamic properties:
$phone = User::find(1)->phone;
The SQL performed by this statement
will be as follows:
select * from users where id = 1
select * from phones where user_id = 1
Take note that Eloquent assumes the foreign key of the relationship based on the model name. In this case, Phone model is assumed to use a user_id foreign key.
Also note that you don't actually have to explicitly set the foreign key indexes in your database (just having those "foreign key" columns with the same data type as the parent key columns is enough for Laravel to accept the relationship), although you should probably have those indexes for the sake of database integrity.
There is indeed support to create foreign key relationships inside migration blueprints and it's very simple too.
Here is a simple example migration where we define a jobs table that has a user_id column that references the id column on users table.
Schema::create('jobs', function($table)
{
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users');
});
You can also use some other methods that laravel provides such as onDelete() or onUpdate
Of course to understand better the options that are available to you please read the documentation here.
Edit:
Keep in mind that Eloquent is just using fluent SQL wrapper and behind the scenes there are just raw sql queries, nothing magical is happening, fluent just makes your life a lot easier and helpers you write maintainable code.
Take a look here about the Query Builder and how it works and also, as #Martin Charchar stated , here about Eloquent and relationships.

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.

Resources