@geyurgfuyewgfyuguy

Laravel Relationships, как получить запись связывания?

Решил перейти на модели, постепенно изучаю доку, не много не понятно, как получить данные связывания, к примеру есть таблица:

posts - содержит записи
categories - содержит категории
posts_categories - содержит id поста и id категории

Подскажите, как получить эту связь?

Есть модели Posts и Categories
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Model;
use App\Models\Categories;

class Posts extends Model
{
    protected $table = 'posts';

    public function categories(): HasMany
	  {
	    return $this->hasMany(Categories::class);
	  }
}

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Model;
use App\Models\Posts;

class Categories extends Model
{
    protected $table = 'categories';

	  public function Posts(): BelongsTo
	  {
		  return $this->belongsTo(Posts::class);
	  }
}

Правильно ли я понимаю, что необходимо создать еще одну модель для получения posts_categories - содержит id поста и id категории? Или это можно сделать иным образом? И каким должен быть запрос, чтобы к примеру проверить, принадлежит ли категория к определенному посту, если нет, добавить новую запись в posts_categories.
  • Вопрос задан
  • 285 просмотров
Решения вопроса 3
delphinpro
@delphinpro Куратор тега Laravel
frontend developer
Если хотите меньше писать, то называйте таблицы правильно.
Связующие таблицы состоят из названий связываемых таблиц в единственном числе в алфавитном порядке.

У вас она должна называться category_post и содержать минимум два столбика unsignedBigInteger
post_id | category_id

Модели должны быть названы в единственном числе Category и Post

Отношения тоже следует называть соответственно. Тут интуитивно просто: если связь ко многим – множественное число (для отношений hasMany, belongsToMany), иначе единственное (для отношений hasOne, belongsTo).

Методы всегда называются в camelCase. Первая буква маленькая.

Только тогда у вас будет работать вся магия ларавел по умолчанию, без дополнительных описаний. Например, не нужно будет указывать таблицу в модели (protected $table = 'categories';)

-------

Например, Пользователь и Пост. У каждого пользователя может быть множество постов, но каждый пост принадлежит единственному пользователю. Тогда мы можем описать эту связь так (связь будет один-ко-многим)

class User {
  public function posts(): HasMany {
    return $this->hasMany(Post::class); // юзер->имеетМного(Постов)
  }
}
class Post {
  public function user(): BelongsTo {
    return $this->belongsTo(User::class); // пост->относитсяК(Юзеру)
  }
}

// Получение данных

foreach ($user->posts as $post) {
   // Все посты пользователя
}

$post->user->name; // Имя пользователя, которому принадлежит этот пост.

// Добавление постов

$user->posts()->create([ 
  'title' => 'Title of post',
  'content' => 'Long content',
  // id юзера в такой записи указывать не нужно, он будет проставлен автоматически.
]);


---------

Теперь к вашему случаю. Тут нужно понять могут ли ваши посты одновременно находиться в нескольких категориях. Если нет, то вам нужна связь один-ко-многим, как в примере выше.
Если да, то вы на верном пути, вам нужна связь многие-ко-многим, через связующую таблицу.
Дальнейший код в примерах написан с учетом приведенных выше замечаний по именованию.

class Post extends Model
{
    public function categories(): BelongsToMany
    {
      return $this->belongsToMany(Category::class); // пост->относитсяКоМногим(Категориям)
    }
}

class Category extends Model
{
    public function posts(): BelongsToMany
    {
      return $this->belongsToMany(Post::class); // категория->относитсяКоМногим(Постам)
    }
}


Это всё, что нужно для связи.

Получить все посты из категории

foreach ($category->posts as $post) {

}


C сортировкой

$posts = $category->posts()->orderBy('created_at')->get();


Для создания есть те же методы create(), save().
Кроме того, есть возможность присоединить уже существующую модель.

$post = Post::create([...]); // Создали пост, он никому не принадлежит
$category->attach($post->id); // Теперь он связан с категорией


Есть метод sync() для синхронизации пачки моделей.

Всё это очень подробно написано в официальной документации.
Я по сути просто сделал небольшую выжимку оттуда.
https://laravel.com/docs/10.x/eloquent-relationships
Ответ написан
alexey-m-ukolov
@alexey-m-ukolov Куратор тега Laravel
В документации есть ответы (с примерами) на все ваши базовые вопросы:
Querying Relations
Inserting & Updating Related Models
Ответ написан
Комментировать
solotony
@solotony
покоряю пик Балмера
судя по всему вам надо использовать связь многие ко многим belongsToMany

https://laravel.com/docs/10.x/eloquent-relationshi...

ну и общие ошибки:
названия моделей в единственном числе
названия методов c маленькой буквы
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы