Допустим, я уже загрузил отношения и теперь хочу получить модели, которые им соответствуют.
Есть ли способ сделать это объективно, а не напрямую использовать идентификаторы?
Вот пример контроллера, описывающий то, чего я хочу достичь:
public function videos(User $user, Category $category)
{
$videos = Video::where('user', $user)->where('category', $category)->get();
// ...
}
Я знаю, что могу сделать это так, но я бы хотел пропустить извлечение идентификатора и оставить его, если возможно, фреймворку:
public function videos(User $user, Category $category)
{
$videos = Video::where('user_id', $user->id)->where('category_id', $category->id)->get();
// ...
}
В where('table_column', $value) или where(['table_column' => $value]) вы можете увидеть, что ищет Eloquent Builder. Ответственный код: здесь. Хотя я не вижу выгоды в том, что вы хотели бы сделать, вы могли бы написать какую-то оболочку, которая перезаписывает поведение метода where по умолчанию - НЕ рекомендуется вообще, потому что вы можете потерять больше, чем получить.
Или еще, вы можете написать собственный метод в модели видео, который возвращает то, что вам нужно: $userVideosOfCategory = Video::userVideoOfCategory(User $user, Category $category); и логику, которую вы создаете в методе пользовательской модели видео. Логика может быть похожа на policy / gate.
Это в основном для более чистого кода. И чтобы реализация не просочилась наружу. Чем меньше вещей в общедоступном API, тем больше я могу изменить позже, не рискуя проблемами совместимости. Также, для ясности, мне не нужно придерживаться метода where. Если мне просто нужно указать имя отношения и объект, я буду счастлив, даже если это отдельный метод, например. whereRelated('user', $user)






Значит, у вас будет видео, которое принадлежит пользователю, верно? Вы могли бы сделать что-то вроде этого:
В вашей модели пользователя:
public function videos()
{
return $this->hasMany(Video::class);
}
И тогда вы можете назвать эту функцию как
$user->videos();
или
$this->user->videos->toArray();
Если вы начнете создавать подобные отношения в модели, это может значительно упростить получение данных. Возможно, это не полный ответ, но он определенно на правильном пути. Удачи!
Красноречивые отношения: https://laravel.com/docs/5.7/eloquent-relationships
Это работает с одиночными отношениями, и именно так я делал это в течение некоторого времени, но теперь я попал в пример использования, когда мне нужно проверить 2 отношения, и в будущем их может быть больше, поскольку мой класс будет становиться более сложным.
Возможно, вы захотите проверить "имеет много сквозных" - похоже ли это на те отношения, которые вы будете формировать? laravel.com/docs/5.7/eloquent-relationships#has-many-through
Это не идеально, но я нашел способ легко это сделать с помощью прицелов. Вот мой код:
trait WhereBelongsTo
{
/**
* @param \Illuminate\Database\Eloquent\Builder|self $query
* @return \Illuminate\Database\Eloquent\Builder|self
*/
public function scopeWhereBelongsTo($query, $relationship, $value)
{
/** @var \Illuminate\Database\Eloquent\Relations\BelongsTo $relationship */
$relationship = call_user_func([$this, $relationship]);
$foreignKey = $relationship->getForeignKey();
$ownerKey = $relationship->getOwnerKey();
if ($value === null) {
return $query->whereNull($foreignKey);
} else {
return $query->where($foreignKey, $value->$ownerKey);
}
}
}
После добавления этой черты в Модель я могу использовать ее так:
public function videos(User $user, Category $category)
{
$videos = Video::whereBelongsTo('user', $user)->whereBelongsTo('category', $category)->get();
// ...
}
Это просто для знаний и более чистого кода?