* * * * *
[TOC]
## 簡介
Laravel 能使用原生 SQL、[查詢構造器](http://www.hmoore.net/tonyyu/laravel_5_6/786261)?和?[Eloquent ORM](http://www.hmoore.net/tonyyu/laravel_5_6/786272)?在各種數據庫后臺與數據庫進行非常簡單的交互。當前 Laravel 支持四種數據庫:
* MySQL
* Postgres
* SQLite
* SQL Server
### 配置
數據庫的配置文件放置在?`config/database.php`?文件中,你可以在此定義所有的數據庫連接,并指定默認使用的連接。此文件內提供了大部分 Laravel 能支持的數據庫配置示例。
默認情況下,Laravel 的示例?[環境配置](http://www.hmoore.net/tonyyu/laravel_5_6/786051#_6)?使用了?[Laravel Homestead](http://www.hmoore.net/tonyyu/laravel_5_6/786195)(這是一種小型虛擬機,能讓你很方便地在本地進行 Laravel 的開發)。你可以根據本地數據庫的需要修改這個配置。
#### SQLite 配置
使用類似?`touch database/database.sqlite`?之類命令創建一個新的 SQLite 數據庫之后,可以使用數據庫的絕對路徑配置環境變量來指向這個新創建的數據庫:
~~~
DB_CONNECTION=sqlite
DB_DATABASE=/absolute/path/to/database.sqlite
~~~
### 讀 & 寫連接
有時候你希望 SELECT 語句使用一個數據庫連接,而 INSERT、 UPDATE 和 DELETE 語句使用另一個數據庫連接。在 Laravel 中這就像小菜一碟,無論你是使用原生查詢,查詢構造器 或者 Eloquent ORM 它都能輕松實現。
想了解數據庫讀寫分離如何配置, 讓我們看看這個例子:
~~~
'mysql' => [
'read' => [
'host' => '192.168.1.1',
],
'write' => [
'host' => '196.168.1.2'
],
'sticky' => true,
'driver' => 'mysql',
'database' => 'database',
'username' => 'root',
'password' => '',
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
],
~~~
注意在上邊的例子中,配置數組中增加了 3 個鍵:?`read`,`write`?和?`sticky`。?`read`?和?`write`?都包含一個鍵為?`host`?的數組。而?`read`?和?`write`?的其它數據庫配置都在鍵為?`mysql`?的主數組中:
如果你希望重寫主數組的某個配置項,只需要將它放入?`read`?和?`write`?的數組中即可。 所以,這個例子中:?`192.168.1.1`?將用作「讀」連接的主機, 而?`192.168.1.2`?將作為「寫」連接的主機。這兩個連接會共享?`mysql`主數組的各項配置,如數據庫的憑據,前綴,字符編碼 等。
#### `sticky`?選項
`sticky`?是一個?*可選*?值,它可用于立即讀取在當前請求周期內已寫入數據庫的記錄。若?`sticky`?被啟用,并且當前請求周期內執行過「寫」操作,那么任何「讀」操作都將使用「寫」連接。這樣可確保同一周期內寫入的數據在同一周期內都可以被立即讀取。它是否啟用,取決于應用程序的需求。
### 使用多個數據庫連接
當使用多個數據庫連接時,你可以通過?`DB`?facade 的?`connection`?方法訪問每一個連接。將?`name`?作為?`connection`?方法的參數傳遞,即可使用?`config/database.php`?配置文件中對應名稱的連接:
~~~
$users = DB::connection('foo')->select(...);
~~~
你也可以在一個連接的實例上使用?`getPdo`?方法 訪問底層的 PDO 實例:
~~~
$pdo = DB::connection()->getPdo();
~~~
## 運行原生 SQL 查詢
配置好數據庫連接后,可以使用?`DB`?Facade 運行查詢。?`DB`?Facade 為每種類型的查詢提供了方法:?`select`?、?`update`?、?`insert`?、?`delete`?和?`statement`。
#### 運行 Select 查詢
你可以使用?`DB`?Facade 的?`select`?方法來運行基礎的查詢語句:
~~~
<?php
namespace App\Http\Controllers;
use Illuminate\Support\Facades\DB;
use App\Http\Controllers\Controller;
class UserController extends Controller
{
/**
* 顯示所有應用程序的用戶列表
*
* @return 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`?對象,可以像下面這樣訪問結果值
~~~
foreach ($users as $user) {
echo $user->name;
}
~~~
#### 使用命名綁定
除了使用?`?`?來表示參數綁定外,你也可以使用命名綁定來執行一個查詢:
~~~
$results = DB::select('select * from users where id = :id', ['id' => 1]);
~~~
#### 運行插入語句
可以使用?`DB`?Facade 的?`insert`?方法來執行?`insert`?語句。與?`select`?一樣,該方法將原生 SQL 查詢作為其第一個參數,并將綁定數據作為第二個參數:
~~~
DB::insert('insert into users (id, name) values (?, ?)', [1, 'Dayle']);
~~~
#### 運行更新語句
`update`?方法用于更新數據庫中現有的記錄。該方法返回受該語句影響的行數:
~~~
$affected = DB::update('update users set votes = 100 where name = ?', ['John']);
~~~
#### 運行刪除語句
`delete`?方法用于從數據庫中刪除記錄。與?`update`?一樣,返回受該語句影響的行數:
~~~
$deleted = DB::delete('delete from users');
~~~
#### 運行普通語句
有些數據庫語句不會有任何返回值。對于這些語句,你可以使用?`DB`?Facade 的?`statement`?方法來運行:
~~~
DB::statement('drop table users');
~~~
### 監聽查詢事件
如果你想監控程序執行的每一個 SQL 查詢,你可以使用?`listen`?方法。這個方法對于記錄查詢或調試非常有用。你可以在?[服務提供器](http://www.hmoore.net/tonyyu/laravel_5_6/786057)?中注冊你的查詢監聽器:
~~~
<?php
namespace App\Providers;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* 啟動應用服務
*
* @return void
*/
public function boot()
{
DB::listen(function ($query) {
// $query->sql
// $query->bindings
// $query->time
});
}
/**
* 注冊服務提供器
*
* @return void
*/
public function register()
{
//
}
}
~~~
## 數據庫事務
你可以使用?`DB`?facade 的?`transaction`?方法在數據庫事務中運行一組操作。如果在事務?`Closure`?中出現一個異常,那么事務將回滾。如果?`Closure`?執行成功,事務將自動提交。你不需要擔心在使用?`transaction`?方法時手動回滾或提交:
~~~
DB::transaction(function () {
DB::table('users')->update(['votes' => 1]);
DB::table('posts')->delete();
});
~~~
#### 處理死鎖
`transaction`?方法接受一個可選的第二參數,該參數表示事務發生死鎖時重試的次數。 一旦這些嘗試用盡,就會拋出一個異常:
~~~
DB::transaction(function () {
DB::table('users')->update(['votes' => 1]);
DB::table('posts')->delete();
}, 5);
~~~
#### 手動使用事務
如果您想要手工開始一個事務,并且對回滾和提交有完全的控制,那么您可以在?`DB`?facade 上使用?`beginTransaction`?方法:
~~~
DB::beginTransaction();
~~~
你可以使用?`rollBack`?方法回滾事務:
~~~
DB::rollBack();
~~~
最后,你可以使用?`commit`?方法提交事務:
~~~
DB::commit();
~~~
> {tip}?`DB`?facade 的事務方法同樣適用于?[查詢構造器](http://www.hmoore.net/tonyyu/laravel_5_6/786261)?和?[Eloquent ORM](http://www.hmoore.net/tonyyu/laravel_5_6/786272)。
- 前言
- 翻譯說明
- 發行說明
- 升級指南
- 貢獻導引
- 入門指南
- 安裝
- 配置信息
- 文件夾結構
- Homestead
- Valet
- 部署
- 核心架構
- 請求周期
- 服務容器
- 服務提供者
- Facades
- Contracts
- 基礎功能
- 路由
- 中間件
- CSRF 保護
- 控制器
- 請求
- 響應
- 視圖
- URL
- Session
- 表單驗證
- 錯誤
- 日志
- 前端開發
- Blade 模板
- 本地化
- 前端指南
- 編輯資源 Mix
- 安全相關
- 用戶認證
- Passport OAuth 認證
- 用戶授權
- 加密解密
- 哈希
- 重置密碼
- 綜合話題
- Artisan 命令行
- 廣播系統
- 緩存系統
- 集合
- 事件系統
- 文件存儲
- 輔助函數
- 郵件發送
- 消息通知
- 擴展包開發
- 隊列
- 任務調度
- 數據庫
- 快速入門
- 查詢構造器
- 分頁
- 數據庫遷移
- 數據填充
- Redis
- Eloquent ORM
- 快速入門
- 模型關聯
- Eloquent 集合
- 修改器
- API 資源
- 序列化
- 測試相關
- 快速入門
- HTTP 測試
- 瀏覽器測試 Dusk
- 數據庫測試
- 測試模擬器
- 官方擴展包
- Cashier 交易工具包
- Envoy 部署工具
- Horizon
- Scout 全文搜索
- Socialite 社會化登錄