主页/PHP笔记/PHP问答/框架Laravel/Eloquent中的多态关联:通过示例解释

Eloquent中的多态关联:通过示例解释

Bug编译狮

Bug编译狮

Eloquent是Laravel框架中的一个强大工具,它允许你在数据库表之间建立复杂的关联关系。其中,多态关联是一种特别的关联类型,可以处理多种不同类型的模型。

多态关联的基本概念

  • 多态性:指同一个属性可以应用于不同的类。
  • 关联:表示两个实体之间的关系。
  • 多态关联:当一个实体可以通过同一个属性与多个不同的实体进行关联时,这种关联称为多态关联。

示例:用户和角色的关系

假设我们有一个User模型和一个Role模型。每个用户可以有多个角色,而每个角色也可以属于多个用户。我们可以使用多态关联来实现这一复杂的关系。

1. 定义模型

首先,定义UserRole模型:

namespace AppModels;

use IlluminateDatabaseEloquentModel;
use IlluminateDatabaseEloquentRelationsHasMany;

class User extends Model
{
    public function roles()
    {
        return $this->hasMany(Role::class);
    }
}

namespace AppModels;

use IlluminateDatabaseEloquentModel;
use IlluminateDatabaseEloquentRelationsBelongsToMany;

class Role extends Model
{
    public function users()
    {
        return $this->belongsToMany(User::class);
    }
}

2. 创建数据

接下来,创建一些示例数据来测试多态关联:

// 创建用户
$user = new User();
$user->name = 'John Doe';
$user->save();

// 创建角色
$role1 = new Role();
$role1->name = 'Admin';
$role1->save();

$role2 = new Role();
$role2->name = 'Editor';
$role2->save();

// 将用户添加到角色
$user->roles()->attach($role1);
$user->roles()->attach($role2);

// 将角色添加到用户
$role1->users()->attach($user);
$role2->users()->attach($user);

3. 查询数据

现在,我们可以查询用户和角色的数据,并验证多态关联是否正常工作:

// 查询所有用户及其角色
$users = User::with('roles')->get();

foreach ($users as $user) {
    echo "User: {$user->name}n";
    foreach ($user->roles as $role) {
        echo "  Role: {$role->name}n";
    }
}

输出结果将会是:

User: John Doe
  Role: Admin
  Role: Editor

总结

通过上述示例,我们展示了如何在Laravel中使用多态关联来处理复杂的关联关系。多态关联使得我们的模型更加灵活和强大,能够更好地适应各种应用场景。

黑板Bug讲师

黑板Bug讲师

介绍

Laravel的Eloquent ORM中的多态关系提供了一种设置单个关联到不同模型的方法。本指南将带你了解多态关系的概念,展示代码示例并解释如何在你的Laravel应用程序中使用它们。

理解多态关系

在Eloquent中,一个模型可以属于另一个模型的多个关联中的关系被称为多对一关系(polymorphic relationship)。典型的例子包括评论或文件,这些对象可以在帖子、视频或其他任何类型的对象上进行关联。要理解这一点,请让我们从一个基本的例子开始:设置一个多对一关系:建立一个模型之间的多对一关系。Comment模特和模特儿Postand 是中文里的“并且”的意思。Video好的,请提供需要翻译的内容。

class Comment extends Model
{
    public function commentable()
    {
        return $this->morphTo();
    }
}

class Post extends Model
{
    public function comments()
    {
        return $this->morphMany('AppComment', 'commentable');
    }
}

class Video extends Model
{
    public function comments()
    {
        return $this->morphMany('AppComment', 'commentable');
    }
}

在数据库中,您的comments表格可能有一个类似于这样的结构:

Schema::create('comments', function (Blueprint $table) {
    $table->id();
    $table->text('body');
    $table->morphs('commentable');
    $table->timestamps();
});

这将创建两个额外的列:commentable_type和我有什么事吗?commentable_id抱歉,我不太明白你的意思,请重新描述一下你的问题或者需求。commentable_type列将存储与相关模型关联的类名。commentable_id存储相关记录的ID。使用这种设置,你现在可以对任何您设置了多态关联模型的表发布评论。

检索并使用多态关系

让我们现在看看如何检索和处理这种关系。例如,要获取与帖子相关的评论:

$post = Post::find(1);
foreach ($post->comments as $comment) {
  echo $comment->body;
}

对于视频,也可以这样做。

$video = Video::find(1);
foreach ($video->comments as $comment) {
  echo $comment->body;
}

高级关系:形态图和自定义键

Laravel 允许您使用自定义类型字段名称,通过使用morph maps 来实现。这可以帮助避免在数据库中存储完全限定的类名。让我们看看如何定义和利用一个morph map:

use IlluminateDatabaseEloquentRelationsRelation;

Relation::morphMap([
  'posts' => 'AppPost',
  'videos' => 'AppVideo',
]);

现在,而不是Laravel存储完整的模型类名,在这里我们使用一个更灵活的方法来获取模型实例。commentable_type它会从morph映射中存储自定义键。ID也可以设置为自定义键:

return $this->morphMany('AppComment', 'commentable', 'model_type', 'model_id');

这改变了Laravel查找列的名称,从默认值。commentable_typeand 是“并且”的意思。commentable_id没有收到您的消息,请问有什么我可以帮助您的吗?model_typeand 是中文中的“和”,表示连接两个事物或概念的连词。model_id好的,请发送你需要翻译的内容。

多对多聚合关系

Eloquent也支持“由许多塑造”的关系,这允许您拥有一个许多到许多多态关联。通常用于如标签这样的场景,这些标签可以属于不同的模型中的任何数量。设置如下所示:

class Tag extends Model
{
    public function posts()
    {
        return $this->morphedByMany('AppPost', 'taggable');
    }
    public function videos()
    {
        return $this->morphedByMany('AppVideo', 'taggable');
    }
}

class Post extends Model
{
    public function tags()
    {
        return $this->morphToMany('AppTag', 'taggable');
    }
}

class Video extends Model
{
    public function tags()
    {
        return $this->morphToMany('AppTag', 'taggable');
    }
}

用于存储数据,你需要一个中间表,可能命名为taggables好的,请提供需要翻译的内容。

Schema::create('taggables', function (Blueprint $table) {
    $table->id();
    $table->morphs('taggable');
    $table->unsignedBigInteger('tag_id');
    $table->timestamps();
});

要获取帖子的所有标签,你可以简单地使用:

$post = Post::find(1);
foreach ($post->tags as $tag) {
  echo $tag->name;
}

多对多多态关系:自定义透视属性

自定义透视属性可以在多对多聚合关系(polymorphic relation)上访问或分配,就像标准的多对多关系一样。这意味着在透视表中可以有额外关于该关系的数据,并方便地进行交互:

// When attaching a tag
$post->tags()->attach($tagId, ['custom_attribute' => 'value']);

// When retrieving pivot data
foreach ($post->tags as $tag) {
  echo $tag->pivot->custom_attribute;
}

结论。

多态关系(Polymerous Relations)在Eloquent ORM中是一种强大的且灵活的特性,能够有效地管理复杂的数据结构和关系,从而在Laravel应用中优雅地进行数据库设计。它们允许编写更可重用和抽象化的代码,并显著简化数据库设计。

长工码奴1523

长工码奴1523

Eloquent 是 Laravel 的 ORM(对象关系映射)库的一部分,它提供了灵活的关联和关联操作。其中的一个核心概念是 hasManyhasMany 关联。

假设我们有一个用户模型 User 和一个帖子模型 Post。我们可以使用 hasManyhasMany 关联来定义一个 User 可能有多个 Post,或者一个 Post 可能属于一个 User

示例代码

use IlluminateSupportFacadesDB;

class User extends Model
{
    public function posts()
    {
        return $this->hasMany(Post::class);
    }
}

class Post
{
    public function user()
    {
        return $this->belongsTo(User::class);
    }
}

在这个例子中:

  • User 模型具有 posts 属性,这表示 User 对应的每一条 Post 都会作为一个关联项存储。
  • Post 模型具有 user 属性,这表示每个 Post 对应的 User 都会被存储为一个关联项。

如何理解 hasManyhasMany

hasMany 表示一个关联可以指向另一个关联的多个实例,而 hasMany 则表示一个关联只能指向另一个关联的单个实例。

例如,如果你有一个用户可以拥有多个帖子,那么你可以这样关联:

$user = new User();
$post1 = new Post();
$post2 = new Post();

$user->posts()->save($post1);
$user->posts()->save($post2);

// 这里,$user->posts() 返回的是一个关联数组,包含了两个元素。
// 因此,你可以遍历这个数组并访问 $post1 和 $post2 的属性。
foreach ($user->posts as $post) {
    var_dump($post); // 输出:object(Post)#4 (3) { ["id"]=> string(1) "1" ["created_at"]=> string(19) "2022-08-20 15:36:47" ["updated_at"]=> string(19) "2022-08-20 15:36:47" } ["id"]=> string(1) "2" ["created_at"]=> string(19) "2022-08-20 15:36:47" ["updated_at"]=> string(19) "2022-08-20 15:36:47" }

在这个例子中,$user->posts() 返回的是一个关联数组,包含了两个元素。你可以遍历这个数组并访问 $post1$post2 的属性。