数据库操作
几乎所有的应用程序都需要和数据库进行交互。Laravel 为此提供了一套非常简单易用的数据库交互方式。开发者可以使用原生 SQL、查询构造器 以及 Eloquent ORM 等方式与数据库交互
配置文件
数据库的配置文件在 config/database.php
文件中。你可以在这个文件中配置所有的数据库连接,并指定默认的数据库连接,该文件中的大部分配置都基于项目的环境变量,且提供了大部分 Laravel 所支持的数据库配置示例
执行原生 SQL 查询
一旦配置好数据库连接,你就可以使用 DB Facade
来执行查询。DB Facade
为每种类型的查询都提供了相应的方法:select
、update
、insert
、delete
以及 statement
执行 SELECT 查询
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\DB;
class UserController extends Controller
{
/**
* 展示用户列表
*
* @return \Illuminate\Http\Response
*/
public function index()
{
$users = DB::select('SELECT * FROM `users` WHERE `active` = ?', [1]);
return view('user.index', ['users' => $users]);
}
}
传递给 select
方法的第一个参数是一个原生 SQL
查询语句,而第二个参数则是需要绑定到查询中的参数值。通常,这些值用于约束 where
语句。使用参数绑定可以有效防止 SQL
注入。
select
方法将始终返回一个包含查询结果的数组。数组中的每个结果都会是一个代表数据库记录的 stdClass
对象
use Illuminate\Support\Facades\DB;
$users = DB::select('select * from users');
foreach ($users as $user) {
echo $user->name;
}
使用命名绑定
除了使用 ?
表示参数绑定外,也可以使用命名绑定的形式来执行一个查询
$results = DB::select('select * from users where id = :id', ['id' => 1]);
执行 INSERT 查询
你可以使用 DB Facade
的 insert
方法来执行 insert
语句。跟 select
方法一样,该方法的第一个和第二个参数分别是原生 SQL 语句和绑定的数据
use Illuminate\Support\Facades\DB;
DB::insert('insert into users (id, name) values (?, ?)', [1, 'Marc']);
执行 UPDATE 查询
update
方法用于更新数据库中现有的记录。该方法将会返回受到本次操作影响的记录行数
use Illuminate\Support\Facades\DB;
$affected = DB::update(
'update users set votes = 100 where name = ?',
['Anita']
);
执行 DELETE 语句
delete
方法用于从数据库中删除现有的记录。与 update
方法一样,返回受到本次操作影响的记录行数
use Illuminate\Support\Facades\DB;
$deleted = DB::delete('delete from users');
执行普通查询
部分数据库语句没有返回值。对于这些语句,你可以使用 DB Facade
的 statement
方法
DB::statement('drop table users');
数据库事务
你可以使用 DB Facade
的 transaction
方法在数据库事务中运行一系列操作。如果事务的闭包中出现了异常,Laravel 将会自动回滚该事务。如果该闭包执行成功,事务将会被自动提交。你完全不需要担心手动回滚或者提交的问题
use Illuminate\Support\Facades\DB;
DB::transaction(function () {
DB::update('update users set votes = 1');
DB::delete('delete from posts');
});
处理死锁
transaction
方法接受一个可选的第二参数,该参数用于表示事务在遇到死锁时尝试重新执行的次数。如果尝试指定次数后依然无法执行,将会抛出一个异常
use Illuminate\Support\Facades\DB;
DB::transaction(function () {
DB::update('update users set votes = 1');
DB::delete('delete from posts');
}, 5);
手动执行事务
如果您想手动开始事务并完全控制回滚和提交,则可以使用 beginTransaction
提供的方法 DB
use Illuminate\Support\Facades\DB;
DB::beginTransaction();
您可以通过以下 rollBack
方法回滚事务
DB::rollBack();
最后,您可以通过以下 commit
方法提交事务
DB::commit();
查询构造器
Laravel 的数据库查询构造器为创建和运行数据库查询提供了一个方便的接口。它可以用于支持大部分数据库操作,并与 Laravel 支持的所有数据库系统完美运行
查询所有数据
你可以使用 DB
facade 里的 table
方法来开始查询。table
方法为给定的表返回一个查询构造器实例,允许你在查询上链式调用更多的约束,最后使用 get
方法获取结果
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\DB;
class UserController extends Controller
{
/**
* 展示所有用户数据。
*
* @return \Illuminate\Http\Response
*/
public function index()
{
$users = DB::table('users')->get();
return view('user.index', ['users' => $users]);
}
}
get
方法返回一个包含 Illuminate\Support\Collection
的结果,其中每个结果都是 PHP StdClass
对象的一个实例。你可以访问字段作为对象的属性来访问每列的值
use Illuminate\Support\Facades\DB;
$users = DB::table('users')->get();
foreach ($users as $user) {
echo $user->name;
}
从数据表中获取单行或单列
如果你只需要从数据表中获取一行数据,你可以使用 first
方法。该方法返回一个 StdClass
对象
$user = DB::table('users')->where('name', 'John')->first();
return $user->email;
如果你不需要整行数据,则可以使用 value 方法从记录中获取单个值。该方法将直接返回该字段的值
$email = DB::table('users')->where('name', 'John')->value('email');
如果是通过 id
字段值获取一行数据,可以使用 find
方法
$user = DB::table('users')->find(3);
获取一列的值
use Illuminate\Support\Facades\DB;
$titles = DB::table('users')->pluck('title');
foreach ($titles as $title) {
echo $title;
}
聚合
查询构造器还提供了各种聚合方法,比如 count
,max
,min
,avg
,还有 sum
。你可以在构造查询后调用任何方法
use Illuminate\Support\Facades\DB;
// 查询数据总数
$users = DB::table('users')->count();
// 查询某个字段的最大值
$price = DB::table('orders')->max('price');
Select
如果不想从数据库表中获取所有列。那么可以使用 select 方法来查询指定的字段
use Illuminate\Support\Facades\DB;
$users = DB::table('users')
->select('name', 'email as user_email')
->get();
原生表达式
有时候可能需要在查询中使用原生表达式。可以使用 DB::raw
创建一个原生表达式
$users = DB::table('users')
->select(DB::raw('count(*) as user_count, status'))
->where('status', '<>', 1)
->groupBy('status')
->get();
Join 链表查询
Inner Join 内链表
use Illuminate\Support\Facades\DB;
$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 左链表
use Illuminate\Support\Facades\DB;
$users = DB::table('users')
->leftJoin('posts', 'users.id', '=', 'posts.user_id')
->get();
Right Join 右链表
use Illuminate\Support\Facades\DB;
$users = DB::table('users')
->rightJoin('posts', 'users.id', '=', 'posts.user_id')
->get();
Union 联合查询
查询构造器还提供了一种简洁的方式将两个或者多个查询联合在一起。例如,你可以先创建一个查询,然后使用 union
方法来连接更多的查询
use Illuminate\Support\Facades\DB;
$first = DB::table('users')
->whereNull('first_name');
$users = DB::table('users')
->whereNull('last_name')
->union($first)
->get();
where 条件查询
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\DB;
class UserController extends Controller
{
/**
* 展示用户列表
*
* @return \Illuminate\Http\Response
*/
public function index()
{
/*
第一个参数 => 字段名
第二个参数 => 操作符 如果把指定的值作为第二个参数时,laravel会默认使用 = 操作符
第三个参数 => 指定的值或者比较字段的值
*/
$users = DB::table('users')
->where('votes', '=', 100)
->where('age', '>', 35)
->get();
// votes 大于等于 100
$users = DB::table('users')
->where('votes', '>=', 100)
->get();
// votes 不等于 1000
$users = DB::table('users')
->where('votes', '<>', 100)
->get();
// 模糊查询name以T开头
$users = DB::table('users')
->where('name', 'like', 'T%')
->get();
// 条件数组
$users = DB::table('users')->where([
['status', '=', '1'],
['subscribed', '<>', '1'],
])->get();
}
}
orWhere
当链式调用多个 where
方法的时候,这些 where
语句将会被看成是 and
关系。另外,您也可以在查询语句中使用 orWhere 方法来表示 or 关系。orWhere
方法接收的参数和 where 方法接收的参数一样
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\DB;
class UserController extends Controller
{
public function index()
{
$users = DB::table('users')
->where('votes', '>', 100)
->orWhere('name', 'John')
->get();
// 如果您需要在括号内对 or 条件进行分组,那么可以传递一个闭包作为 orWhere 方法的第一个参数
$users = DB::table('users')
->where('votes', '>', 100)
->orWhere(function($query) {
$query->where('name', 'Abigail')
->where('votes', '>', 50);
})
->get();
}
}
其他 Where 语句
whereBetween / orWhereBetween
whereBetween
方法是用来验证字段的值是否在给定的两个值之间
$users = DB::table('users')
->whereBetween('votes', [1, 100])
->get();
whereNotBetween / orWhereNotBetween
whereNotBetween
方法是用来验证字段的值是否不在给定的两个值之间
$users = DB::table('users')
->whereNotBetween('votes', [1, 100])
->get();
whereIn / whereNotIn / orWhereIn / orWhereNotIn
whereIn
方法是用来验证一个字段的值是否在给定的数组中
$users = DB::table('users')
->whereIn('id', [1, 2, 3])
->get();
whereNotIn 方法是用来验证一个字段的值是否不在给定的数组中
$users = DB::table('users')
->whereNotIn('id', [1, 2, 3])
->get();
whereNull / whereNotNull / orWhereNull / orWhereNotNull
whereNull
方法是用来验证给定字段的值是否为 NULL:
$users = DB::table('users')
->whereNull('updated_at')
->get();
whereNotNull 方法是用来验证给定字段的值是否不为 NULL
$users = DB::table('users')
->whereNotNull('updated_at')
->get();
whereDate / whereMonth / whereDay / whereYear / whereTime
whereDate
方法是用来比较字段的值与给定的日期值是否相等 (年 - 月 - 日)
$users = DB::table('users')
->whereDate('created_at', '2016-12-31')
->get();
whereMonth
方法是用来比较字段的值与给定的月份是否相等(月)
$users = DB::table('users')
->whereMonth('created_at', '12')
->get();
whereDay
方法是用来比较字段的值与一个月中给定的日期是否相等 (日)
$users = DB::table('users')
->whereDay('created_at', '31')
->get();
whereYear
方法是用来比较字段的值与给定的年份是否相等(年)
$users = DB::table('users')
->whereYear('created_at', '2016')
->get();
whereTime
方法是用来比较字段的值与给定的时间是否相等(时:分: 秒)
$users = DB::table('users')
->whereTime('created_at', '=', '11:20:45')
->get();
Ordering, Grouping, Limit
orderBy
方法允许你通过给定字段对结果集进行排序。 orderBy
的第一个参数应该是你希望排序的字段,第二个参数控制排序的方向,可以是 asc
或 desc
$users = DB::table('users')
->orderBy('name', 'desc')
->get();
如果你需要使用多个字段进行排序,你可以多次引用 orderBy
$users = DB::table('users')
->orderBy('name', 'desc')
->orderBy('email', 'asc')
->get();
groupBy
和 having
方法用于将结果分组。 having
方法的使用与 where
方法十分相似
$users = DB::table('users')
->groupBy('account_id')
->get();
可以向 groupBy
方法传递多个参数,来对结果使用多个字段进行分组
$users = DB::table('users')
->groupBy('first_name', 'status')
->having('account_id', '>', 100)
->get();
limit
方法用于限制结果的返回数量
$users = DB::table('users')
->limit(5)
->get();
插入语句
查询构造器还提供了 insert
方法用于插入记录到数据库中。 insert
方法接收数组形式的字段名和字段值进行插入操作
DB::table('users')->insert([
'email' => 'kayla@example.com',
'votes' => 0
]);
你甚至可以将二维数组传递给 insert
方法,依次将多个记录插入到表中
自增 IDs
如果数据表有自增 ID ,使用 insertGetId
方法来插入记录可以返回 ID 值
$id = DB::table('users')->insertGetId(
['email' => 'john@example.com', 'votes' => 0]
);
更新语句
除了插入记录到数据库中,查询构造器也可以通过 update
方法更新已有的记录。 update
方法和 insert
方法一样,接受包含要更新的字段及值的数组
$affected = DB::table('users')
->where('id', 1)
->update(['votes' => 1]);
自增与自减
查询构造器还提供了方便的方法来递增或递减给定列的值。这两个方法都至少接受一个参数:要修改的列。可以提供第二个参数来指定列的递增或递减量
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
方法从表中删除记录。 在使用 delete
前,可以添加 where
子句来约束 delete
语法
DB::table('users')->delete();
DB::table('users')->where('votes', '>', 100)->delete();
调试
在绑定查询的时候,您可以使用 dd
或 dump
方法来输出查询绑定和 SQL。dd
方法将会显示调试信息并终止执行请求,而 dump
方法则会显示调试信息并允许请求继续执行
DB::table('users')->where('votes', '>', 100)->dd();
DB::table('users')->where('votes', '>', 100)->dump();