Laravel 与另一个模型有关系的多态多对多关系枢轴 table
Laravel Polymorphic Many-to-Many relationship pivot table with relationship to another Model
我有如下 table 结构,如图所示:
简而言之,它由几个多对多的多态关系组成,如下所述:
many resources
可以有很多 sources
并且 pivot table sourceables
包含 catalog_number
和 lot_number
信息使数据透视表 table 中的每一行都是唯一的。许多资源也可能来自相同来源或不同来源,通过枢轴上的目录号和批号区分 table。
许多 resources
也可以有许多 publications
附加到它,通过 publicationables
table 和 notes
在枢轴上table
许多出版物也可以描述资源的来源。
我的问题:
- 由于资源的来源是由枢轴table
sourceables
区分的,我应该如何保存sourceables
到publications
的枢轴行之间的关系?
- 你能在
sourceables
和 'publicationables' 到 link 到 publications
之间有一个自定义的中间 table 模型吗?
- 如何检索资源及其所有出版物以及所有相应出版物的来源?
这是我的回答,希望能对您的问题有所帮助。我已经发布了一个 GitHub repository,其中包含我在此处编写的所有代码的示例。我在此处添加了有关如何复制我的场景的更多信息。
数据库和关系
这是我对数据库及其关系的解释。您可以检查存储库中的所有迁移。
解决方案
问题 1:
我应该如何保存sourceable的pivot rows到publications之间的关系?
答案:
在继续代码示例之前,我想解释一些重要的概念以供理解。我将使用表达式 tag 来引用 identifier 或 index Morph Relations used to相关模型。
它的工作方式是将标签分配给要添加到关系中的任何模型。任何使用这些标签的模型都可以存储在 Morph Pivot Table 中。 Laravel 使用 _"modelable"type 列来过滤对存储模型名称的关系的调用。您可以使用关系“标记”您的模型,在模型中创建一个方法,该方法 return 是 morphToMany 关系函数。
对于这个具体案例,以下是如何进行:
在您的资源模型中,您有两种方法,一种与 sourceable 索引相关,另一种与 publicationable 标签相关,使用 morphToMany return。
这是资源模型 (./app/Models/Resource.php):
的样子
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
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 索引相关,另一种与 inverse relation 相关publicationable 标签的资源方法使用 morphedByMany in return。
发布模型 (./app/Models/Publication.php):
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
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:你能否在 sourceable 和 publicationable 到 link 之间有一个中间 table出版物?
答案:
不,你不需要。您可以使用 sourceables table 来完成此操作。您始终可以通过创建 returns 与源模型的 morphToMany 关系的方法将源与任何模型相关联。这些是我们在 问题 1.
上对出版物所做的工作
问题 3:如何检索资源及其所有出版物以及所有相应出版物的来源?
答案:
我认为 Eloquent 这是整个 Laravel 框架中我最喜欢的功能。这是蛋糕上的樱桃,我们在模型定义上所做的一切。
如果您再次检查资源和发布模型定义,我们会添加一个 withPivot() 方法,其中包含我们希望包含在我们对关系所做的任何调用中的相关字段eloquent。此方法可以从 Pivot table.
读取自定义值
重要提示:对于此示例,我隐式添加了枢轴值,因为我没有在迁移中将这些列声明为 NULL。
要使用关系将出版物与资源相关联(存储在数据透视表 table),您只需:
(使用artisan修补程序)
Psy Shell v0.10.8 (PHP 8.0.6 — CLI) by Justin Hileman
>>> $publication = \App\Models\Publication::find(5)
>>> $resource = \App\Models\Resource::find(19)
>>> $resource->publications()->attach($publication, ["notes" => "Eureka!"]);
### Adding another Publication
>>> $publication = \App\Models\Publication::find(10)
>>> $resource->publications()->attach($publication, ["notes" => "Eureka 2!"]);
(使用控制器)
use App\Models\Resource;
use App\Models\Publication;
...
$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修补程序)
Psy Shell v0.10.8 (PHP 8.0.6 — CLI) by Justin Hileman
>>> $resource = \App\Models\Publication::find(5)
>>> $resource->publications()->get();
简单吧? :) Eloquent 力量!
(使用控制器)
use App\Models\Resource;
...
$id_resource = 1; // This is the Resource Id you want to reach.
$resource = Resource::find($id_resource);
$resource->publications()->get();
如有任何疑问,这是您可以从所有模型中存储和检索的方式:
(使用控制器)
use App\Models\Publication;
use App\Models\Resource;
use App\Models\Source;
...
... 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();
我有如下 table 结构,如图所示:
简而言之,它由几个多对多的多态关系组成,如下所述:
many
resources
可以有很多sources
并且 pivot tablesourceables
包含catalog_number
和lot_number
信息使数据透视表 table 中的每一行都是唯一的。许多资源也可能来自相同来源或不同来源,通过枢轴上的目录号和批号区分 table。许多
resources
也可以有许多publications
附加到它,通过publicationables
table 和notes
在枢轴上table许多出版物也可以描述资源的来源。
我的问题:
- 由于资源的来源是由枢轴table
sourceables
区分的,我应该如何保存sourceables
到publications
的枢轴行之间的关系? - 你能在
sourceables
和 'publicationables' 到 link 到publications
之间有一个自定义的中间 table 模型吗? - 如何检索资源及其所有出版物以及所有相应出版物的来源?
这是我的回答,希望能对您的问题有所帮助。我已经发布了一个 GitHub repository,其中包含我在此处编写的所有代码的示例。我在此处添加了有关如何复制我的场景的更多信息。
数据库和关系
这是我对数据库及其关系的解释。您可以检查存储库中的所有迁移。
解决方案
问题 1:
我应该如何保存sourceable的pivot rows到publications之间的关系?
答案:
在继续代码示例之前,我想解释一些重要的概念以供理解。我将使用表达式 tag 来引用 identifier 或 index Morph Relations used to相关模型。 它的工作方式是将标签分配给要添加到关系中的任何模型。任何使用这些标签的模型都可以存储在 Morph Pivot Table 中。 Laravel 使用 _"modelable"type 列来过滤对存储模型名称的关系的调用。您可以使用关系“标记”您的模型,在模型中创建一个方法,该方法 return 是 morphToMany 关系函数。
对于这个具体案例,以下是如何进行: 在您的资源模型中,您有两种方法,一种与 sourceable 索引相关,另一种与 publicationable 标签相关,使用 morphToMany return。 这是资源模型 (./app/Models/Resource.php):
的样子<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
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 索引相关,另一种与 inverse relation 相关publicationable 标签的资源方法使用 morphedByMany in return。 发布模型 (./app/Models/Publication.php):
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
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:你能否在 sourceable 和 publicationable 到 link 之间有一个中间 table出版物?
答案:
不,你不需要。您可以使用 sourceables table 来完成此操作。您始终可以通过创建 returns 与源模型的 morphToMany 关系的方法将源与任何模型相关联。这些是我们在 问题 1.
上对出版物所做的工作问题 3:如何检索资源及其所有出版物以及所有相应出版物的来源?
答案:
我认为 Eloquent 这是整个 Laravel 框架中我最喜欢的功能。这是蛋糕上的樱桃,我们在模型定义上所做的一切。
如果您再次检查资源和发布模型定义,我们会添加一个 withPivot() 方法,其中包含我们希望包含在我们对关系所做的任何调用中的相关字段eloquent。此方法可以从 Pivot table.
读取自定义值重要提示:对于此示例,我隐式添加了枢轴值,因为我没有在迁移中将这些列声明为 NULL。
要使用关系将出版物与资源相关联(存储在数据透视表 table),您只需:
(使用artisan修补程序)
Psy Shell v0.10.8 (PHP 8.0.6 — CLI) by Justin Hileman
>>> $publication = \App\Models\Publication::find(5)
>>> $resource = \App\Models\Resource::find(19)
>>> $resource->publications()->attach($publication, ["notes" => "Eureka!"]);
### Adding another Publication
>>> $publication = \App\Models\Publication::find(10)
>>> $resource->publications()->attach($publication, ["notes" => "Eureka 2!"]);
(使用控制器)
use App\Models\Resource;
use App\Models\Publication;
...
$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修补程序)
Psy Shell v0.10.8 (PHP 8.0.6 — CLI) by Justin Hileman
>>> $resource = \App\Models\Publication::find(5)
>>> $resource->publications()->get();
简单吧? :) Eloquent 力量!
(使用控制器)
use App\Models\Resource;
...
$id_resource = 1; // This is the Resource Id you want to reach.
$resource = Resource::find($id_resource);
$resource->publications()->get();
如有任何疑问,这是您可以从所有模型中存储和检索的方式:
(使用控制器)
use App\Models\Publication;
use App\Models\Resource;
use App\Models\Source;
...
... 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();