laravel 基础教程 —— 查询生成器

数据库:查询生成器

简介

Laravel
的数据库查询生成器提供了一种便民流利的接口来打造和运作数据库查询。它可以用来在拔取中提供执行半数以上的数据库操作,并且它可以在颇具协助的数据库系统中展开合作。

留神:Laravel 的查询生成器使用了 PDO 参数绑定来针对可能的 SQL
注入攻击。所以那里不必要手动的去清洗作为绑定所传递的字符串。

搜索结果

从表中检索所有的行

在上马流畅的执行查询此前,你须要先利用 DB 假面的 table 方法,table
方法会再次回到一个给定表的查询生成器实例,那允许你链式添加三种询问约束,并最终拿到结果。大家来看一个演示,大家只是调用
get 来获取具有的表中的笔录:

<?php

namespace App\Http\Controllers;

use DB;
use App\Http\Controllers\Controller;

class UserController extends Controller
{
  /**
   * Show a list of all of the application's users.
   *
   * @return Response
   */
   public function index()
   {
     $users = DB::table('users')->get();

     return view('user.index', ['users' => $users]);
   }
}

似乎原生的询问同一,get 方法会重返一个 array ,其每一项结果都是一个
StdClass PHP 类的对象。你可以经过其属性来访问每一列的值:

foreach ($users as $user) {
  echo $user->name;
}

从表中检索一个独自的行仍旧列

如果您只必要从数量表中检索出单身的一行,你可以选用 first
方法,该方法会再次来到一个单独的 StdClass 对象:

$user = DB::table('users')->where('name', 'John')->first();

echo $user->name;

若果您仍旧不要求一个完好无缺的行,那么你可以经过应用 value
方法从记录中拿走一个可相信的列的值。该方法会直接再次回到列中的值:

$email = DB::table('users')->where('name', 'John')->value('email');

对结果进行分块

假定你与表中的数千条记下同盟,你可以考虑选拔 chunk
方法,该办法一遍会从结果中找找出一小块。并且将那每一块放进闭包中提必要进度。该格局对于编写
Artisan
命令来合作数千条的记录格外管用。比如,让我们将全方位用户表分块成每一次 100
条来办事:

DB::table('users')->orderBy('id')->chunk(100, function ($users) {
  foreach ($users as $user) {
    //
  } 
});

你可以通过在 Closure 中返回 false 来截至进一步的拍卖块的操作:

DB::table('users')->orderBy('id')->chunk(100, function ($users) {
  // Process the records...

  return false; 
});

探寻表列的值

假设你指望取得一个数组来含有一个列中所有的值,你可以选用 pluck
方法,在这一个事例中,大家将取得具有的角色名称:

$titles = DB::table('roles')->pluck('title');

foreach($titles as $title) {
  echo $title;
}

你也可以为所再次回到的数组指定自定义的键:

$roles = DB::table('roles')->pluck('title', 'name');

foreach ($roles as $name => $title) {
  echo $title;
}

合计

询问生成器也提供了种种协商的方法。比如 countmaxminavg,和
sum。你可以在查询创设后调用那一个方法:

$users = DB::table('users')->count();

$price = DB::table('orders')->max('price');

当然,你可以结合其他约束来创设你的查询:

$price = DB::table('orders')
           ->where('finalized', 1)
           ->avg('price');

选择

指定一个抉择约束

自然,你不会接连想要从数据库中取得具有的列。你可以选拔 select
方法来指定一个自定义的 select 约束到查询:

$users = DB::table('users')->select('name', 'email as user_email')->get();

distinct 方法允许你强迫查询重临一个不另行的结果:

$users = DB::table('users')->distinct()->get();

设若你已经得到了查询生成器的实例,并且你想要在已经添加过接纳约束的实例中添加额外一列的探寻,你可以采取
addSelect 方法:

$query = DB::table('users')->select('name');

$users = $query->addSelect('age')->get();

原生的表达式

奇迹,你恐怕须求在查询时行使原生的表达式,那么些表明式会以字符串的措施注入到查询中,所以你应该小心的不用构造出其余的
SQL 注入点。你可以采纳 DB::raw 方法来布局一个原生的表达式:

$users = DB::table('users')
           ->select(DB::raw('count(*) as user_count, status'))
           ->where('status', '<>', 1)
           ->groupBy('status')
           ->get();

Joins

内三番五次申明

询问生成器也足以用来编排 join 注明。为了履行一个基础的 SQL
内接连,你可以在查询生成器中运用 join 方法。join
方法所收受的第二个参数应该是你需求参预的表的称号,而其他的参数则是对进入提供约束。当然,似乎您所看到的,你可以在一个查询中参预七个表:

$users = DB::table('users')
           ->join('contacts', 'users.id', '=', 'contacts.user_id')
           ->join('orders', 'users.id', '=', 'orders.user_id')
           ->select('users.*', 'contacts.phone', 'orders.price')
           ->get();

左连接注脚

如果您必要执行 left join 来代替 inner join,你可以应用 leftJoin
方法,leftJoin 方法具有和 join 方法同样的施用方式:

$users = DB::table('users')
           ->leftJoin('posts', 'users.id', '=', 'posts.user_id')
           ->get();

接力连接表明

您可以拔取 crossJoin 方法来推行一个接力的连天操作,你必要为
crossJoin
提供一个你想要交叉连接的表名。交叉连接会生成第四个表和加入的表的笛Carl积:

$users = DB::table('sizes')
           ->crossJoin('colours')
           ->get();

高级的 Join 声明

你也足以指定更尖端的 join 约束。你可以传递一个 Closure 作为 join
方法的首个参数。Closure 会接收一个 JoinClause
对象并且该对象允许你指定 join 约束:

DB::table('users')
  ->join('contacts', function ($join) {
    $join->on('users.id', '=', 'contacts.user_id')->orOn(...); 
  })
  ->get();

假如你喜爱在 joins 中应用 where 风格约束,那么您可以在 join 上接纳
whereorWhere 方法。该方法会比较列的值而代表直接相比两列:

DB::table('users')
  ->join('contacts', function ($join) {
    $join->on('users.id', '=', 'contacts.user_id')
      ->where('contacts.user_id', '>', 5);
  })
  ->get();

Unions(联合)

询问生成器也提供了一种高效的不二法门来将八个查询联合起来。比如,你能够营造一个初步化的询问,然后利用
union 方法来将其与后来的查询联合起来:

$first = DB::table('users')
           ->whereNull('first_name');

$users = DB::table('users')
           ->whereNull('last_name')
           ->union($first)
           ->get();

unionAll 方法也是可用的,并且它与 union 方法具有同样的签证形式。

Where 子句

简单的 Where 子句

你可以在询问生成器中行使 where 方法来在询问中添加 where
约束。超过一半基础的 where
调用都亟待提供多少个参数,第二个参数是列的名号,第一个参数是相比操作的章程,第多个参数则是针对列所需求评估的值。

例如,那里的查询用来验证 “votes” 列的值等于 100:

$users = DB::table('users')->where('votes', '=', 100)->get();

为了有利于,你可以直接传送必要比较的值到第三个参数来注解列值与给定值相等的论断:

$users = DB::table('users')->where('votes', 100)->get();

理所当然,你也得以在使用 where 子句时采取其它的操作符:

$users = DB::table('users')
           ->where('votes', '>=', 100)
           ->get();

$users = DB::table('users')
           ->where('votes', '<>', 100)
           ->get();

$users = DB::table('users')
           ->where('name', 'like', 'T%')
           ->get();

您也足以传递一个数组所结合的尺码到 where 方法中:

$users = DB::table('users')->where([
  [status', '1'],
  ['subscribed','<>', '1'],
])->get();

或声明

您可以将 where 约束连在一起,以及添加 or 子句到查询中。orWhere
方法接收和 where 方法同样的参数:

$users = DB::table('users')
           ->where('votes', '>', 100)
           ->orWhere('name', 'John')
           ->get();

其它 Where 子句

whereBetween

whereBetween 方法确定列的值是或不是在三个给定值之间:

$users = DB::table('users')
           ->whereBetween('votes', [1, 100])->get();

whereNotBetween

whereNotBetween 方法确定列的值应该不在所给定值区间内:

$users = DB::table('users')
           ->whereNotBetween('votes', [1, 100])
           ->get();

whereIn / whereNotIn

whereIn 方法验证给定的列的值应该是给定的数组值中之一:

$users = DB::table('users')
           ->whereIn('id', [1, 2, 3])
           ->get();

whereNotIn 方法验证所给定的列的值应该不在给定的数组中:

$users = DB::table('users')
           ->whereNotIn('id', [1, 2, 3])
           ->get();

whereNull / whereNotNull

whereNull 方法验证所给定列的值应该是 NULL:

$users = DB::table('users')
           ->whereNull('updated_at')
           ->get();

whereNotNull 方法验证所给定的列的值不该为 NULL:

$users = DB::('users')
           ->whereNotNull('updated_at')
           ->get();

whereColumn

whereColumn 方法可以用来判定两列的值是还是不是等于:

$users = DB::table('users')
           ->whereColumn('first_name', 'last_name');

您也得以传递一个相比较符到方法中:

$users = DB::table('users')
           ->whereColumn('updated_at', '>', 'created_at');

whereColumn 方法可以接到一个暗含了五个限制条件的数组。那些原则会被采纳
add 判定操作:

$users = DB::table('users')
           ->whereColumn([
             ['first_name', 'last_name'],
             ['updated_at', '>', 'created_at']
           ]);

高级 Where 子句

参数分组

突发性你需求营造一些尤为高档的 where 子句,比如,“where
exists”或者嵌套的参数分组。Laravel
的询问生成器也能很好的拍卖那么些。让大家来看一个分组括号内约束的事例:

DB::table('users')
  ->where('name', '=', 'John')
  ->orWhere(function ($query) {
    $query->where('votes', '>', 100)
          ->where('title', '<>', 'Admin');
  })
  ->get();

就好像您所看到的,传递一个 ClosureorWhere
方法来教导查询生成器起首一个组约束。Closure
会接收一个查询生成器的实例,那样您就足以在括号组内营造一些封锁。下边的示范将会转变下边的
SQL:

select * from users where name = 'John' or (votes > 100 and title <> 'Admin')

Exists 声明

whereExists 方法允许你编写 where exists SQL 子句。whereExists
方法接收一个 Closure
参数,这一个闭包会接收一个查询生成器实例,那允许你在 “exists”
子句中去营造查询:

DB::table('users')
  ->whereExists(function ($query) {
    $query->select(DB::raw(1))
      ->from('orders')
      ->whereRaw('orders.user_id = users.id');
  })
  ->get();

地方的询问将转变上面的 SQL:

select * from users
where exists (
  select 1 from orders where orders.user_id = users.id
)

JSON where 子句

Laravel 支持对辅助 JSON 列类型的数据库查询 JSON
类型的列。如今,那只含有在 MySQL 5.7 和 Postgres。你须求选用 ->
操作符来查询 JSON 列:

$users = DB::table('users')
           ->where('options->language', 'en')
           ->get();

$users = DB::table('users')
           ->where('preferences->dining->meal', 'salad')
           ->get();

排序,分组,限制 & 位移

orderBy

orderBy 方法允许你对给定列的查询结果开展排序。orderBy
所接受的首先个参数应该是你指望举行排序的列,而第三个参数应该是您说了算展开排序的矛头,它们应该是
asc 或者 desc:

$users = DB::table('users')
           ->orderBy('name', 'desc')
           ->get();

inRandomOrder

inRandomOrder
方法可以用来对查询的结果开展任意排序。比如,你可以使用这么些方法来随便的收获用户:

$randomUser = DB::table('users')
                ->inRandomOrder()
                ->first();

groupBy / having / havingRaw

groupByhaving 方法可以用来对查询结果开展分组。having
方法具有和 where 方法同样的签证:

$users = DB::table('users')
           ->groupBy('account_id')
           ->having('account_id', '>', 100)
           ->get();

havingRaw 方法可以用来在 having
子句中利用原生的字符串值,比如,大家得以找到所有销售额当先 $2,500
的机关:

$users = DB::table('orders')
           ->select('department', DB::raw('SUM(price) as total_sales'))
           ->groupBy('department')
           ->havingRaw('SUM(price) > 2500')
           ->get();

skip / take

您可以行使 takeskip
方法来界定查询所重返结果的数据和在查询中跳过早晚的数量(offset):

$users = DB::table('users')->skip(10)->take(5)->get();

规则语句

偶尔你或许希望唯有当一些条件达标时才去添加一些询问到语句中。又或者您想要在唯有进入的请求数据中包括指定的字段时才会咬定在
where 子句中开展进入。你可以采取 when 方法来完结这几个:

$role = $request->input('role');

$users = DB::table('users')
           ->where($role, function ($query) use ($role) {
             return $query->where('role_id', $role);
           })
           ->get();

when 方法只享有给定的首个参数为 true
时才会履行给定的闭包。假设第二个参数是 false,那么闭包将不会被实施。

插入

查询生成器也为插入记录到数据库中提供了 insert 方法。insert
方法可以接受列名所结合的键值对数组作为参数:

DB::table('users')->insert(
  ['email' => 'john@example.com', 'votes' => 0]
);

您也足以在一回调用 insert
方法时添加多条记下到数据库中,你须要传递一个嵌套的数组,数组中的每一个数组都意味了数据库中的一行:

DB::table('users')->insert([
  ['email' => 'taylor@example.com', 'votes' => 0],
  ['email' => 'dayle@example.com', 'votes' => 0]
]);

自行递增的 IDs

要是挑中留存活动递增的 id,你可以运用 insertGetId
方法来插入记录的同时得到 ID:

$id = DB::table('users')->insertGetId(
  ['email' => 'john@example.com', 'votes' => 0]
);

注意:当使用 PostgreSQL 时,insertGetId 方法期望自增的列名为
id。若是您想要检索的 ID 是一个别的列名,你须要传递列名到
insertGetId 方法的第一个参数。

更新

自然,除了新增记录之外,查询生成器也提供了为数据库中留存的记录更新的
update 方法。update 方法像 insert
方法一致,接收一个键值对所构成的数组来进展列值的立异。你可以在动用
update 查询时行使 where 子句:

DB::table('users')
  ->where('id', 1)
  ->update(['votes' => 1]);

增量 / 递减

询问生成器也提供一些惠及的措施来对列的值举办增量和递减。那只是一种高效的不二法门,用来提供比手动写入
update 语句更具表现力和精简的接口。

那二种艺术都吸收最少一个参数:待修改的列名,首个参数是一个可选的参数,它用来决定递增或者递减的多寡:

DB::table('users')->increment('votes');

DB::table('users')->increment('votes', 5);

DB::table('users')->decrement('votes');

DB::table('users')->decrement('votes', 5);

您也得以指定同时革新额外的列:

DB::table('users')->increment('votes', 1, ['name' => 'John']);

删除

自然,查询生成器也提供了从数据库中剔除记录的 delete 方法:

DB::table('users')->delete();

您可以在调用 delete 方法在此之前增加一些 where 子句:

DB::table('users')->where('votes', '>', 100)->delete();

设若您愿意消除整个表的数码,你可以使用 truncate
方法,它将解除所有的行并且重置自增的 ID 到 0:

DB::table('users')->truncate();

悲观锁

询问生成器也提供了有的措施来增援您在 select
注脚中落到实处“悲观锁”。你可以在查询中使用 sharedLock
方法来运转“共享锁”。共享锁可以确保所选定的行在工作提交前不会被涂改:

DB::table('users')->where('votes', '>', 100)->sharedLock()->get();

别的,你也可以选拔 lockForUpdate
方法。更新锁可以幸免行被修改或者被另统计享锁所选中:

DB::table('users')->where('votes', '>', 100)->lockForUpdate()->get();
网站地图xml地图