Задать вопрос
Fragster
@Fragster
помогло? отметь решением!

Как сделать динамический scope в relation?

Есть вот такая схема:
Vl4N9Mx.png

Задача получить все AgreementType с информацией, есть ли для указанного Profile запись в agreement_profile с agreement_profile.agreement_id == agreement_types.last_agreement_id

Как сделать обычным запросом - понятно.
Со скоупами и отношениями пока так:

классы моделей

class AgreementType extends Model
{
//
  public function agreements(): HasMany
  {
    return $this->hasMany(Agreement::class);
  }

  public function lastApproved(): HasOne
  {
    return $this->hasOne(AgreementProfile::class, 'agreement_id', 'last_agreement_id');
  }

  public function lastApprovedByProfile(string $profileId): HasOne
  {
    return $this->hasOne(AgreementProfile::class, 'agreement_id', 'last_agreement_id')->where('profile_id', $profileId);
  }
//
}

// модель для использования в качестве связи 
class AgreementProfile extends Pivot
{
}

// соглашения
class Agreement extends Model
{
  public function agreementType(): BelongsTo
  {
    return $this->belongsTo(AgreementType::class);
  }

  public function profiles(): BelongsToMany
  {
    return $this->belongsToMany(Profile::class)->withTimestamps();
  }
}

// профили
class Profile extends Model
{
  public function agreements(): BelongsToMany
  {
    return $this->belongsToMany(Agreement::class)->withTimestamps();
  }
}



Вот так получилось сделать что нужно:
$user = User::where('phone', '75555555555')->first();
    $profile = $user->profile;

    $query = AgreementType::whereNotNull('last_agreement_id')->withExists(['lastApproved as last_agreement_approved' => function ($q) use ($profile) {
      $q->where('profile_id', $profile->id);
    }]);
    $data = $query->get();


Хочу сделать более лаконично, чтобы использовать в нескольких местах. При попытке использования динамического скоупа у связи не понимаю, как туда передать параметр. При использовании withExists('lastApprovedByProfile') закономерно выдается ошибка
Too few arguments to function App\Models\AgreementType::lastApprovedByProfile()
.

Есть ли возможность использования динамических скоупов со связями?
  • Вопрос задан
  • 36 просмотров
Подписаться 1 Средний 1 комментарий
Решения вопроса 1
Fragster
@Fragster Автор вопроса
помогло? отметь решением!
Надо у AgreementType вместо связи создать динамический скоуп:
public function scopeWithLastApprovedByProfile(Builder $query, string $profileId): void
  {
    $query->withExists(['lastApproved as last_agreement_approved' => function ($q) use ($profileId) {
      $q->where('profile_id', $profileId);
    }]);
  }

и использовать как обычный динамический скоуп:
AgreementType::whereNotNull('last_agreement_id')->withLastApprovedByProfile($profile->id);
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы