在我的网络应用程序中,用户可以将文档或电子邮件上传到 channel 。
channel 还可以有 document_tags 和 email_tags,所有 上传的文档/电子邮件应该自动继承。
此外,document_tags 和email_tags将有不同的描述:tag_descriptions。因此,例如,如果我们有一个文档,上传到具有标签的 channel :animals (id = 1) 和 pets (id = 2)
Document #55 已上传至 Channel #8。Document #55 将自动继承具有 document_tags.channel_id = 55 的标签(这可以通过以下关系访问:$channel->文档标签)。在本例中是动物和宠物。 tag_descriptions 中为 animals 和 pets 设置唯一的描述,例如:tag_descriptions
id | taggable_type | taggable_id | typeable_type | typeable_id | description
1 | App\DocumentTag | 1 | App\Document | 55 | My unique description for animals.
2 | App\DocumentTag | 2 | App\Document | 55 | My unique description for pets.
现在在上面的数据库设计中,上传的文件#55,有标签:animals和pets相关联,但是这两个标签还有独特的描述,对于特定的文档是独一无二的。
如果我上传另一个文档或电子邮件(比如 email #20),那么我想它会是这样的:
tag_descriptions:
id | taggable_type | taggable_id | typeable_type | typeable_id | description
1 | App\DocumentTag | 1 | App\Document | 55 | My unique description for animals.
2 | App\DocumentTag | 2 | App\Document | 55 | My unique description for pets.
3 | App\EmailTag | 1 | App\Email | 20 | Another unique description for animals.
4 | App\EmailTag | 2 | App\Email | 20 | Yet another unique description for pets.
现在 email #20 也有标签 animals 和 pets,但在这种情况下,用户可以为标签。
现在我的问题是:
以上设计是否可行,是否被认为是 Laravel/PHP 中的最佳实践?我有点不确定如何构建代码,因为 TagDescription 模型会突然有两个多态关系(taggable 和typeable),我在文档中找不到任何支持它的内容。
此外,我不确定是否可以使用上述设计通过特定的上传文档访问唯一描述,例如:
//In my Document.php model:
public function tagdescriptions()
{
return $this->morphMany(TagDescription::class, 'typeable');
}
然后像这样使用它:$document->tagdescriptions。
最后但同样重要的是 - 我有点不确定如何为特定的 taggable_id/taggable_type 和独特的电子邮件/文档保存独特的标签描述。 (typeable_id 和 typeable_type)。
最佳答案
我不确定您到底想做什么,但是具有两个多态关系的表没有意义。启用多态关系的表是数据透视表。虽然我知道您想要每个标签和关系类型的唯一描述,但数据透视表应该只有两个外键列,一个表与和相关。
还有一种方法,就是利用多态关系作为对数据透视表的约束。首先,多态关系中的数据透视表应该重命名为“taggables”。您不需要“email_tag”表和“document_tag”表,您可以使用名为“tags”的表。要获得每个标签的唯一描述,您可以将描述添加到表“tabblables”。
迁移文件看起来像这样......
public function up()
{
Schema::create('taggables', function (Blueprint $table) {
$table->increments('id');
$table->unsignedInteger('tag_id');
$table->unsignedInteger('taggable_id');
$table->string('taggable_type');
$table->string('description');
$table->timestamps();
});
Schema::create('tags', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
Schema::create('documents', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
Schema::create('emails', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
}
这里是您需要在电子邮件和文档模型中执行的操作。
class Email extends Model
{
/**
* Get all of the tags.
*/
public function tags()
{
return $this->morphToMany(Tag::class, 'taggable')->withPivot('description');
}
}
class Document extends Model
{
/**
* Get all of the tag descriptions.
*/
public function tags()
{
return $this->morphToMany(Tag::class, 'taggable')->withPivot('description');
}
}
“withPivot”函数将返回查询中指定列的值。
这是您需要在标签模型中执行的操作。
class Tag extends Model
{
/**
* Get all of the tag descriptions.
*/
public function documents()
{
return $this->morphByMany(Document::class, 'taggable');
}
/**
* Get all of the tag descriptions.
*/
public function emails()
{
return $this->morphByMany(Email::class, 'taggable');
}
}
您不需要“可标记”表模型。
事情是这样的。当你修补......
$email = App\Email::find(1)->tags;
此查询将运行...
select `tags`.*,
`taggables`.`taggable_id` as `pivot_taggable_id`,
`taggables`.`tag_id` as `pivot_tag_id`,
`taggables`.`taggable_type` as `pivot_taggable_type`,
`taggables`.`description` as `pivot_description`
from `tags`
inner join `taggables` on `tags`.`id` = `taggables`.`tag_id`
where `taggables`.`taggable_id` = 1
and `taggables`.`taggable_type` = 'App\Email'
你看到的是多态关系的约束可以查询唯一描述。总之,您不能在一个数据透视表中放置两个以上的外键关系,但您可以将约束添加到您的数据透视表。
我认为将这个添加到您的 AppServiceProvider.php 文件中看起来更干净...
public function boot()
{
Relation::morphMap([
'email' => Email::class,
'document' => Document::class
]);
}
https://laravel.com/docs/5.8/eloquent-relationships#polymorphic-relationships
这将使您能够将“电子邮件”或“文档”的值存储为您的可标记类型。
对于发布到表格,我认为这看起来最干净...
$tag = Tag::firstOrNew(["name"=>"#tag"]);
$tag->name = "#tag";
$document = new Document();
$document->name = "new doc";
$document->save();
$document->tags()->save($tag,["description"=>"some description"]);
当然可以使用 attach()。 Save() 使用 attach() 如下所示... https://github.com/laravel/framework/blob/5.8/src/Illuminate/Database/Eloquent/Relations/BelongsToMany.php#L871
希望这对您有所帮助。
关于php - Laravel/PHP - 高级多态关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55816088/
我的问题的一个例子是体育游戏。一场体育比赛有两支球队,一支主队和一支客队。我的事件记录模型如下:classTeam"Team"has_one:away_team,:class_name=>"Team"end我希望能够通过游戏访问一个团队,例如:Game.find(1).home_team但我收到一个单元化常量错误:Game::team。谁能告诉我我做错了什么?谢谢, 最佳答案 如果Gamehas_one:team那么Rails假设您的teams表有一个game_id列。不过,您想要的是games表有一个team_id列,在这种情况下
📢博客主页:https://blog.csdn.net/weixin_43197380📢欢迎点赞👍收藏⭐留言📝如有错误敬请指正!📢本文由Loewen丶原创,首发于CSDN,转载注明出处🙉📢现在的付出,都会是一种沉淀,只为让你成为更好的人✨文章预览:一.分辨率(Resolution)1、工业相机的分辨率是如何定义的?2、工业相机的分辨率是如何选择的?二.精度(Accuracy)1、像素精度(PixelAccuracy)2、定位精度和重复定位精度(RepeatPrecision)三.公差(Tolerance)四.课后作业(Post-ClassExercises)视觉行业的初学者,甚至是做了1~2年
我使用的是遗留数据库,所以我无法控制数据模型。他们使用了很多多态链接/连接表,就像这样createtableperson(per_ident,name,...)createtableperson_links(per_ident,obj_name,obj_r_ident)createtablereport(rep_ident,name,...)其中obj_name是表名,obj_r_ident是标识符。因此链接的报告将按如下方式插入:insertintoperson(1,...)insertintoreport(1,...)insertintoreport(2,...)insertint
我想合并多个事件记录关系例如,apple_companies=Company.where("namelike?","%apple%")banana_companies=Company.where("namelike?","%banana%")我想结合这两个关系。不是合并,合并是apple_companies.merge(banana_companies)=>Company.where("namelike?andnamelike?","%apple%","%banana%")我要Company.where("名字像?还是名字像?","%apple%","%banana%")之后,我会写代
我有一个简单的问题,与关联有关。我有一个书的模型,它有_onereservation。预订属于_书本。我想在预订Controller的创建方法中确保在预订时没有预订一本书。换句话说,我需要检查该书是否存在任何其他预订。我该怎么做?编辑:Aaa我做到了,感谢大家的提示,学到了一些新东西。当我尝试提供的解决方案时,出现no_method错误或nil_class等。这让我开始思考,我尝试处理的对象根本不存在。Krule给了我使用book.find的想法,所以我尝试使用它。最终我得到了它的工作:book=Book.find_by_id(reservation_params[:book_id])
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭9年前。我来自C、php和bash背景,很容易学习,因为它们都有相同的C结构,我可以将其与我已经知道的联系起来。然后2年前我学了Python并且学得很好,Python对我来说比Ruby更容易学。然后从去年开始,我一直在尝试学习Ruby,然后是Rails,我承认,直到现在我还是学不会,讽刺的是那些打着简单易学的烙印,但是对于我这样一个老练的程序员来说,我只是无法将它
我目前还在上学,正在上一门关于用C++实现数据结构的类(class)。在业余时间,我喜欢使用“高级”语言(主要是Ruby和一些c#)进行编程。既然这些高级语言为你管理内存,你会用数据结构做什么?我可以理解对队列和堆栈的需求,但是您需要在Ruby中使用二叉树吗?还是2-3-4树?为什么?谢谢。 最佳答案 Sosincethesehigherlevellanguagesmanagethememoryforyou,whatwouldyouusedatastructuresfor?使用数据结构的主要原因与垃圾收集无关。但它是以某种方式有效的
我有一组名为Tasks和Posts的资源,它们之间存在has_and_belongs_to_many(HABTM)关系。还有一个连接它们的值的连接表。create_table'posts_tasks',:id=>falsedo|t|t.column:post_id,:integert.column:task_id,:integerend所以我的问题是如何检查特定任务的ID是否存在于从@post.tasks创建的数组中?irb(main):011:0>@post=Post.find(1)=>#@post.tasks=>[#,#]所以我的问题是,@post.tasks中是否存在"@task
根据我目前的理解,如果我必须描述Rails应用程序的各个组件如何协同工作以响应请求,我会说以下内容:1)路由确定哪些请求URL映射到哪些Controller方法。2)Controller方法从模型中获取信息并将该信息(以全局变量的形式)传递给相应的View模板。3)View模板使用存储在全局变量中的数据来构造最终响应。在上面的解释中,几个组件之间的关系是明确的,不可否认的;即:1)路由和Controller方法2)Controller方法和View模板其实上面的关系是一对一的。但是,模型类与其相邻组件类型(即Controller)的关系并不明确。是的,Controller从模型中检索信
有这个:classEventtrueenduser=User.create!我可以:Event.create!(:historizable=>user)但我不能:Event.where(:historizable=>user)#Mysql2::Error:Unknowncolumn'events.historizable'in'whereclause'我必须改为这样做:Event.where(:historizable_id=>user.id,:historizable_type=>user.class.name)更新重现问题的代码:https://gist.github.com/fg