Я моделирую отчет, который в зависимости от его типа (пропавший без вести, разыскиваемый и т. Д.) Может содержать разные поля, но каждый тип имеет несколько полей. Я думаю, это то, что отличает этот вопрос от того, чтобы сказать: этот вопрос < / a>, где поля являются общими для всех типов.

На данный момент я создал модель отчета с целочисленным полем, указывающим его тип, который ссылается на таблицу типов. Преимущество состоит в том, что эту модель легко понять и реализовать. Это означает, что я могу легко искать предметы. С другой стороны, это означает, что некоторые поля не имеют смысла для некоторых моделей и, следовательно, всегда имеют значение NULL. Когда я добавляю поля, уникальные для отдельных типов, я получаю много столбцов в таблице, многие из которых имеют значение NULL.

Я хотел бы получить совет по использованию полиморфных отношений Laravel (5.2). Я предполагаю, что у меня будет базовая модель отчета, содержащая все общие поля и поля MorphTo; затем разделите разные типы, содержащие их уникальные поля во взаимно однозначной связи с моделью отчетов. Возможно ли это и имеет ли это вообще смысл? Я вижу проблемы в том, что я теряю возможность поиска по всем «отчетам» независимо от типа. Или есть способ обойти это, например, Java, где наследование позволяет подклассам считаться членами суперкласса?

Примерная схема таких отношений представлена ​​ниже. В отчетах содержатся общие поля, а в «Разыскиваемых» и «Пропавших без вести» - уникальные поля.

Relationship between wanted and missing reports, and the base report

0
Chris Njuguna 21 Дек 2016 в 21:38

1 ответ

Лучший ответ

Из диаграммы, представляющей отношения в вашем вопросе выше, я думаю, что это прямой случай родитель-потомок.

Здесь ваш BaseReport или Report - это, так сказать, родительская модель, а WantedReport и MissingReport - так сказать дочерняя модель.

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

Table-reports
id    // primary key
date
description

Table - wanted_reports
id    //primary key
report_id    //foreign key linking to the reports table
status_at
is_captured   //maybe a boolean field
charge

Table - missing_reports
id    //primary key
report_id       //foreign key linking to the reports table 
status_at
is_found
last_seen_date
last_seen_at  

Вы можете определить соответствующие модели как - Отчет

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Report extends Model
{
    protected $table = 'reports';

    protected $fillable = ['report_date', 'description'];

    public function wanted_reports()
    {
        return $this->hasMany(WantedReport::class);
    }

    public function missing_reports()
    {
         return $this->hasMany(MissingReport::class);
    }
}  

WantedReport

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class WantedReport extends Model
{

    protected $table = 'wanted_reports';

    protected $fillable = ['report_id', 'status_at', 'is_captured', 'charge'];


    public function report()
    {
        return $this->belongsTo(Report::class);
    }
}  

MissingReport

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class MissingReport extends Model
{

    protected $table = 'missing_reports';

    protected $fillable = ['report_id', 'status_at', 'is_found', 'last_seen_date', 'last_seen_at];


    public function report()
    {
        return $this->belongsTo(Report::class);
    }
}  

Затем в любом месте вашего приложения вы можете получить доступ к отношениям, как обычно, например

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class ReportsController
{

    public function store(Request $$request)
    {
        $report = $this->model->create([
            'report_date' => Carbon:::now(),
            'description' => $request->get('description')
        ]);

        if($report)
        {
            $wantedReport = $report->wanted_reports()->create([
                'status_at' => $request->get('status'),
                ...
            ]);

            $missingReport = $report->missing_reports()->create([
                'status_at' => $request->get('status'),
                ...
            ]); 
        }  

    }
}  

Надеюсь это поможет

1
Donkarnash 22 Дек 2016 в 07:59
Спасибо @Donkamash. Это имеет большой смысл и довольно лаконично. Однако каждый отчет «Требуемый_отчет» и «Отсутствующий_репорт» относится только к одному отчету, поэтому я не уверен, что это правильно? public function missing_reports() { return $this->hasMany(MissingReport::class); } Кроме того, я все еще пытаюсь понять, почему не полиморфные отношения. Насколько я могу судить, полиморфизм устраняет необходимость явно поддерживать внешний ключ. Я все еще схожу с ума по этим концепциям, так что терпите меня
 – 
Chris Njuguna
22 Дек 2016 в 18:09
Если это отношение «один к одному», вы можете определить свое отношение соответствующим образом public function missing_reports() { return $this->hasOne(MissingReport::class); }. В вашем случае не требуется полиморфное отношение, а также помните, что полиморфное отношение требует дополнительного поиска в таблице при запросе (влияние на производительность), поэтому не используйте, если не требуется, - я бы посоветовал. Но опять же, это зависит от ваших предпочтений.
 – 
Donkarnash
22 Дек 2016 в 18:58
Спасибо. Позвольте мне реализовать это. Я склонен принять ваш ответ, но сначала позвольте мне подтвердить, что на практике он работает так, как я хочу.
 – 
Chris Njuguna
22 Дек 2016 в 22:12