In the eloquent box there are a bunch of different cool pribluds for using links. But I have been suffering for a very long time with more complex (and even simple) connections, using these very pribludy.
For example, how to implement the One-to-One through One (or pivot) connection, so that this connection would work normally through ->with('relation') or ->whereHas('relation') ?
My current code, which does not work in full Eloquent functionality:
<?php class User { /** * User Jobs * * @return \Illuminate\Database\Eloquent\Relations\HasMany */ public function jobs() { return $this->hasMany(Job::class, 'client_id'); } /** * User Bids * * @return mixed */ public function bids() { return $this->hasMany(Bid::class, 'writer_id')->with('job'); } } class Bid { /** * Job relation * * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ public function job() { return $this->belongsTo(Job::class)->withTrashed(); } /** * User writer relation * * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ public function writer() { return $this->belongsTo(User::class, 'writer_id'); } /** * User writer relation (alias) * * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ public function user() { return $this->writer(); } } class Job { /** * Bids relation * * @return \Illuminate\Database\Eloquent\Relations\HasMany */ public function bids() { return $this->hasMany(Bid::class); } /** * User owner relation (alias) * * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ public function user() { return $this->client(); } /** * User owner relation * * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ public function client() { return $this->belongsTo(User::class, 'client_id'); } /** * Won bid relation * * @return \Illuminate\Database\Eloquent\Relations\HasOne */ public function wonBid() { return $this->hasOne(Bid::class)->whereNotNull('accepted_at'); } /** * User winner model * * @return \App\Models\User|null */ public function getWinnerAttribute() { return $this->wonBid ? $this->wonBid->writer : null; } } Customer (User) has jobs (Jobs)
User (User) has bets (Bids)
Jobs has bids, and one winning bid (Bids) with non-empty accepted_at
So, how to reach the executor with the help of eloquent? something like App\Models\Jobs::whereHas('winner')->get()
There were options:
<?php public function winner() { $related = User::class; $foreignKey = 'id'; $localKey = 'job_id'; $relation = 'winner'; /** @var \App\Models\User $instance */ $instance = $this->newRelatedInstance($related); $builder = $instance->setTable('users')->newQuery() ->selectRaw('users.id') ->rightJoin( DB::raw(" (select `bids`.`accepted_at`, `bids`.`writer_id`, `bids`.`job_id`, `bids`.`id` from `bids` where `bids`.`accepted_at` is not null) `bids` "), 'users.id', '=', 'bids.writer_id' ); $foreignKey = $foreignKey ?: $this->getForeignKey(); $localKey = $localKey ?: $this->getKeyName(); return (new BelongsTo($builder, $this, $foreignKey, $localKey, $relation)) ->from('users'); }