快速入門(mén)
快速入門(mén)
數(shù)據(jù)庫(kù):入門(mén)
簡(jiǎn)介
Laravel 能使用原生 SQL、流暢的查詢構(gòu)造器 和 Eloquent ORM 在各種數(shù)據(jù)庫(kù)后臺(tái)與數(shù)據(jù)庫(kù)進(jìn)行非常簡(jiǎn)單的交互。當(dāng)前 Laravel 支持四種數(shù)據(jù)庫(kù):
- MySQL
- PostgreSQL
- SQLite
- SQL Server
配置
數(shù)據(jù)庫(kù)的配置文件放置在 config/database.php
文件中,你可以在此定義所有的數(shù)據(jù)庫(kù)連接,并指定默認(rèn)使用的連接。此文件內(nèi)提供了大部分 Laravel 能支持的數(shù)據(jù)庫(kù)配置示例。
默認(rèn)情況下,Laravel 的示例 環(huán)境配置 使用了 Laravel Homestead(這是一種小型虛擬機(jī),能讓你很方便地在本地進(jìn)行 Laravel 的開(kāi)發(fā))。你可以根據(jù)本地?cái)?shù)據(jù)庫(kù)的需要修改這個(gè)配置。
SQLite 配置
使用類似 touch database/database.sqlite
之類命令創(chuàng)建一個(gè)新的 SQLite 數(shù)據(jù)庫(kù)之后,可以使用數(shù)據(jù)庫(kù)的絕對(duì)路徑配置環(huán)境變量來(lái)指向這個(gè)新創(chuàng)建的數(shù)據(jù)庫(kù):
DB_CONNECTION=sqliteDB_DATABASE=/absolute/path/to/database.sqlite
如果要開(kāi)啟 SQLite 連接的外鍵約束,您應(yīng)該將 foreign_key_constraints
添加到 config / database.php
配置文件中:
'sqlite' => [ // ... 'foreign_key_constraints' => true, ],
讀寫(xiě)分離
有時(shí)候你希望 SELECT 語(yǔ)句使用一個(gè)數(shù)據(jù)庫(kù)連接,而 INSERT,UPDATE,和 DELETE 語(yǔ)句使用另一個(gè)數(shù)據(jù)庫(kù)連接。在 Laravel 中,無(wú)論你是使用原生查詢,查詢構(gòu)造器,或者是 Eloquent ORM,都能輕松的實(shí)現(xiàn)
為了弄明白讀寫(xiě)分離是如何配置的,我們先來(lái)看個(gè)例子:
'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' => '', ],
注意在以上的例子中,配置數(shù)組中增加了三個(gè)鍵,分別是 read
, write
和 sticky
。 read
和 write
的鍵都包含一個(gè)鍵為 host
的數(shù)組。而 read
和 write
的其他數(shù)據(jù)庫(kù)都在鍵為 mysql
的數(shù)組中。
如果你想重寫(xiě)主數(shù)組中的配置,只需要修改 read
和 write
數(shù)組即可。所以,這個(gè)例子中: 192.168.1.1
將作為 「讀」 連接主機(jī),而 192.168.1.2
將作為 「寫(xiě)」 連接主機(jī)。這兩個(gè)連接會(huì)共享 mysql
數(shù)組的各項(xiàng)配置,如數(shù)據(jù)庫(kù)的憑據(jù)(用戶名 / 密碼),前綴,字符編碼等。
sticky
選項(xiàng)
sticky
是一個(gè) 可選值,它可用于立即讀取在當(dāng)前請(qǐng)求周期內(nèi)已寫(xiě)入數(shù)據(jù)庫(kù)的記錄。若 sticky
選項(xiàng)被啟用,并且當(dāng)前請(qǐng)求周期內(nèi)執(zhí)行過(guò) 「寫(xiě)」 操作,那么任何 「讀」 操作都將使用 「寫(xiě)」 連接。這樣可確保同一個(gè)請(qǐng)求周期內(nèi)寫(xiě)入的數(shù)據(jù)可以被立即讀取到,從而避免主從延遲導(dǎo)致數(shù)據(jù)不一致的問(wèn)題。不過(guò)是否啟用它,取決于應(yīng)用程序的需求。
使用多個(gè)數(shù)據(jù)庫(kù)連接
當(dāng)使用多個(gè)數(shù)據(jù)庫(kù)連接時(shí),你可以通過(guò) DB
Facade 的 connection
方法訪問(wèn)每一個(gè)連接。傳遞給 connection
方法的參數(shù) name
應(yīng)該是 config/database.php
配置文件中 connections 數(shù)組中的一個(gè)值:
$users = DB::connection('foo')->select(...);
你也可以使用一個(gè)連接實(shí)例上的 getPdo
方法訪問(wèn)底層的 PDO 實(shí)例:
$pdo = DB::connection()->getPdo();
運(yùn)行原生 SQL 查詢
一旦配置好數(shù)據(jù)庫(kù)連接后,便可以使用 DB
facade 運(yùn)行查詢。 DB
facade 為每種類型的查詢提供了方法: select
,update
,insert
,delete
和 statement
。
運(yùn)行 Select 查詢
你可以使用 DB
Facade 的 select
方法來(lái)運(yùn)行基礎(chǔ)的查詢語(yǔ)句:
<?php namespace App\Http\Controllers; use Illuminate\Support\Facades\DB; use App\Http\Controllers\Controller; class UserController extends Controller{ /** * 顯示應(yīng)用程序中所有用戶的列表 * * @return Response */ public function index() { $users = DB::select('select * from users where active = ?', [1]); return view('user.index', ['users' => $users]); } }
傳遞給 select
方法的第一個(gè)參數(shù)就是一個(gè)原生的 SQL 查詢,而第二個(gè)參數(shù)則是需要綁定到查詢中的參數(shù)值。通常,這些值用于約束 where
語(yǔ)句。參數(shù)綁定用于防止 SQL 注入。
select
方法將始終返回一個(gè)數(shù)組,數(shù)組中的每個(gè)結(jié)果都是一個(gè) = StdClass
對(duì)象,可以像下面這樣訪問(wèn)結(jié)果值:
foreach ($users as $user) { echo $user->name; }
使用命名綁定
除了使用 ?
表示參數(shù)綁定外,你也可以使用命名綁定來(lái)執(zhí)行一個(gè)查詢:
$results = DB::select('select * from users where id = :id', ['id' => 1]);
運(yùn)行插入語(yǔ)句
可以使用 DB
Facade 的 insert
方法來(lái)執(zhí)行 insert
語(yǔ)句。與 select
一樣,該方法將原生 SQL 查詢作為其第一個(gè)參數(shù),并將綁定數(shù)據(jù)作為第二個(gè)參數(shù):
DB::insert('insert into users (id, name) values (?, ?)', [1, 'Dayle']);
運(yùn)行更新語(yǔ)句
update
方法用于更新數(shù)據(jù)庫(kù)中現(xiàn)有的記錄。該方法返回受該語(yǔ)句影響的行數(shù):
$affected = DB::update('update users set votes = 100 where name = ?', ['John']);
運(yùn)行刪除語(yǔ)句
delete
方法用于從數(shù)據(jù)庫(kù)中刪除記錄。與 update
一樣,返回受該語(yǔ)句影響的行數(shù):
$deleted = DB::delete('delete from users');
運(yùn)行普通語(yǔ)句
有些數(shù)據(jù)庫(kù)語(yǔ)句不會(huì)有任何返回值。對(duì)于這些語(yǔ)句,你可以使用 DB
Facade 的 statement
方法來(lái)運(yùn)行:
DB::statement('drop table users');
監(jiān)聽(tīng)查詢事件
如果你想監(jiān)控程序執(zhí)行的每一個(gè) SQL 查詢,你可以使用 listen
方法。這個(gè)方法對(duì)于記錄查詢或調(diào)試非常有用。你可以在 服務(wù)提供器 中注冊(cè)你的查詢監(jiān)聽(tīng)器:
<?php namespace App\Providers; use Illuminate\Support\Facades\DB; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider{ /** * 啟動(dòng)應(yīng)用服務(wù) * * @return void */ public function boot() { DB::listen(function ($query) { // $query->sql // $query->bindings // $query->time }); } /** * 注冊(cè)服務(wù)提供器 * * @return void */ public function register() { // } }
數(shù)據(jù)庫(kù)事務(wù)
你可以使用 DB
facade 的 transaction
方法在數(shù)據(jù)庫(kù)事務(wù)中運(yùn)行一組操作。如果事務(wù)的閉包 Closure
中出現(xiàn)一個(gè)異常,事務(wù)將會(huì)回滾。如果事務(wù)閉包 Closure
執(zhí)行成功,事務(wù)將自動(dòng)提交。一旦你使用了 transaction
, 就不再需要擔(dān)心手動(dòng)回滾或提交的問(wèn)題:
DB::transaction(function () { DB::table('users')->update(['votes' => 1]); DB::table('posts')->delete(); });
處理死鎖
transaction
方法接受一個(gè)可選的第二個(gè)參數(shù) ,該參數(shù)用來(lái)表示事務(wù)發(fā)生死鎖時(shí)重復(fù)執(zhí)行的次數(shù)。一旦定義的次數(shù)嘗試完畢,就會(huì)拋出一個(gè)異常:
DB::transaction(function () { DB::table('users')->update(['votes' => 1]); DB::table('posts')->delete(); }, 5);
手動(dòng)使用事務(wù)
如果你想要手動(dòng)開(kāi)始一個(gè)事務(wù),并且對(duì)回滾和提交能夠完全控制,那么你可以使用 DB
Facade 的 beginTransaction
方法:
DB::beginTransaction();
你可以使用 rollBack
方法回滾事務(wù):
DB::rollBack();
最后,你可以使用 commit
方法提交事務(wù):
DB::commit();
{tip}
DB
facade 的事務(wù)方法同樣適用于 查詢構(gòu)造器 和 Eloquent ORM.