资讯专栏INFORMATION COLUMN

深入理解 Laravel Eloquent(三)——模型间关系(关联)

2501207950 / 2750人阅读

摘要:是什么是一个,全称为,翻译为对象关系映射如果只把它当成数组库抽象层那就太小看它了。所谓对象,就是本文所说的模型对象关系映射,即为模型间关系。至此,深入理解系列文章到此结束。

  

原文发表在我的个人网站:深入理解 Laravel Eloquent(三)——模型间关系(关联)

在本篇文章中,我将跟大家一起学习 Eloquent 中最复杂也是最难理解的部分——模型间关系。官方英文文档中叫 Relationships,个人认为翻译成 “模型间关系” 比现在的 “关联” 更好理解一点哈哈。

Eloquent是什么

Eloquent 是一个 ORM,全称为 Object Relational Mapping,翻译为 “对象关系映射”(如果只把它当成 Database Abstraction Layer 数组库抽象层那就太小看它了)。所谓 “对象”,就是本文所说的 “模型(Model)”;对象关系映射,即为模型间关系。中文文档: http://laravel-china.org/docs/eloquent#relationships

下面我们开始一个一个地学习。

一对一关系

顾名思义,这描述的是两个模型之间一对一的关系。这种关系是不需要中间表的。

假如我们有两个模型:User 和 Account,分别对应注册用户和消费者,他们是一对一的关系,那么如果我们要使用 Eloquent 提供的一对一关系方法,表结构应该是这样的:

rubyuser: id ... ... account_id
account: id ... ... user_id

假设我们需要在 User 模型中查询对应的 Account 表的信息,那么代码应该是这样的。 /app/models/User.php:

phphasOne("Account", "user_id", "id");
  }
}

然后,当我们需要用到这种关系的时候,该如何使用呢?如下:

php$account = User::find(10)->hasOneAccount;

此时得到的 $account 即为 Account 类的一个实例。


这里最难的地方在于后面的两个 foreign_key 和 local_key 的设置,大家可以就此记住:在 User 类中,无论 hasOne 谁,第二个参数都是 user_id,第三个参数一般都是 id。由于前面的 find(10) 已经锁定了 id = 10,所以这段函数对应的 SQL 为: select * from account where user_id=10


这段代码除了展示了一对一关系该如何使用之外,还传达了三点信息,也是我对于大家使用 Eloquent 时候的建议:

  

每一个 Model 中都指定表名

has one account 这样的关系写成 hasOneAccount() 而不是简单的 account()

每次使用模型间关系的时候都写全参数,不要省略

相应的,如果使用 belongsTo() 关系,应该这么写:

phpbelongsTo("User", "user_id", "id");
  }
}
一对多关系

学会了前面使用一对一关系的基础方法,后面的几种关系就简单多了。

我们引入一个新的Model:Pay,付款记录。表结构应该是这样的:

rubyuser: id ... ...
pay: id ... ... user_id

User 和 Pay 具有一对多关系,换句话说就是一个 User 可以有多个 Pay,这样的话,只在 Pay 表中存在一个 user_id 字段即可。 /app/models/User.php:

phphasMany("Pay", "user_id", "id");
  }
}

然后,当我们需要用到这种关系的时候,该如何使用呢?如下:

php$accounts = User::find(10)->hasManyPays()->get();

此时得到的 $accounts 即为 IlluminateDatabaseEloquentCollection 类的一个实例。大家应该也已经注意到了,这里不是简单的 -> hasOneAccount 而是 ->hasManyPays()->get(),为什么呢?因为这里是 hasMany,操作的是一个对象集合。

相应的 belongsTo() 的用法跟上面一对一关系一样:

phpbelongsTo("User", "user_id", "id");
  }
}
多对多关系

多对多关系和之前的关系完全不一样,因为多对多关系可能出现很多冗余数据,用之前自带的表存不下了。

我们定义两个模型:Article 和 Tag,分别表示文章和标签,他们是多对多的关系。表结构应该是这样的:

rubyarticle: id ... ...
tag: id ... ...
article_tag: article_id tag_id

在 Model 中使用:

phpbelongsToMany("Article", "article_tag", "tag_id", "article_id");
  }
}

需要注意的是,第三个参数是本类的 id,第四个参数是第一个参数那个类的 id。

使用跟 hasMany 一样:

php$tagsWithArticles = Tag::take(10)->get()->belongsToManyArticle()->get();

这里会得到一个非常复杂的对象,可以自行 var_dump()。跟大家说一个诀窍,var_dump() 以后,用 Chrome 右键 “查看源代码”,就可以看到非常整齐的对象/数组展开了。

  

在这里给大家展示一个少见用法(奇技淫巧):

phppublic function parent_video()
{
    return $this->belongsToMany($this, "video_hierarchy", "video_id", "video_parent_id");
}
public function children_video()
{
    return $this->belongsToMany($this, "video_hierarchy", "video_parent_id", "video_id");
}

对,你没有看错,可以 belongsToMany 自己。

其他关系

Eloquent 还提供 “远层一对多关联”、“多态关联” 和 “多态的多对多关联” 这另外三种用法,经过上面的学习,我们已经掌握了 Eloquent 模型间关系的基本概念和使用方法,剩下的几种不常用的方法就留到我们用到的时候再自己探索吧。

重要技巧:关系预载入

你也许已经发现了,在一对一关系中,如果我们需要一次性查询出10个 User 并带上对应的 Account 的话,那么就需要给数据库打 1 + 10 条 SQL,这样性能是很差的。我们可以使用一个重要的特性,关系预载入:http://laravel-china.org/docs/eloquent#eager-loading

直接上代码:

php$users = User::with("hasOneAccount")->take(10)->get()

这样生成的 SQL 就是这个样子的:

sqlselect * from account where id in (1, 2, 3, ... ...)

这样 1 + 10 条 SQL 就变成了 1 + 1 条,性能大增。



至此,深入理解 Laravel Eloquent 系列文章到此结束。推荐继续了解 软删除 、转换成数组/JSON。

END

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/20903.html

相关文章

  • 深入理解 Laravel Eloquent(二)——中操作流(Builder)

    摘要:原文发表在我的个人网站深入理解二中间操作流本篇教程是该系列教材的第二篇,将主要讲述中中间操作流的概念。复杂用法示例下一步深入理解三模型间关系关联 原文发表在我的个人网站:深入理解 Laravel Eloquent(二)——中间操作流(Builder) 本篇教程是该系列教材的第二篇,将主要讲述 Eloquent 中中间操作流的概念。中间操作流是我自己总结并翻译的概念,支撑该功能的类...

    yy736044583 评论0 收藏0
  • Laravel 的 ORM 返回的数据类型小结

    摘要:一简介的数据库查询构造器提供了一个方便流畅的接口,用来创建及运行数据库查询语句。的查询构造器使用参数绑定,来保护你的应用程序免受注入的攻击。和返回的是影响行数,即失败为,成功为删除行数。 相信很多人在学习 Laravel 时,会对 ORM 返回的数据类型产生混淆,如返回集合,模或者整数类型,下面将对增删改查操作进行一个小结。 一、简介 Laravel 的数据库查询构造器提供了一个方便、...

    LeviDing 评论0 收藏0
  • Laravel核心解读--Database(四) 模型关联

    摘要:为关联关系设置约束子模型的等于父模型的上面设置的字段的值子类实现这个抽象方法通过上面代码看到创建实例时主要是做了一些配置相关的操作,设置了子模型父模型两个模型的关联字段和关联的约束。不过当查询父模型时,可以预加载关联数据。 Database 模型关联 上篇文章我们主要讲了Eloquent Model关于基础的CRUD方法的实现,Eloquent Model中除了基础的CRUD外还有一个...

    gekylin 评论0 收藏0
  • Laravel学习笔记七-创建博客

    摘要:本节将使用用户创建博文来学习数据模型关联的有关知识。我们发现为我们生成的时间是英文的,如果要使用中文时间,则需要对进行本地化设置。动态属性让你能够访问关联函数,就像他们是在模型中定义的属性会假设对应关联的外键名称是基于模型名称的。 本节将使用用户创建博文来学习数据模型关联的有关知识。 一、Laravel常用知识总结 1.提示信息汉化 如果用Laravel原生的表单提示错误信息,则是英文...

    icyfire 评论0 收藏0
  • 20 个 Laravel Eloquent 必备的实用技巧

    摘要:看起来是一个简单的机制,但是在底层,有很多半隐藏的函数和鲜为人知的方式来实现更多功能。在这篇文章中,我将演示几个小技巧。另外,在里也有些和时间相关的预定义方法通过关系排序一个复杂一点的技巧。幸运的是,确实有这样的方法。 showImg(https://segmentfault.com/img/bV8L5s?w=1240&h=634); Eloquent ORM 看起来是一个简单的机制,...

    clasnake 评论0 收藏0

发表评论

0条评论

2501207950

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<