Отношения Laravel с использованием одной таблицы файлов для разных моделей - PullRequest
0 голосов
/ 08 ноября 2018

Я создал таблицу files для хранения метаданных файлов и локального пути, где найти этот файл.

Я хочу использовать эту таблицу для нескольких моделей.

Например, users может сохранить изображение профиля в этой таблице. Но у companies их логотип может храниться в этой таблице. Так что на самом деле все мои модели, которые могут хранить файл, имеют отношение к этой таблице.

Итак, в users и companies я создал столбец file_id, который ссылается на id в таблице files. Поскольку таблица files может хранить файлы для нескольких моделей, я не храню user_id или company_id в таблице `files.

Теперь вопрос в том, как я могу добавить это отношение в таблицу users и companies? Потому что, насколько я вижу, для таблицы files требуется идентификатор users или companies.

Чего мне не хватает?

Ответы [ 2 ]

0 голосов
/ 08 ноября 2018

Вы идете в правильном направлении.

Вы можете иметь users и companies внешний ключ в вашей таблице files.

Посмотрите в Laravel 5 Полиморфные отношения.

https://laravel.com/docs/5.7/eloquent-relationships#polymorphic-relations

Вы можете иметь внешний ключ fileable_id и тип внешнего ключа fileable_type

если вы добавите файл для companies record

Пусть, скажем, идентификатор вашей компании равен 24, а используемая модель - App\Models\Company

Добавить следующее к вашей файловой модели App\File

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

И следуя вашим App\User и App\Company

 public function files()
{
    return $this->morphMany('App\Comment', 'fileable'); // use morphOne if you want One to One relation
}

Для создания файла для Company .

$company = Company::find(24);
$company->files()->create([
   'path' => '/folder/myfile.txt',
   'size' => '14585',
   'extension' => 'txt',
]);

На этом этапе вы можете получить MassAssignmentException

внутри вашей App\File модели

добавить $fillable = ['path', 'size' , 'extension'];

Ваша запись будет выглядеть так:

id   path                size   extension     fileable_id    fileable_type

1  /folder/myfile.txt   14585   txt           24              App\Models\Company

Laravel автоматически сохраняет значения fileable_id и fileable_type, судя по объекту, вызывающему метод отношений. Вам не нужно ставить их вручную

Подсказка: всегда просматривайте официальные документы

0 голосов
/ 08 ноября 2018

Это похоже на Полиморфное Отношение . из документации:

Полиморфные отношения

Структура таблицы

Полиморфные отношения позволяют модели принадлежать более чем одной другой модели в одной ассоциации. Например, представьте, что пользователи вашего приложения могут «комментировать» как сообщения, так и видео. Используя полиморфные отношения, вы можете использовать один comments таблица для обоих этих сценариев. Сначала давайте рассмотрим таблицу структура, необходимая для построения этих отношений:

posts
    id - integer
    title - string
    body - text

videos
    id - integer
    title - string
    url - string

comments
    id - integer
    body - text
    commentable_id - integer
    commentable_type - string

Следует отметить два важных столбца: commentable_id и commentable_type столбцы в таблице comments. commentable_id столбец будет содержать значение идентификатора сообщения или видео, а commentable_type столбец будет содержать имя класса владельца модель. Столбец commentable_type показывает, как ORM определяет, какие «тип» модели-владельца, возвращаемой при доступе к commentable отношение.

Структура модели

Далее, давайте рассмотрим определения модели, необходимые для построения этого отношения:

use Illuminate\Database\Eloquent\Model;

class Comment extends Model
{
    /**
     * Get all of the owning commentable models.
     */
    public function commentable()
    {
        return $this->morphTo();
    }
}

class Post extends Model
{
    /**
     * Get all of the post's comments.
     */
    public function comments()
    {
        return $this->morphMany('App\Comment', 'commentable');
    }
}

class Video extends Model
{
    /**
     * Get all of the video's comments.
     */
    public function comments()
    {
        return $this->morphMany('App\Comment', 'commentable');
    }
}

Итак, в вашем случае структура вашей файловой таблицы может выглядеть следующим образом:

files
    id - integer
    url - string
    fileable_id - integer // <--- the id of the object
    fileable_type - string // <-- the type of the object (user, company, etc)

Тогда в ваших моделях:

file.php

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class File extends Model
{
    /**
     * Get all of the owning fileable models.
     */
    public function fileable()
    {
        return $this->morphTo();
    }
}

User.php

class User extends Model
{
    /**
     * Get all of the user's files.
     */
    public function files()
    {
        return $this->morphMany(File::class, 'fileable');
        // or
        // return $this->morphOne(File::class, 'fileable'); equivalent to hasOne
    }
}

Company.php

class Company extends Model
{
    /**
     * Get all of the company's files.
     */
    public function files()
    {
        return $this->morphMany(File::class, 'fileable');
        // or
        // return $this->morphOne(File::class, 'fileable'); equivalent to hasOne
    }
}
...