C4pt4inC4nn4bis
C4pt4inC4nn4bis

Reputation: 588

Lazy eager loaded relationship missing in toArray()

Laravel 5.8

I am lazy loading an user with the related customer which has a one-to-one-relation with a crmaccount-object

The models are working so that when i retrieve the eager-loaded entity it shows all of the nested relationships.

One row later i use the "toArray()" method on that object and the output is missing the third-level-relations.

The only thing which maybe some kind of special regarding the "crmaccount"-model is that it holds a column which is json an has to be casted.

Any idea what is going on here?

enter image description here

enter image description here

All of these happens in a middleware. No difference if i use with or load.

public function handle($request, Closure $next)
{
    $UserData = \Auth::user();
    if($UserData){
        $User = \App\Login::with(['role','customer','customer.crmaccount'])->find($UserData->id);
        dump($User);
        dd($User->toArray());


        $UserData['isAdmin'] = false;
        if($UserData['role']['name'] === 'Admin'){
            $UserData['isAdmin'] = true;
        }
        $request->request->add(['UserData' => $UserData]);
    }

    return $next($request);
}

Login

<?php

namespace App;

use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;

class Login extends Authenticatable{
    use Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name', 'email', 'password','customer_id','role_id'
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];

    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
    ];
    /* */
    public function Role(){
        return $this->belongsTo('App\Role');
    }
    public function Customer(){
        return $this->belongsTo('App\Customer');
    }
    /**
     * [hasOpportunities Ruft alle Opportunities des Users ab. Da diese lediglich zwei Entitäten weiter sind, kann anstatt von dot-notated Lazy-Load auch die hasManyThrough-ORM-Methode genutzt werden]
     * @return [hasManyThrough-Relation] [Die hasManyThrough-ORM-Beziehung]
     */
    public function hasOpportunities(){
        return $this->hasManyThrough(
            'App\Opportunity',
            'App\Customer',

            'id',
            'customer_id',
            'customer_id'
        );
    }
    /**
     * [hasSalesreps Ruft alle SalesReps des Users ab. Da diese lediglich zwei Entitäten weiter sind, kann anstatt von dot-notated Lazy-Load auch die hasManyThrough-ORM-Methode genutzt werden]
     * @return [hasManyThrough-Relation] [Die hasManyThrough-ORM-Beziehung]
     */
    public function hasSalesreps(){
        return $this->hasManyThrough(
            'App\Salesrep',
            'App\Customer',

            'id',
            'customer_id',
            'customer_id'
        );
    }
}

Customer

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Customer extends Model{
    public $timestamps = false;

    protected $visible = ['id','name'];

    protected $fillable = ['name'];


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

    public function Salesreps()
    {
        return $this->hasMany('App\Salesrep');
    }

    public function Prospects()
    {
        return $this->hasMany('App\Prospect');
    }

    public function Trees()
    {
        return $this->hasMany('App\Salesreptrees');
    }

    public function Opportunities()
    {
        return $this->hasMany('App\Opportunity');
    }

    public function User()
    {
        return $this->hasMany('App\Login');
    }
}

Crmaccount

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Crmaccount extends Model{
    public $timestamps = false;
    protected $visible = ['id','name','crm_system','customer_id','crm_api_config'];
    protected $fillable = [
        'name','crm_system','customer_id','crm_api_config'
    ];
    protected $casts = [
        'crm_api_config' => 'array'
    ];
    public function customer(){
        return $this->belongsTo('App\Customer');
    }
}

Upvotes: 4

Views: 2024

Answers (1)

Tim Lewis
Tim Lewis

Reputation: 29258

On every model, there is a protected $visible = []; and protected $hidden = [] attribute. These control the attributes that are available when the model is converted to an object, array or json. This includes relationships, as Laravel internally converts them to attributes, so omitting them from visible, or including them in hidden will cause them to not be available.

In Customer.php:

protected $visible = ['id','name'];

Since crmaccount is not in that array, only id and name will be available. Simply add crmaccount to the array to handle:

protected $visible = ['id','name', 'crmaccount'];

Alternatively, use hidden to explicitly set the attributes you don't want to show, and relationship, if loaded via ->with() will show by default.

Upvotes: 5

Related Questions