Self Relationship with Laravel

Asked

Viewed 1,261 times

5

I have the following problem trying to make a self relationship with Laravel 5. I want to make a user registration, where users may have other users linked, creating an autorelationing N x N, user_user;

The user will have a status, and this status is another model.

class User extends Authenticatable{

protected $fillable = [
    'name', 'email', 'password', 'status_id'
];

...

class Vinculo extends Model{

protected $fillable = [
    'id', 'user_id', 'vinculo_id'
];

....

class StatusUser extends Model{

protected $fillable = [ 
    'id', 'nome',       
];

..

and in my Usercontroller I query the user with status

public function show($id){  

    $result = $this->context->with('statususers')->find($id);

...

that returns the json,

{
"id": 2,
"name": "aa",
"email": "[email protected]",
"statususers": {
    "id": 2,
    "nome": "Ativo"
}

}

..

Now my question is, how to query all users related to a specific user, and that on linked users can also be displayed the status of each,

Relationship in the User class

    public function vinculos(){
    return $this->belongsToMany('App\User', 'vinculos', 'user_id', 'vinculos_id');
}

...

I modify the show method, including the relationship links

    public function show($id){  

    $result = $this->context->with('statususers')->with('vinculos')->find($id);

Relationship is ok, but is not returning the status of linked users, this is the problem.

{
"id": 2,
"name": "aa",
"email": "[email protected]",
"remember_token": "Y7cc9OHpKalEkKivihETU2LQeNftGWZ1hqVH0v2nM1z0DZ3dUe3emwsIDxec",
"statususers": {
    "id": 2,
    "nome": "Ativo"
},
"vinculos": [
    {
        "id": 3,
        "name": "bb",
        "email": "[email protected]",
        "pivot": {
            "user_id": 2,
            "amigo_id": 3
        }
    }
        {
        "id": 4,
        "name": "cc",
        "email": "[email protected]",
        "pivot": {
            "user_id": 2,
            "amigo_id": 3
        }
    }
]

}

This is the big question, if my related object is of the User class, why do not other users also show their respective status objects, equal to the parent record of the links? Seeing that all other attributes of the User class are displayed correctly, but the status object is missing..

Can someone help me?

3 answers

4

Maybe what you’re trying to do is use the nested relationship.

It is a way to bring, through the method with, a relationship relationship.

Example: posts relates to usuários, and each user has one país.

In the Laravel We could do so:

 Post::with('usuario.pais')->get();

The result would be something like this representation:

[
   'id'    => 1,
   'texto' => 'Meu post',
   'usuario_id' => 1,
   'usuario' => [
      'id'   => 1,
      'nome' => 'Wallace',
      'pais_id' => 1,
      'pais' => [ 'id' => 1, 'Brasil',]
   ]

]

Another detail. I forgot to mention that you should not use the methods with in sequence, because internally they do not use the $this to reference the instance itself, but use new static (I’ve already looked at the class source code Illuminate\Database\Eloquent\Model).

You must pass all arguments at once to with, and he must also be the first to be called.

Example (certain):

 Post::with('comments.people', 'images')->where('id', '=', 1);

 Post::with(['comments.people', 'images'])->where('id', '=', 1);

Examples (wrong):

 // isso anula a query anterior

 Post::where('id', '=', 1)->with('comments.people', 'images');


// isso só faz funcionar o último with

Post::with('comments.people')->with('images');

The other methods like where, lists, get and such, are of class Illuminate\Database\Eloquent\Builder. They are called through the magical method __call present in the class Model (her alias is Eloquent). Already the method with is a static method, and therefore it only serves to create a new instance of the model itself with the predefined relationships that will be loaded.

To show that I am not giving out any incorrect information, just check the code on github, on the line 672.

https://github.com/illuminate/database/blob/5.1/Eloquent/Model.php

1

Just make a hasMany.

Example: I am a person and I have several children, my dependents who are people..

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Pessoa extends Model
{
  // id, usuario_id, nome, rg, cpf, foto_url, data_nascimento, endereco_id, responsavel_id, fornecedor_id

  protected $fillable =
  ['usuario_id', 'nome', 'rg', 'cpf', 'foto_url', 'data_nascimento', 'responsavel_id', 'fornecedor_id'];

  public $timestamps = false;


  public function dependentes()
  {
    return $this->hasMany('App\Pessoa','responsavel_id');
  }

  public function contatos()
  {
    return $this->hasOne('App\Contato');
  }

}

1

Good afternoon, you guys, So, Wallace, that’s not exactly what I wanted, but I got it sorted.

Gave a great search in the documentation of Laravel, and I ended up seeing that by default the relationships use the form Eager Load, that will only load the objects when they are accessed, that for performance and such..

In my case, I had to force the load using Lazy Load, which loads all instances, causing all objects to be listed the way I wanted them to,

the result obtained was this:"

{
"id": 2,
"name": "aa",
"email": "[email protected]",
"statususers": {
    "id": 2,
    "nome": "Ativo"
},
"vinculos": [
    {
        "id": 3,
        "name": "bb",
        "email": "[email protected]",
        "statususers": {
            "id": 2,
            "nome": "Ativo"
         },
        "pivot": {
            "user_id": 2,
            "amigo_id": 3
        }
    }
        {
        "id": 4,
        "name": "cc",
        "email": "[email protected]",
        "statususers": {
            "id": 2,
            "nome": "Ativo"
         },
        "pivot": {
            "user_id": 2,
            "amigo_id": 3
        }
    }
]

The status of linked users is now being listed.

Thank you, thank you!

  • 1

    But you force the load of relationships by doing the way I did. I don’t understand what’s wrong with my answer. You showed your json, but you didn’t show how you got the result. It’s good to post here so others understand how you solved the problem.

  • 2

    I won’t take the negative until I have the real solution to the problem. Demonstrate how the expected return of the data is not the solution of the problem, you need to show the code with which you arrived at it.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.