Laravel - Hierarchy in Eloquent model - laravel

my database have this hierarchy:
- Manager:
- Coordinator:
- Supervisor:
- Operator
this code, output all "coordinator" belongs to "manager":
Manager::find(1)->coordinator()->get();
is possible get all "supervisor" belongs to "coordinator" directly? Example:
Manager::find(1)->coordinator()->supervisor()->get();
Sorry by english, i'm brazilian

That is perfectly possible, you just need to define all the relationship in your models. Then you could retrieve all all your "operators" for a specific "manager" by doing:
Manager::find(1)->coordinator->supervisor->operator;
In that code, I'm using dynamic properites that come with Eloquent ORM.
When I said 'you need to defin all the relationships in your models' doing the following:
class Manager extends Eloquent
{
public function coordinator()
{
return $this->hasMany('Coordinator');
}
}
Then you will do the same for coordinator that has many supervisors and for supervisor that has many operators.
See the documentation about Relationship, one-to-many, in Laravel 4.

Related

How do I use a Laravel dynamic relationship?

I am a newbe in Laravel. The docs show how to use relationships like this:
One To Many (Inverse) / Belongs To
Now that we can access all of a post's comments, let's define a relationship to allow a comment to access its parent post. To define the inverse of a hasMany relationship, define a relationship method on the child model which calls the belongsTo method:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Comment extends Model
{
/**
* Get the post that owns the comment.
*/
public function post()
{
return $this->belongsTo(Post::class);
}
}
Once the relationship has been defined, we can retrieve a comment's parent post by accessing the post "dynamic relationship property":
use App\Models\Comment;
$comment = Comment::find(1);
return $comment->post->title;
My question is: Where is this code? In a controller or in a view?
If you use MVC structure, you should understand that
Model is layer where you store your data
View is layer where you should only display your data
and Controller is layer where you can keep your logic.
If you have a lot of difficult logic or big application, you should better to use Services, as layer between Controllers And Models.
Receiving Comments from model and prepeare them should be in controller level. In view level you just define how to show them to user.
I hope it will help you to understand difference between logic layers.
you can access this relationship in controller or view like this-
suppose you want to make relation between product model and brand model:-
in product model:-
public function brand(){
return $this->belongsTo('App\Model\Brand','brand_id','id');
}
now you are able to see which product belongs to which brand without any query or using loop.
just do in controller:-
$product=Product::with('brand')->get();
here you get all the data...
and when you use it on **view **just do it:
{{$product->brand->brand_name}}
//brand name should the column name
I hope you understood...
Happy Learning!

hasManyThrough with an intermediate pivot table

Description:
My application is structured as follows:
Property has a Many-Many relationship with Manager, and a Unit has a One-Many relationship with a Property, i.e. A manager can manage multiple properties, one property can have multiple manager accounts and one property can have multiple units.
I would like to have a HasManyThrough relationship on the manager to get all his units, so ideally it would look something like: $manager->units instead of having through loop through each property and call $property->units on it. Is this possible with the current version of laravel?
Tables:
managers:
id
properties:
id
managers_properties:
manager_id
property_id
units:
id
property_id
Eloquent currently does not have methods for chained relations, other than the hasManyThrough, that is only applicable to 2 chained hasMany relations. You should create your own implementation to fetch the related resources. The simplest way is to define an accessor on the Manager model:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Support\Collection;
/**
* #property-read Collection|\App\Models\Property[] $properties
* #property-read Collection|\App\Models\Unit[] $units
*/
class Manager extends Model
{
public function properties(): BelongsToMany
{
return $this->belongsToMany(Property::class);
}
public function getUnitsAttribute(): Collection
{
return $this->properties
->pluck('units')
->flatten(1)
->unique('id')
->sortBy('id');
}
}
You should now be able to access the related units with $manager->units assuming $manager instanceof App\Models\Manager.
Note
Calling $manager->units does perform at most n + 1 database queries: 1 for fetching n related properties, and another n for fetching related units for each returned property. "At most" because the resources might have been loaded already because of previous calls to the accessor.
Note
Calling $manager->units returns you a Collection of Unit models, a format that's equivalent to what you'd get from the magic accessor of a to-many relationship method. However getUnitsAttribute() is not an actual relationship method (it does not return a relationship object), so it can not be treated as such, whereas Manager::properties() can be.

Reverse polymorphic relation in Laravel 5

Suppose we have following models: a Warrior, an Axe and a Sword
Is there a way to make the following behavior possible?
$warrior->weapon = $sword;
// ...
or
$warrior->weapon = $axe;
// ...
In other words, is it possible to treat separate models as if they had similar types with Eloquent?
P.S
Obviously, above is a simplified example of a problem only serving the purpose of conveying the gist of it.
Yes, you can make weapon a polymorphic relation. Add columns weapon_type and weapon_id to your table, which can be done in a migration file with the morphs type:
Schema::table('warriors', function ($table) {
$table->morphs('weapon');
});
Now you are ready to add your relationship to the Warrior model:
public function weapon() {
return $this->morphTo();
}
That's it! Now you can add the weapon and Eloquent will take care of the rest. The relation even supports eager loading. I suggest that all your weapons should implement an interface so you know what methods they have in common, but unfortunately there is no way for Eloquent to enforce that interface for you through the PHP type system.

Model relationship in Laravel

I have 2 controllers & Models:
User Controller: (Model Relationship: $this->hasMany(Hero::Class);)
Hero Controller: Each hero has his own attributes, such as name, strength and life.
Model Relationship: ($this->belongsTo(User::class);)
Each user can own multiple heroes.
that means that USER ID: 1 may have 3 heroes: HERO ID 5, 20, 26..
My question: How to define the relationships like that and make laravel knows how to handle my user_heroes table?
The relationship i'm talking about is described in the following image:
How to I setup such kind of relationship in my laravel API?
If a User can have many heroes, and a Hero can also belong to many users, it is a many to many relationship. In Laravel the inverse of a many to many relationship is also a many to many relationship, and they are both described by belongsToMany().
https://laravel.com/docs/5.2/eloquent-relationships#many-to-many
So in your User model:
public function heros() {
return $this->belongsToMany(Hero::class);
}
And in your Hero model:
public function users() {
return $this->belongsToMany(User::class);
}
Laravel will assume the joining table is named hero_user, the 2 model names, singular, joined in alphabetical order. If you want to use user_heroes as you have in your image, you need to specify it:
return $this->belongsToMany(Hero::class, 'user_heroes');
(in both model methods).

Correct relationship in Laravel

I have four tables in database: groups, specialties, lessons, group_lesson. It's structures:
groups
id
specialty_id
name
specialties
id
name
lessons
id
specialty_id
group_lesson (UNIQUE INDEX lesson_id, group_id)
lesson_id
group_id
date
My models look like that for now:
class Group extends Eloquent {
public function specialty() {
return $this->belongsTo('Specialty');
}
}
class Lesson extends Eloquent {
public function specialty() {
return $this->belongsTo('Specialty');
}
}
class Specialty extends Eloquent {
public function lessons() {
return $this->hasMany('Lesson');
}
public function groups() {
return $this->hasMany('Group');
}
}
I need get additional fields in Group model look like that
Group - Eloquent model
name - string
lessons - collection of Lesson models of Group Specialty
date - date from group_lesson table
I've tried different relationships and combinations, but it's doesn't work. Please help me to write correct relationships.
You can use eager-loading to access relational data through relationships, and can even chain relationships further. As a rule of thumb, if you can draw a path to from 1 model to another through a relationship, you can eagerload all the relevant and relational data for that with chained eager-loads.
Laravel Eager Loading
As an example
$speciality_group = Speciality::with('group','lessons')->find($id);
Even though you are only getting a single instance of the speciality model, the related data is hasMany, meaning multiple records. You need to loop through these records using a foreach loop to access the relevant data for them, or alternitavely add additional closures in your initial query to load only a single related model.
foreach($speciality_group->group as $group)
{
echo $group->name;
}
You will need to do this for both instances where you want to display related information.

Resources