How to Find a Model's Relationships

Get all relationships from Eloquent model

To accomplish this, you will have you know the names of the methods within the model - and they can vary a lot ;)

Thoughts:

  • if you got a pattern in the method, like relUser / relTag, you can filter them out

  • or loop over all public methods, see if a Relation object pops up (bad idea)

  • you can define a protected $relationMethods (note: Laravel already uses $relations) which holds an array with method.

After calling Post->User() you will receive a BelongsTo or 1 of the other objects from the Relation family, so you can do you listing for the type of relation.

[edit: after comments]

If the models are equipped with a protected $with = array(...); then you are able to look into the loaded relations with $Model->getRelations() after a record is loaded. This is not possible when no record is loaded, since the relations aren't touched yet.

getRelations() is in /vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php

But currently it doesn't show up in the api at laravel.com/api - this is because we got newer version

How to get all data from a Eloquent Model with it's relations?

The issue was that in the company model, the user and the address methods were referencing with the hasOne() method to other models. It was looking for a secondary key to be in the users' table, not in the companies one.

Simply swapping up the hasOne() with belongsTo fixed out my issue.

So now my Company.php model looks like:

public function user()
{
return $this->belongsTo(User::class);
}

public function address()
{
return $this->belongsTo(Address::class);
}

User.php

public function company()
{
return $this->hasOne(Company::class);
}

Address.php

public function company()
{
return $this->hasOne(Company::class);
}

Now we can get all the list of companies with their user and address by Company::with('user')->with('address')->get();

Get array of Eloquent model's relations

It's not possible because relationships are loaded only when requested either by using with (for eager loading) or using relationship public method defined in the model, for example, if a Author model is created with following relationship

public function articles() {
return $this->hasMany('Article');
}

When you call this method like:

$author = Author::find(1);
$author->articles; // <-- this will load related article models as a collection

Also, as I said with, when you use something like this:

$article = Article::with('author')->get(1);

In this case, the first article (with id 1) will be loaded with it's related model Author and you can use

$article->author->name; // to access the name field from related/loaded author model

So, it's not possible to get the relations magically without using appropriate method for loading of relationships but once you load the relationship (related models) then you may use something like this to get the relations:

$article = Article::with(['category', 'author'])->first();
$article->getRelations(); // get all the related models
$article->getRelation('author'); // to get only related author model

To convert them to an array you may use toArray() method like:

dd($article->getRelations()->toArray()); // dump and die as array

The relationsToArray() method works on a model which is loaded with it's related models. This method converts related models to array form where toArray() method converts all the data of a model (with relationship) to array, here is the source code:

public function toArray()
{
$attributes = $this->attributesToArray();

return array_merge($attributes, $this->relationsToArray());
}

It merges model attributes and it's related model's attributes after converting to array then returns it.

How can I find a model's relationships?

Dog.reflect_on_all_associations

http://api.rubyonrails.org/classes/ActiveRecord/Reflection/ClassMethods.html#M001405

You wouldn't do this on an instance but on the model itself.

Always get related model of relationship model in Laravel Eloquent

To load the Localization with the ordersArea() relation, you can use Eager loading. You can read more about this in the documentation: Eager Loading.

Example

$company->ordersArea()
->with('localization')
->first();

Alternatively, you can add the protected $with = ['localization']; to your OrdersArea model. This will always load the localization with the OrdersArea. You should only use this if that relation is always required.

You can also retrieve the relation after the parent model has already been retrieved. This is called Lazy Eager Loading.

$ordersArea = OrdersArea::find($id);
$ordersArea->load('localization');

How to never get Model without relationships in Eloquent?

You can enable eager loading by default if you add the relationship to the $with property of the model as described here: https://laravel.com/docs/9.x/eloquent-relationships#eager-loading-by-default

The documentation reads:

Sometimes you might want to always load some relationships when
retrieving a model. To accomplish this, you may define a $with
property on the model:

=====Edit1

Another option is using Global Scopes https://laravel.com/docs/9.x/eloquent#global-scopes.
You can go from here, you can add some more logic to exclude models without the relationship.
=====Edit2

The extra logic will be adding this from the documentation:
https://laravel.com/docs/9.x/eloquent-relationships#querying-relationship-existence

protected static function boot(){
parent::boot();
static::addGlobalScope('relation', function($builder){
$builder->has('relation')->with('relation');
});
}

Eloquent - Get Model with relationship as boolean

First, you can find how many likes does user make to the comment, in this way.

$likes = Comment::whereHas(['likes' => function($q) use ($user){
$q->where('user_id', $user->id);
})->where('post_id', $postId)->count();

Then using $likes variable value, you can conditionally create a boolean value and assign to new variable or same $likes variable.

$hasLike = $likes ? true : false;


Related Topics



Leave a reply



Submit