与另一模型有关系的Laravel多态多对多关系透视表 [英] Laravel Polymorphic Many-to-Many relationship pivot table with relationship to another Model

查看:30
本文介绍了与另一模型有关系的Laravel多态多对多关系透视表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有如下图所示的表结构:

简单地说,它由几个多对多的多态关系组成,如下所述:

  • resources多个resources可以有多个sources,数据透视表sourceables包含catalog_numberlot_number信息,以使数据透视表中的每一行都是唯一的。许多资源也可以来自相同的来源或不同的来源,通过数据透视表上的目录号和批号进行区分。

  • 多个resources也可以附加多个publications,通过透视表上notespublicationables

  • 还可以在许多出版物中描述资源的来源。

我的问题:

  1. 由于资源来源按透视表sourceables区分,sourceables的透视行关系如何保存到publications
  2. 您是否可以在sourceables和‘Publationables’之间有一个自定义中间表模型以链接到publications
  3. 如何检索包含其所有发布的资源以及包含所有对应发布的源?

推荐答案

这是我的答案,我希望我能给您的问题带来一些启发。我已经发布了一个GitHub repository,其中包含我在这里编写的所有代码的示例。我添加了有关如何在那里复制我的方案的更多信息。

数据库和关系

以下是我对数据库及其关系的解释。您可以检查存储库上的所有迁移。

解决方案

问题1:

如何将来源的透视表行之间的关系保存到发布?

答案:

在继续代码示例之前,我想解释一些需要理解的重要概念。我将使用表达式标记来引用用于关联模型的标识符索引。 它的工作方式是将标签分配给您想要添加到关系中的任何模型。使用这些标签的任何模型都可以存储在变形透视表中。Laravel使用_";Modelable&Quot;type列过滤调用存储模型名称的关系。您可以使用关系对模型进行标记(&Q;;&Q;),将方法创建到模型中,以返回MorToMany关系函数。

对于此特定案例,以下是如何继续操作: 在资源模型中,您有两个方法,一个与Sourceable索引相关,另一个与Publationable标记相关,返回时使用MorToMany。 以下是资源模型(./app/model/resource ce.php)的外观:

<?php
namespace AppModels;

use IlluminateDatabaseEloquentFactoriesHasFactory;
use IlluminateDatabaseEloquentModel;

class Resource extends Model
{
    use HasFactory;
    protected $guarded = [];

    public function publications()
    {
        return $this->morphToMany(Publication::class, 'publicationable')->withPivot('notes');
    }

    public function sources()
    {
        return $this->morphToMany(Source::class, 'sourceable')->withPivot(['catalog_number', 'lot_number']);
    }
}

在您的发布模型中,您有两个方法,一个与Sourceable索引相关,另一个与反向关系相关,其中Resource方法与可发布标记的反向关系使用MoredByMany。 下面是发布模型(./app/Models/Publication.php)的外观:

<?php

namespace AppModels;

use IlluminateDatabaseEloquentFactoriesHasFactory;
use IlluminateDatabaseEloquentModel;

class Publication extends Model
{
    use HasFactory;
    protected $guarded = [];

    public function sources()
    {
        return $this->morphToMany(Source::class, 'sourceable')->withPivot(['catalog_number', 'lot_number']);
    }

    public function resources()
    {
        return $this->morphedByMany(Resource::class, 'publicationable');
    }
}
With this, you can be able to accomplish your goal of relating Publications with Resources and Sources.

问题2:是否可以在可源可发布之间设置中间表以链接到出版物?

答案:

不,您不需要这样做。您可以使用Sourceables表来完成此操作。通过创建向Source模型返回MorToMany关系的方法,您始终可以将Source与任何模型相关联。这些是我们对问题1上的出版物所做的操作。

问题3:如何检索包含所有发布的资源以及包含所有对应发布的源?

答案:

我认为雄辩,这是我在整个Laravel框架上最喜欢的特性。这是蛋糕上的樱桃,加上我们在模型定义上所做的一切。

如果您再次检查资源和发布模型定义,我们将添加一个with Pivot()方法,其中包含我们希望在对eloquent的关系进行的任何调用中包含的相关字段。此方法使从透视表中读取自定义值成为可能。

重要提示:对于此示例,我隐式添加透视表值,因为我没有在迁移中将这些列声明为NULL。

若要将发布与使用关系的资源相关联(存储在透视表上),您只需:

(使用Artisan Tinker)
Psy Shell v0.10.8 (PHP 8.0.6 — CLI) by Justin Hileman
>>> $publication = AppModelsPublication::find(5)
>>> $resource = AppModelsResource::find(19)
>>> $resource->publications()->attach($publication, ["notes" => "Eureka!"]);
### Adding another Publication
>>> $publication = AppModelsPublication::find(10)
>>> $resource->publications()->attach($publication, ["notes" => "Eureka 2!"]);
(使用控制器)
use AppModelsResource;
use AppModelsPublication;
...
$id_resource = 1; // This is the Resource Id you want to reach.
$id_publication = 10; // This is the Resource Id you want to reach.

$resource = Resource::find($id_resource);
$publication = Publication::find($id_publication);
$pivotData = [ "notes" => "Eureka!" ];

$resource->publications()->attach($publication, $pivotData);

要从资源检索所有发布,您只需:

(使用Artisan Tinker)
Psy Shell v0.10.8 (PHP 8.0.6 — CLI) by Justin Hileman
>>> $resource = AppModelsPublication::find(5)
>>> $resource->publications()->get();

容易吧?:)雄辩的力量!

(使用控制器)
use AppModelsResource;
...
$id_resource = 1; // This is the Resource Id you want to reach.
$resource = Resource::find($id_resource);

$resource->publications()->get();

以防万一,您可以通过以下方式从所有模型中存储和检索:

(使用控制器)
use AppModelsPublication;
use AppModelsResource;
use AppModelsSource;
...
... Method ...
$id_publication = 1;
$id_resource = 1;
$id_source = 1;

$publication = Publication::find($id_resource);
$resource = Resource::find($id_resource);
$source = Source::find($id_resource);

$publicationPivotColumns = [
    "notes" => "This is a note...",
];

$sourcePivotColumns = [
    "catalog_number" => 100,
    "lot_number" => 4903,
];

// Storing Data
// Attach (Store in the publicationables table) a Publication to a Resource
$resource->publications()->attach($publication, $publicationPivotColumns);

// Attach (Store in the sourceables table) a Source to a Resource
$resource->sources()->attach($source, $sourcePivotColumns);

// Attach (Store in the sourceables table) a Source to a Publication
$publication->sources()->attach($source, $sourcePivotColumns);

// Retraiving Data
// Get all Sources from a Resource
$resource->sources()->get();

// Get all Publications from a Resource
$resource->publications()->get();

// Get all Sources from a Publication
$publication->sources()->get();

这篇关于与另一模型有关系的Laravel多态多对多关系透视表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆