、数组或者是一个 stdClass 了,已经不是可以持续构造的 Builder 对象了。...,一行就是条件参数数组,是不是非常方便。...这个就要一步一步来看了,前面其实我们已经看到了 laravel/framework/src/Illuminate/Database/Query/Builder.php 这个对象的类文件,那么我们是怎么通过...use Illuminate\Database\Query\Builder as QueryBuilder; // laravel/framework/src/Illuminate/Database/...(), $this->getPostProcessor() ); } 注意这个 QueryBuilder 实际上是 use Illuminate\Database\Query\Builder
Connector数据库连接器的闭包外 (就是参数里的 $pdo, 他是一个闭包,具体值在下面和上篇文章中都有提到) 还加载了两个重要的组件 Illuminate\Database\Query\Grammars...接下我们到QueryBuilder类文件 \Illuminate\Database\Query\Builder.php里看看它里面的源码 namespace Illuminate\Database\Query...; } /** * 编译Select查询语句的各个部分 * @param \Illuminate\Database\Query\Builder $query * @return array...、 wheres属性,那么我们见先来看看这三个属性的编译器: /** * 编译Select * 部分的SQL * @param \Illuminate\Database\Query\Builder...通过梳理流程我们知道: Laravel是在第一次执行SQL前去连接数据库的,之所以$pdo一开始是一个闭包因为闭包会保存创建闭包时的上下文里传递给闭包的变量,这样就能延迟加载,在用到连接数据库的时候再去执行这个闭包连上数据库
查询作用域 全局作用域 全局作用域允许你对给定模型的所有查询添加约束。使用全局作用域功能可以为模型的所有操作增加约束。...* * @param \Illuminate\Database\Eloquent\Builder $builder * @param \Illuminate\Database...$query) { return $query->where('active', 1); } } 使用上述添加的本地约束查询,只需要在查询中使用scope前缀的方法,去掉...scope前缀即可 $users = App\User::popular()->active()->orderBy('created_at')->get(); 本地作用域方法是可以接受参数的 public...; $user->first_name = 'Sally'; 属性转换 模型的$casts属性提供了一种非常简便的方式转换属性为常见的数据类型,在模型中,使用$casts属性定义一个数组,该数组的key
); } /** * 只包含激活用户的查询作用域 * * @return \Illuminate\Database\Eloquent\Builder */ public function scopeActive...->orderBy('created_at')->get(); 动态作用域 /** * 让查询只包含给定类型的用户 * * @param \Illuminate\Database\Eloquent...\Builder $query * @param mixed $type * @return \Illuminate\Database\Eloquent\Builder */ public function...] ]); 在中间表上保存额外数据 处理多对多关联时, save 方法接收中间表数组作为第二个参数: App\User::find(1)->roles()->save($role, ['expires'...反序列化为 PHP 数组 // 设置 options 属性的值时, 给定数组将会自动转化为 JSON 以供存储 'options' => 'array', ];
上篇文章我们讲了Database的查询构建器Query Builder, 学习了Query Builder为构建生成SQL语句而提供的Fluent Api的代码实现。...$this->take(1)->get($columns)->first(); } } //newModelInstance newFromBuilder 定义在\Illuminate\Database...的where方法在接到调用请求后直接把请求转给来Query Builder的 where方法,然后get方法也是先通过Query Builder的 get方法执行查询拿到结果数组后再通过 newFromBuilder...方法把结果数组转换成Model对象构成的集合,而另外一个比较常用的方法 first也是在 get方法的基础上实现的,对query应用limit 1,再从 get方法返回的集合中用 Arr::first(...是在Query Builder的基础上做了进一步封装, Eloquent Builder会把这些CRUD方法的调用转给Query Builder里对应的方法来完成操作,所以在Query Builder里能使用的方法到
中主要有三件利器:\Illuminate\Database\MysqlConnector;\Illuminate\Database\Query\Grammars\Grammar;\Illuminate\...Database\Query\Processors\Processor,其中\Illuminate\Database\MysqlConnector是在ConnectionFactory中构造出来的并通过...MySqlConnection的构造参数注入的,上篇中重点谈到的通过createPdoResolver($config)获取到的闭包函数作为参数注入到该MySqlConnection,而\Illuminate...\Database\Query\Grammars\Grammar和\Illuminate\Database\Query\Processors\Processor是在MySqlConnection构造函数中通过...OK,那Query Builder是如何把书写的api编译成SQL呢?
OK,那Query Builder是如何把书写的api编译成SQL呢?...return new \Illuminate\Database\Query\Builder( $this, $this->getQueryGrammar(), $this->getPostProcessor...在看下这两步骤之前,先看下后置处理器对查询的结果集做了什么后置操作: // \Illuminate\Database\Query\Processors\Processor public...OK,那Query Builder是如何把书写的api编译成SQL呢?...return new \Illuminate\Database\Query\Builder( $this, $this->getQueryGrammar(), $this->getPostProcessor
laravel/framework/src/Illuminate/Database/Eloquent/Collection.php 对象,然后这个对象里面有个 items 属性,是一个数组。...,有两种形式的序列化,一是序列化为数组,二是序列化为 JSON 格式字符串。...不过这里需要注意的是,模型默认生成的 QueryBuilder 是 llaravel/framework/src/Illuminate/Database/Eloquent/Builder.php 对象,...而不是我们之前 查询构造器 中的 laravel/framework/src/Illuminate/Database/Query/Builder.php 对象。...但 Eloquent\Builder 的内部持有的一个query 属性依然是 Query\Builder 对象,也就是说在底层,它依然是调用的我们熟悉的那个 查询构造器 来进行工作的。
\Database\Query\Builder|\App\Phone whereId($value) * @method static \Illuminate\Database\Query\Builder...\Query\Builder|\App\Product whereShopId($value) * @method static \Illuminate\Database\Query\Builder|...\Query\Builder|\App\Shop whereSite($value) * @method static \Illuminate\Database\Query\Builder|\App\...预加载查询 (1)嵌套预加载 Eloquent在通过属性访问关联数据时是延迟加载的,就是只有该关联数据只有在通过属性访问它时才会被加载。在查找上层模型时可以通过预加载关联数据,避免N+1问题。...发现:只有4个query,耗时3.58ms,效率提高很多。把原来的N+1这种query改造成了where..in..这种query,效率提高不少。可以用EXPLAIN来查看SQL语句的执行计划。
编写全局作用域 1.定义一个类 namespace App\Scopes; use Illuminate\Database\Eloquent\Scope; use Illuminate\Database...\Eloquent\Model; use Illuminate\Database\Eloquent\Builder; class AgeScope implements Scope { /**...* 将范围应用于给定的 Eloquent 查询生成器 * * @param \Illuminate\Database\Eloquent\Builder $builder...渴求式加载指定字段 有时候,使用渴求式加载时不需要查询全部字段,这个时候可使用“指定字段” 格式with('模型方法:id,字段1,字段2') 需要注意的是渴求式加载指定字段必须列出父表id 如下例子...} 插入多条数据添加并添加额外字段,通过键值关联对应记录与额外字段 第一个参数 插入的值(数组),第二个参数插入值对应的额外字段(数组) public function show(){
)即一个没有指定名称的函数,经常用做回调函数(callback)参数的值 2.匿名函数既可以作为参数传递给函数,也可以做为变量赋值,进而控制函数的执行过程;可以从父作用域中继承变量,使用use关键字来继承...二是数据库连接工厂阶段,\Illuminate\Database\Connectors\ConnectionFactory 三是数据库连接器阶段,\Illuminate\Database\Connectors...\Query\Builder)实例封装了数据库连接实例、请求语法实例和结果处理实例,这里类的实例提供了统一的接口方法供查询构造器实例使用 5.查询构造器使用阶段: SQL语句准备阶段,Illuminate...\Database\Query\Grammars SQL语句执行阶段,Illuminate\Database\Connection C.Eloquent ORM 1.两个阶段 Eloquent ORM查询构造器的生成...,Illuminate\Database\Eloquent\Model::newQuery() 操作命令的执行,Illuminate\Database\Eloquent\Builder 2.ORM映射最大的好处是将数据表的结构映射成一个类对象
实际上,上一篇聊到了\Illuminate\Database\Query\Builder这个非常重要的类,这个类含有三个主要的武器:MySqlConnection, MySqlGrammar, MySqlProcessor...$this->compileUnions($query); } return $sql; } 这里首先会调用Illuminate\Database\Query\..., $bindings = 1作为参数传递进去 return $this->run($query, $bindings, function (Connection $me, $query...所以这里可看出Query Builder是在PHP PDO的基础上实现的一层封装,使得用更加面向对象的Fluent API来操作数据库,而不需要写一行SQL语句。...OK, illuminate/database package不仅提供了Query Builder,还提供了Eloquent ORM。
,如果query发生,则将传入的SQL语句参数写入日志内。...我们使用全局的 Config 类获取配置信息: Config::get('database.log', false) 如果没有开启数据库日志,则手动处理,将上述 illuminate.query 事件的监听器写入系统内...那么监听事件实现起来是这样的: Event::listen('illuminate.query', function($query, $bindings, $time, $name){}); 好了,既然获取到传入的数据了...为了处理方便,将所有原始数据写入 Log 类方法的第二个传参, 我们将参数打包到数组: $data = compact('bindings', 'time', 'name'); 因为单个SQL语句绑定的参数有很多...,进行格式化;如果是时间戳或者字符串,直接存档。
通过全局作用域类实现 要实现「全局作用域」,首先需要编写一个实现 Illuminate\Database\Eloquent\Scope 接口的全局作用域类,这里我们将其命名为 EmailVerifiedAtScope...php namespace App\Scopes; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent...\Model; use Illuminate\Database\Eloquent\Scope; class EmailVerifiedAtScope implements Scope { public...,比如我要在文章中查询指定类型的文章,可以通过在 Post 模型类中定义如下方法: public function scopeOfType(Builder $query, $type) { return...$query->where('type', $type); } 这样,在查询指定类型的文章时,就可以这么实现: $posts = Post::active()->ofType(Post::Article
; 该方法可以可以用于批量删除传入的指定ID数组的条目: Contact::destroy([1, 5, 7]); 当然了,delete方法只是链式调用的一个方法,我们通过查询构造器过滤后的数据集, 都可以调用该方法将其删除...模型中相关代码如下: use Illuminate\Database\Eloquent\Model;use Illuminate\Database\Eloquent\SoftDeletes;class...) { return $query->where('vip', true)->where('trial', false); }} 给本地的作用域方法添加传入的参数: class...创建 app/Scopes/ActiveScope.php 文件: namespace App\Scopes;use Illuminate\Database\Eloquent\Scope;use Illuminate...\Database\Eloquent\Model;use Illuminate\Database\Eloquent\Builder;class ActiveScope implements Scope{
* * @param \Illuminate\Database\Eloquent\Builder $query * @param string...* * @param \Illuminate\Database\Eloquent\Builder $query * @param array...我尝试debug进入where()函数看了看它内部的实现,src/Illuminate/Database/Query/Builder.php: public function where($column...($query, $boolean); } 可以观察到,这里面有个很重要的回调,遍历了用户输入的第一个数组参数column,当发现其键名是一个数字,且键值是一个数组时,将会调用[query, method...POST中传入的一个数组,这意味着注入到模板中的变量只是简单的字符串数组,没有任何对象。
Redis 简介 Redis 是一个开源的,高级键值对存储数据库。由于它包含 字符串,哈希,列表,集合,和 有序集合 这些数据类型,所以它通常被称为数据结构服务器。...' => env('REDIS_CACHE_DB', 1), ], ], 默认的服务器配置应该足以进行开发。...Laravel 使用魔术方法将命令传递给 Redis 服务器,因此只需传递 Redis 命令所需的参数即可: Redis::set('name', 'Taylor'); $values = Redis...::lrange('names', 5, 10); 或者,你也可以使用 command 方法将命令传递给服务器,它接受命令的名称作为其第一个参数,并将值的数组作为其第二个参数: $values = Redis...这个 $channel 名称将作为第二个参数传递给提供的回调 闭包: Redis::psubscribe(['*'], function ($message, $channel) { echo
应用场景 某些SQL语句需要加某些共同的条件,例如status > 0,如果我们每条SQL语句都加的话显然是很麻烦的,作为一个优雅的框架,当然有相应的解决办法 编写作用域 Laravel 应用默认并没有为作用域预定义文件夹...,所以你可以按照自己的喜好在 app 目录下创建 Scopes目录并实现接口(Illuminate\Database\Eloquent\Scope)的方法apply。...* * @param \Illuminate\Database\Eloquent\Builder $builder * @param \Illuminate\...php namespace App\Models; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\...1); } public function scopeType($query){ return $query->where('type','>', 0
\Database\Eloquent\Relations\HasMany 类的实例,Eloquent封装了一组类来处理各种关联,其中 HasMany是继承自 HasOneOrMany抽象类, 这也正印证了上面说的一对一是一种特殊的一对多关联...', '=', 'role_user.role_id') 然后 addWhereConstraints为其添加的where约束为: //假设User对象的id是1 $query->where('role_user.user_id...->where('users.country_id', '=', 1) 假设country_id是1 $this->query->where($this->getQualifiedFirstKeyName...->throughParent->getQualifiedDeletedAtColumn()); } } } 定义远层一对多关联会返回一个 \Illuminate\Database...$this->query->where('users.country_id', '=', 1) 假设country_id是1 对应的SQL查询是: SELECT * FROM posts INNER JOIN
Illuminate\Database\Query\Builder 调用方法去完成整个SQL。...$parameters); } 转发,调用的是 Illuminate\Database\Connection ,用户处理 table()方法,随后会通过 table() 方法指向 Illuminate\...,首先每个 Eloquent ORM 都需要继承父类 Illuminate\Database\Eloquent\Model 你大概会这样写 User::find(1) 父类是不存在这个方法的,它会通过...new Builder($query); } 最后我们到了 Illuminate\Database\Eloquent\Builder 文件下,这个类中涵盖了ORM的基本操作,例如find , findOrFail...如果你在代码用到了get方法,抱歉,这里没有,它依旧会通过__call 方法将你的请求转发到 Illuminate\Database\Query\Builder 类中 $this->query->{$method