到目前为止,我们还没有真正的使用查询器,之前我们在DB facade上面调用了一些简单方法,让我们构建一些查询.
查询器将方法链接到一起从而构建查询,在链的末尾你可以使用一些方法(可能是get())来触发查询.
来让我们看一个简单的例子
Copy $usersOfType = DB :: table ( 'users' )
-> where ( 'type' , $type )
-> get () ;
这里,我们创建了查询,查询users表格,查询条件是type,然后我们执行查询获取结果
让我们看下可用的链式方法有哪些,这些方法我称之为约束方法,修改方法,条件方法和结束/返回方法
约束方法
这些方法进行约束查询,并返回较小的数据子集
select()
选择查询的列
Copy $emails = DB :: table ( 'contacts' )
-> select ( 'email' , 'email2 as second_email' )
-> get () ;
// Or
$emails = DB :: table ( 'contacts' )
-> select ( 'email' )
-> addSelect ( 'email2 as second_email' )
-> get () ;
where()
你可以使用WHERE限制返回内容的范围,默认情况下,where()接收3个参数,列,比较运算符,值
Copy $newContacts = DB :: table ( 'contact' )
-> where ( 'created_at' , '>' , now () -> subDay ())
-> get () ;
然而,如果第二个运算符是=,那么可以省略这个参数
$vipContacts = DB::table('contacts')->where('vip',true)->get();
如果要组合where()语句,你可以再另外一个后面追加或者传递数组
Copy $newVips = DB :: table ( 'contacts' )
-> where ( 'vip' , true )
-> where ( 'created_at' , '>' , now () -> subDay ()) ;
// Or
$newVips = DB :: table ( 'contacts' ) -> where ( [[ 'vip' , true ] ,
[ 'created_at' , '>' , now () -> subDay () ] ,
] ) ;
orWhere()
创建一个简单的OR WHERE
Copy $priorityContacts = DB :: table ( 'contacts' )
-> where ( 'vip' , true )
-> orWhere ( 'created_at' , '>' , now () -> subDay ())
-> get () ;
若要创建具有多个条件的更复杂OR WHERE语句,请给orWhere传递闭包
Copy $contacts = DB :: table ( 'contacts' )
-> where ( 'vip' , true )
-> orWhere ( function ($query) {
$query -> where ( 'created_at' , '>' , now () -> subDay ())
-> where ( 'trial' , false ) ;
} )
-> get () ;
多个where()和orWhere()混合调用
如果将orWhere()调用与多个where()调用结合使用,则需要非常小心,以确保查询按您认为的方式进行。这并不是因为Laravel有任何错误,而是因为像下面这样的查询可能无法实现您期望的结果:
Copy $canEdit = DB :: table ( 'users' )
-> where ( 'admin' , true )
-> orWhere ( 'plan' , 'premium' )
-> where ( 'is_plan_owner' , true )
-> get () ;
SELECT * FROM users
WHERE admin = 1
OR plan = 'premium'
AND is_plan_owner = 1 ;
如果要编写SQL,上面的示例中明确指出“if this or(this and this)”,则需要将闭包传递到orWhere()中调用:
Copy $canEdit = DB :: table ( 'users' )
-> where ( 'admin' , true )
-> orWhere ( function ($query) {
$query -> where ( 'plan' , 'premium' )
-> where ( 'is_plan_owner' , true ) ;
} )
-> get () ;
SELECT * FROM users
WHERE admin = 1
OR (plan = 'premium' AND is_plan_owner = 1 );
whereBetween(colName, [low, high])
允许查询返回介于两个值之间的行(包含两个值)
Copy $mediumDrinks = DB :: table ( 'drinks' )
-> whereBetween ( 'size' , [ 6 , 12 ] )
-> get () ;
同样适用于whereNotBetween(),但是结果会反转
whereIn(colName, [1, 2, 3])
返回列表范围的行
Copy $closeBy = DB :: table ( 'contacts' )
-> whereIn ( 'state' , [ 'FL' , 'GA' , 'AL' ] )
-> get () ;
同样适用于whereNotIn(),结果会反转
whereNull(colName) 和 whereNotNull(colName)
查询NULL或者Not NULL
whereRaw()
可以给where传递原生非转义字符串
Copy $goofs = DB :: table ( 'contacts' ) -> whereRaw ( 'id = 12345' ) -> get ()
小心SQL注入!
传递给whereraw()的任何SQL查询都不会被转义。小心使用此方法;这是应用程序中SQL注入攻击的主要机会。
whereExists()
允许你传递子查询,并至少返回一条记录,假设你想获取至少有一条留言的用户
Copy $commenters = DB :: table ( 'users' )
-> whereExists ( function ($query) {
$query -> select ( 'id' )
-> from ( 'comments' )
-> whereRaw ( 'comments.user_id = users.id' ) ;
} )
-> get () ;
distinct()
返回与其他记录比较后的记录,通常与select()搭配使用,因为如果你使用了主键,则不会有重复的记录
Copy $lastNames = DB :: table ( 'contacts' ) -> select ( 'city' ) -> distinct () -> get () ;
修改方法
这些方法更改了查询结果,不仅仅是限制了结果
orderBy(colName, direction)
查询结果排序,第二个参数可以是asc(默认值,升序)或desc(降序)
Copy $contacts = DB :: table ( 'contacts' )
-> orderBy ( 'last_name' , 'asc' )
-> get () ;
groupBy() 和 having() 或者 havingRaw()
将结果按列分组。或者,having()和havingraw()允许您根据组的属性筛选结果。例如,您可以只查找人口至少为30人的城市
Copy $populousCities = DB :: table ( 'contacts' )
-> groupBy ( 'city' )
-> havingRaw ( 'count(contact_id) > 30' )
-> get () ;
skip()和take()
最常用于分页,它们允许您定义返回多少行,以及在开始返回之前跳过多少行,就像分页系统中的页码和页面大小一样。
Copy // returns rows 31-40
$page4 = DB :: table ( 'contacts' ) -> skip ( 30 ) -> take ( 10 ) -> get () ;
latest(colName)和oldest(colName)
通过传递的列进行升序(oldest)或者降序(latest)排列,如果没传值则按照created_at排列
inRandomOrder()
随机排序结果
条件方法
Laravel 5.2以及更高版本有两个方法,可以通过传递值的布尔状态对内容进行条件判断(需要传递个闭包)
when()
第一个参数传"真"则会执行闭包内的查询,第一个参数传"假"那么什么都不做,注意第一个参数应该是布尔(true,false),一个可选值($status,从用户输入中提取,并默认为null)或返回一个值的闭包,重要的是要返回true或者false,例如
Copy $status = request ( 'status' ) ; // Defaults to null if not set
$posts = DB :: table ( 'posts' )
-> when ( $status , function ($query) use ($status) {
return $query -> where ( 'status' , $status ) ; } )
-> get () ;
$posts = DB :: table ( 'posts' )
-> when ( $ignoreDrafts , function ($query) {
return $query -> where ( 'draft' , false ) ;
} ) -> get () ;
您还可以传递第三个参数,即另一个闭包,只有在第一个参数false 时才会应用该闭包。
unless()
与when相反,如果第一个参数为false,则会运行第二个闭包
结束/返回方法
终止查询链并触发SQL查询,如果在查询链没有调用这些方法,那么你将得到一个查询器实例,如果在查询链上执行了这些方法,那么你将得到具体的记录.
get()
获取查询器的所有结果
Copy $contacts = DB :: table ( 'contacts' ) -> get () ;
$vipContacts = DB :: table ( 'contacts' ) -> where ( 'vip' , true ) -> get () ;
first()和firstOrFail()
获取第一条结果,就像Like,但是它只返回一条
Copy $newestContact = DB :: table ( 'contacts' )
-> orderBy ( 'created_at' , 'desc' )
-> first () ;
如果没有结果,first()将自动失败,而firstorfail()将引发异常。
如果将列名数组传递给任一方法,它将只返回这些列的数据,而不是所有列的数据。
find(id)和findOrFail(id)
与first()类似,传递一个与主键对应的ID进行查找,如果ID对应的不存在,find会失败,而findOrFail会异常
Copy $contactFive = DB :: table ( 'contacts' ) -> find ( 5 ) ;
value()
从第一行提取单个字段,像first()但是你只想获取单个列
Copy $newestContactEmail = DB :: table ( 'contacts' )
-> orderBy ( 'created_at' , 'desc' )
-> value ( 'email' ) ;
count()
返回所有匹配结果的计数
Copy $countVips = DB :: table ( 'contacts' )
-> where ( 'vip' , true )
-> count () ;
min()和max()
返回特定列的最小或最大值
Copy $highestCost = DB :: table ( 'orders' ) -> max ( 'amount' ) ;
sum()和avg()
返回特定列中所有值的总和或平均值
Copy $averageCost = DB :: table ( 'orders' )
-> where ( 'status' , 'completed' )
-> avg ( 'amount' ) ;
使用DB::raw在查询器中写原生查询
之前看到过一些方法用于原生语法-例如select有一个对应的selectRaw方法可以给其传递字符串用于查询,然后放到WHERE语法后
当然你也可以调用DB::raw()来实现相同的结果
Copy $contacts = DB :: table ( 'contacts' )
-> select ( DB :: raw ( '*, (score * 100) AS integer_score' ))
-> get () ;
连接
定义联合查询有时有点困难,但是Laravel的查询器做的比较好,如例子
Copy $users = DB :: table ( 'users' )
-> join ( 'contacts' , 'users.id' , '=' , 'contacts.user_id' )
-> select ( 'users.*' , 'contacts.name' , 'contacts.status' )
-> get () ;
join()创建了一个连接查询,你可以用链式写法组合多个join,或者使用leftJoin来创建左连接
最后,你也可以给join传递闭包创建更复杂的连接查询
Copy DB :: table ( 'users' )
-> join ( 'contacts' , function ($join) {
$join
-> on ( 'users.id' , '=' , 'contacts.user_id' )
-> orOn ( 'users.id' , '=' , 'contacts.proxy_user_id' ) ;
} ) -> get () ;
组合
通过首先创建两个查询,然后使用union()或unionall()方法,可以将它们联合起来(将它们的结果组合成一个结果)
Copy $first = DB :: table ( 'contacts' )
-> whereNull ( 'first_name' ) ;
$contacts = DB :: table ( 'contacts' )
-> whereNull ( 'last_name' )
-> union ( $first )
-> get () ;
插入
插入非常简单,传递一个数组插入单条记录,传递数组的数组,插入多条记录,使用insertGetId()替代insert()可以自动生成主键
Copy $id = DB :: table ( 'contacts' ) -> insertGetId ( [
'name' => 'Abe Thomas' ,
'email' => 'athomas1987@gmail.com' ,
] ) ;
DB :: table ( 'contacts' ) -> insert ( [
[ 'name' => 'Tamika Johnson' , 'email' => 'tamikaj@gmail.com' ] ,
[ 'name' => 'Jim Patterson' , 'email' => 'james.patterson@hotmail.com' ] ,
] ) ;
更新
更新也非常简单,创建更新查询只需要将数组传递给它
Copy DB :: table ( 'contacts' )
-> where ( 'points' , '>' , 100 )
-> update ( [ 'status' => 'vip' ] ) ;
还可以使用increment()和decrement()方法快速增加和减少列。第一个参数是列名,第二个(可选)是要递增/递减的数字
Copy DB :: table ( 'contacts' ) -> increment ( 'tokens' , 5 ) ;
DB :: table ( 'contacts' ) -> decrement ( 'tokens' ) ;
删除
删除更简单,在查询结尾调用delete()即可
Copy DB :: table ( 'users' )
-> where ( 'last_login' , '<' , now () -> subYear ())
-> delete () ;
您还可以截断表,该表将删除每一行并重置自增ID。
JSON操作
如果你有一个JSON列,你可以使用箭头语法来更新或选择JSON结构
Copy // Select all records where the "isAdmin" property of the "options"
// JSON column is set to true
DB :: table ( 'users' ) -> where ( 'options->isAdmin' , true ) -> get () ;
// Update all records, setting the "verified" property
// of the "options" JSON column to true
DB :: table ( 'users' ) -> update ( [ 'options->isVerified' , true ] ) ;