Laravel 5 eloquent - add child field to parent mod

2019-08-18 01:56发布

I have a user model which has a child relationship called teacher. How can I add a field from the related teacher model to the dataset returned of the parent user model?

I would like the user model returned to have a structure like below:

user.firstname

user.lastname

user.teacher.address

I have tried using the following and variations thereof with no success:

            $query->select('firstname', 'lastname')
            ->addSelect( \DB::raw('teachers.address AS address') );

user.php model:

    use Notifiable;
use SoftDeletes;
use EncryptableTrait;

/**
 * The attributes that are mass assignable.
 *
 * @var array
 */
protected $fillable = [
   'title',
   'firstname',
   'firstname_h',
   'lastname',
   'lastname_h',
   'email',
   'email_h',
   'password',
   'userable_id',
   'userable_type'
];

/**
 * The attributes that are mass encryptable, using the EncryptableTrait.
 *
 * @var array
 */
protected $encryptable = [
    'firstname',
    'lastname',
    'email',
];

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

public function userable()
{
    return $this->morphTo();
}

public function teacher() // Using custom BelongsToMorph relationship type
{
    return BelongsToMorph::build($this, Teacher::class, 'userable');
}

public function roles()
{
    return $this->belongsToMany('App\Role')->withTimestamps();
}

public function schools()
{
    return $this->belongsToMany('App\School')->withPivot('suspended', 'rating');
}

public function thisSchool()
{
    return $this->belongsToMany('App\School')->where('school_id', Auth::user()->userable->id)->withPivot('id', 'suspended', 'rating', 'notes');
}

public function addRole($user, $role_id)
{
    $user->roles()->attach($role_id);
}

public function removeRole($user, $role_id)
{
    $user->roles()->detach($role_id);
}

public function isAdmin($user)
{

    foreach ($user->roles as $role) {

        if($role->id == 4) {

            return true;

        } else {

            $return = false;

        }

    }

    return $return;

}

public function isSchoolAdmin($user)
{

    foreach ($user->roles as $role) {

        if($role->id == 2) {

            return true;

        } else {

            $return = false;

        }

    }

    return $return;

}

public function events()
{
    return $this->belongsToMany('App\Event')->withPivot('cancelled', 'cancelled_by');
}

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

public function teachingstages()
{
    return $this->belongsToMany('App\Teachingstage', 'teacher_teachingstage')->orderBy('teachingstage_id');
}

public function teachingsubjects()
{
    return $this->belongsToMany('App\Teachingsubject', 'teacher_teachingsubject');
}

teacher.php model:

    use EncryptableTrait;

protected $table = "teachers";

/**
 * The attributes that are mass assignable.
 *
 * @var array
 */
protected $fillable = [
   'mobile',
   'dob',
   'gender',
   'address',
   'postcode',
   'latitude',
   'longitude',
   'max_distance',
   'public',
   'photo',
   'experience',
   'active',
   'verified',
   'payscale',
   'ta_number',
   'temp_or_perm',
   'locked'
];

/**
 * The attributes that are mass encryptable, using the EncryptableTrait.
 *
 * @var array
 */
protected $encryptable = [
    'mobile',
    'address',
    'postcode',
    'experience',
    'ta_number'
];

public function user()
{
    return $this->morphOne('App\User', 'userable');
}

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

public function bookingrequests()
{
    return $this->belongsToMany('App\Bookingrequest')->withPivot('sent', 'sent_at', 'declined', 'created_at', 'updated_at');
}

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

This is my existing query that I am having issues with:

        $query = User::where('userable_type', 'App\Teacher');

        $query->with('userable');

        $query->select('firstname', 'lastname')
            ->addSelect( \DB::raw('teachers.address AS address') );

        $query->whereDoesntHave('thisSchool');

        $otherTeachers = $query->get();

This is an existing app and everything works as expected; my question is more about how I can add a child model column as an alias to the parent model (I will then use the new alias columns to calculate something).

Thanks in advance,

K...

1条回答
走好不送
2楼-- · 2019-08-18 02:51

OK, I worked this out myself in the end.

I added a scope to my user model:

    public function scopeJoinWithTeacher($query)
{
    return $query->leftJoin("teachers", "teachers.id", "=", "users.userable_id");
}

I then implemented this new scope in my query and aliased columns from child to parent model in the get():

    $query = User::where('userable_type', 'App\Teacher');
    $query->with('userable');
    $query->whereDoesntHave('thisSchool');
    $query->JoinWithTeacher();
    $query->orderBy( 'distance', 'ASC' );

    $otherTeachers = $query->get(['teachers.longitude AS longitude', 'teachers.latitude AS latitude', 'users.*']);

I now have the longitude and latitude columns from the teacher child relation in my parent model returned from eloquent. In my specific case, I then go further to use these alias fields to calculated distance and create a new alias called distance in my user model.

Hope that helps somebody who was attempting the same thing!

K...

查看更多
登录 后发表回答