搜索
首页后端开发php教程Laravel 5.1 文档攻略--Laravel Eloquent ORM最强大也是最难理解的部分:数据关系

简介

其实大家都知道,数据表之间都是可以关联的,Eloquent ORM是数据模型操作代替表操作,那么表的关联查询,在Eloquent这里也就是模型间的关联查询,这就是本章的主要内容;

Eloquent一个支持以下6种表间关系:

  • One To One(一对一)

  • One To Many(一对多)

  • Many To Many(多对多)

  • Has Many Through(跨表一对多)

  • Polymorphic Relations(belongsTo多态)

  • Many To Many Polymorphic Relations(belongsToMany多态)

前三个关系是什么就不多解释了(请自行百度),这个地方需要很多耐心,努力让自己习惯对象思维,暂时先不要用sql,练一段时间就会发现非常好用;

当然,也有人吐槽Eloquent由于过于强大,造成每次加载都带一大堆东西,影响效率(实际没啥影响,不服的拿数据跟我说),但是在代码的编写效率,可读性,可维护性上可以说是质的飞跃,所以还是强烈建议优先使用。

这一章我是学得最早,但是教程是写的最晚的,因为各种关系比较复杂,好在我是做产品出身,应该可以把复杂的事情解释清楚,下面就让我们来认识一下这个星球上最强大的ORM:Eloquent

基本概念

先看看是怎么使用的吧:

$user->posts()->where('active', 1)->get();

这个就是通过 $user 对象查出他一共发布了多少篇文章(状态为已发布的)。

我们看到 posts() 在这里是 $user 的一个方法,所以要使用关联查询,得先在 $user 模型里定义关系(方法);

一对一

从这张图中,我们可以看到要使用Eloquent 模型关系,第一步要在模型里定义模型关系,第二步数据库要准备正确的表;第三部分使用 查询的方法,第四部分是使用绑定和解除绑定的方法,我们后续的模型关系都按照这个流程理解和解释;

要点:反复观察图!

定义模型

定义User模型

namespace App;use Illuminate\Database\Eloquent\Model;class User extends Model{        public function phone()    {        return $this->hasOne('App\Phone');    }}

定义Phone模型

namespace App;use Illuminate\Database\Eloquent\Model;class Phone extends Model{    public function user()    {        return $this->belongsTo('App\User');    }}

注意:定义模型的时候方法名注意单复数,“一”就用单数,“多”就用复数,这样不容易混淆搞错。 hasOne() 类似这个关系绑定方法有很多,需要在使用中慢慢熟悉,注意观察。

数据表

主要是注意,外键和中间表这些东西,本例中没有中间表;

关系查询

模型关系方法查询

$user->posts()->where('active', 1)->get();

这就是模型方法查询, $user->posts() 这里查出来是个DQB对象,后面可以接各种数据库查询方法;

动态属性查询

$user->posts;

你可以把关系当做属性用,直接查出来一个collection集;缺点是后面不能跟DQB方法了。

这两种方法都很常用,酌情使用;(下同,不再解释)

关系绑定和解除

通用的绑定方法就是save();

通用的解除方法,对于belongsTo的关系是dissociate(); 对于belongsToMany的关系是detach();

还有一些特定的绑定解除方法,我们再单独的关系模型中讲;

一对多

反绑

如果你要通过belongsTo关系绑定,可以用associate()来绑定,最后要save()一下,如图;

多对多

由于belongsTo换成了belongsToMany, 所以对应的绑定方法换成了attach()和detach();注意这里面填对象ID,可以用数组形式批量绑定;

save()方法仍然适用与关系绑定;

对中间表的操作

由于多对多关系多了一张中间表,Eloquent除了默认对这里面的外键进行操作以外,还可以对中间表的其他字段进行操作,看示例:

App\User::find(1)->roles()->save($role, ['expires' => $expires]);
$user->roles()->attach($roleId, ['expires' => $expires]);
$user->roles()->attach([1 => ['expires' => $expires], 2, 3]);
$user->roles()->sync([1 => ['expires' => true], 2, 3]);

sync()方法

sync就是同步,意思是说中间表会同步成sync()里面参数一样,没有写在参数里的都会移除,因此可以用来解除绑定;

Has Many Through(跨表一对多)

其实这只是一种快速查询方法,看图,本来可以先通过Conuntry查User,然后通过User查Post,现在你可以通过Country直接查Post;

通常Country和User,User和Post的表间关系都是事先建立好的,这个时候你再使用hasManyThrough;

Polymorphic Relations(belongsTo多态)

本来belongsTo只能属于一种对象的,就像女朋友只能属于男朋友;现在好了,女朋友不仅可以属于男朋友,还可以属于干爹了。

开玩笑的,最常见的应用还是图片,可以属于多种模型,看图;

我们发现这里的动词变成了morphTo(), morphMany();

先上一小段英语课,提升一下语感:

morph这个词的意思是改变形态,简称变态;这个和变形金刚的那个transform是不一样的,那个主要是改变形状;

morphTo(), morphMany(); 其实就是belongsTo() 和 hasMany() 多态形式,多态就是不仅拥有男票,还有干爹,有点“变态”;

关于绑定和解绑

associate()不适用用于morphTo();所以只能单向的用save()绑定了;

关于解绑,dissociate()也不适用用于morphTo();所以,只能把Photo实例删除!!删除了就没任何关系了(因为没有中间表)

感觉有点不是很自然的设计,不过目前调查下来情况就是这样;

Many To Many Polymorphic Relations(belongsToMany多态)

这个最典型的应用就是标签了,标签要涉及多对多的关系,还涉及对应不同类型的模型的问题,所以就是belongsToMany+多态;

看图,可绑定,可解绑;

Eager Loading(预加载)

这个问题很简单,看个实例你就懂了:

$books = App\Book::all();foreach ($books as $book) {    echo $book->author->name;}

万一books有一万本,那么循环就要1万次,每次循环,因为用了关联查询 $book->author->name; ,都会读数据库一次,意味着至少读数据库一万次,数据库哭了。

Eager Loading 就是让数据库读取发生在循环之前:

$books = App\Book::with('author')->get();foreach ($books as $book) {    echo $book->author->name;}

看,加了个神奇的with()后,所有数据在foreach前都读出来了,后面循环的只是读出来的数据,一共查询数据库2次!!

Eager Loading可以极大的缓解数据库查询压力,是性能优化的重要手段!

Eager Loading 多个关系

就是一次多加几张关联表而已;

$books = App\Book::with('author', 'publisher')->get();

嵌套 Eager Loading

$books = App\Book::with('author.contacts')->get();

把书的作者读出来,顺便把作者的联系方式读出来。

有条件的 Eager Loading

上面说的是整张表整张表的读出来,太土豪了,其实有时候我们只需要表里的部分记录:

$users = App\User::with(['posts' => function ($query) {    $query->where('title', 'like', '%first%');}])->get();

这中闭包的写法我们讲过多次,就是加个条件而已;

Lazy Eager Loading

这标题难道不是自相矛盾吗?又Lazy,又Eager?

哦,原来是在lazy的流程里判断需不需要eager loading一下:

$books = App\Book::all();if ($someCondition) {    $books->load('author', 'publisher');}
$books->load(['author' => function ($query) {    $query->orderBy('published_date', 'asc');}]);

注意这个load(),这是对collection用的;

跨模型更新时间戳

简单的来说,就是一条评论更新的时候,顺便把文章的'updated_at'字段也更新了;

namespace App;use Illuminate\Database\Eloquent\Model;class Comment extends Model{    /**     * All of the relationships to be touched.     *     * @var array     */    protected $touches = ['post'];    /**     * Get the post that the comment belongs to.     */    public function post()    {        return $this->belongsTo('App\Post');    }}

设置$touches这个属性;

然后你更新Comment的时候,就会把Post的'updated_at'字段也更新了;

更多内容请访问: Laravel 5.1 文档攻略

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
简单地说明PHP会话的概念。简单地说明PHP会话的概念。Apr 26, 2025 am 12:09 AM

phpsessionstrackuserdataacrossmultiplepagerequestsusingauniqueIdStoredInacookie.here'showtomanageThemeffectionaly:1)startAsessionWithSessionwwithSession_start()和stordoredAtain $ _session.2)

您如何循环中存储在PHP会话中的所有值?您如何循环中存储在PHP会话中的所有值?Apr 26, 2025 am 12:06 AM

在PHP中,遍历会话数据可以通过以下步骤实现:1.使用session_start()启动会话。2.通过foreach循环遍历$_SESSION数组中的所有键值对。3.处理复杂数据结构时,使用is_array()或is_object()函数,并用print_r()输出详细信息。4.优化遍历时,可采用分页处理,避免一次性处理大量数据。这将帮助你在实际项目中更有效地管理和使用PHP会话数据。

说明如何使用会话进行用户身份验证。说明如何使用会话进行用户身份验证。Apr 26, 2025 am 12:04 AM

会话通过服务器端的状态管理机制实现用户认证。1)会话创建并生成唯一ID,2)ID通过cookies传递,3)服务器存储并通过ID访问会话数据,4)实现用户认证和状态管理,提升应用安全性和用户体验。

举一个如何在PHP会话中存储用户名的示例。举一个如何在PHP会话中存储用户名的示例。Apr 26, 2025 am 12:03 AM

Tostoreauser'snameinaPHPsession,startthesessionwithsession_start(),thenassignthenameto$_SESSION['username'].1)Usesession_start()toinitializethesession.2)Assigntheuser'snameto$_SESSION['username'].Thisallowsyoutoaccessthenameacrossmultiplepages,enhanc

哪些常见问题会导致PHP会话失败?哪些常见问题会导致PHP会话失败?Apr 25, 2025 am 12:16 AM

PHPSession失效的原因包括配置错误、Cookie问题和Session过期。1.配置错误:检查并设置正确的session.save_path。2.Cookie问题:确保Cookie设置正确。3.Session过期:调整session.gc_maxlifetime值以延长会话时间。

您如何在PHP中调试与会话相关的问题?您如何在PHP中调试与会话相关的问题?Apr 25, 2025 am 12:12 AM

在PHP中调试会话问题的方法包括:1.检查会话是否正确启动;2.验证会话ID的传递;3.检查会话数据的存储和读取;4.查看服务器配置。通过输出会话ID和数据、查看会话文件内容等方法,可以有效诊断和解决会话相关的问题。

如果session_start()被多次调用会发生什么?如果session_start()被多次调用会发生什么?Apr 25, 2025 am 12:06 AM

多次调用session_start()会导致警告信息和可能的数据覆盖。1)PHP会发出警告,提示session已启动。2)可能导致session数据意外覆盖。3)使用session_status()检查session状态,避免重复调用。

您如何在PHP中配置会话寿命?您如何在PHP中配置会话寿命?Apr 25, 2025 am 12:05 AM

在PHP中配置会话生命周期可以通过设置session.gc_maxlifetime和session.cookie_lifetime来实现。1)session.gc_maxlifetime控制服务器端会话数据的存活时间,2)session.cookie_lifetime控制客户端cookie的生命周期,设置为0时cookie在浏览器关闭时过期。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

PhpStorm Mac 版本

PhpStorm Mac 版本

最新(2018.2.1 )专业的PHP集成开发工具

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

将Eclipse与SAP NetWeaver应用服务器集成。

MinGW - 适用于 Windows 的极简 GNU

MinGW - 适用于 Windows 的极简 GNU

这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。

VSCode Windows 64位 下载

VSCode Windows 64位 下载

微软推出的免费、功能强大的一款IDE编辑器