展開文件目錄

資料庫:入門

介紹

Laravel 使用原生 SQL 和流暢的查詢產生器,以及 Eloquent ORM 讓操作各種後端資料庫非常的容易。目前 Laravel 支援四種資料庫:

  • MySQL
  • PostgreSQL
  • SQLite
  • SQL Server

設定

資料庫的設定檔放在你應用程式的 config/database.php。在這個設定檔內你可以定義所有的資料庫連接,以及指定預設使用哪個連接。在這個檔案內提供了大多數支援的資料庫系統範例。

預設來說,Laravel 的環境設定範例是使用 Laravel Homestead,在開發 Laravel 時,這是相當便利的本機虛擬機器。當然,你可以因應需求隨時修改你本機端的資料庫設定。

SQLite 設定

如果使用像是 touch database/database.sqlite 類似的指令建立新的 SQLite 資料庫,你可以使用資料庫的絕對路徑來輕易的將環境變數設定給剛建立的資料庫:

DB_CONNECTION=sqlite
DB_DATABASE=/absolute/path/to/database.sqlite

讀寫分離

有時候你可能希望使用一個資料庫連線來處理查詢,另一個用來處理寫入、更新和刪除。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'    => '',
],

注意,有三個鍵加入了這個設定檔陣列內:readwritestickyreadwrite 鍵都包含單一個鍵的陣列值:hostreadwrite 連接的其他的資料庫設定選項將會合併在主要的 mysql 陣列內。

如果你希望覆蓋主要陣列的值,你只需要將項目放置在 readwrite 的陣列中。所以,在這個情況下,192.168.1.1 會用於「讀取」的主機連線,而 192.168.1.2 會被用於「寫入」的主機練線。資料庫的憑證、前綴、編碼設定,以及所有其它的選項都存放在 mysql 陣列內,兩個連接將會共用這些選項。

sticky 選項

sticky 選項是一個可選的值,可以被用於立即讀取在目前請求週期內已寫入資料庫的記錄。如果啟動了 sticky 選項,而且已經在目前的請求週期間對資料庫執行了「寫入」操作,任何進一步的「讀取」操作都將使用「寫入」連線。這樣保證了在請求週期中寫入的任何資料可以在週期結束前立即從資料庫讀取剛寫入的資料。可以根據你的應用程式需求而決定是否要使用這個選項。

使用多個資料庫的連線

當你使用多個連接,你可以使用 DB facade 的 connection 方法存取每個連線。傳遞給 connection 方法的 name 必須對應至 config/database.php 設定檔裡連接列表的其中一個:

$users = DB::connection('foo')->select(...);

你也可以在連接的實例使用 getPdo 方法存取原生的底層 PDO 實例:

$pdo = DB::connection()->getPdo();

執行原生 SQL 查詢

一旦你設定好了資料庫連線,你可以使用 DB facade 進行查詢。DB facade 提供每個類型的查詢方法:selectupdateinsertdeletestatement

執行一個 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 方法總是回傳結果的陣列。陣列中的每個結果將是一個 PHP StdClass 物件,讓你能夠存取結果的值:

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

使用命名綁定

除了使用 ? 表示你的參數綁定外,你也可以使用命名綁定執行查詢:

$results = DB::select('select * from users where id = :id', ['id' => 1]);

執行一個 Insert 陳述式

若要執行 insert 語法,你可以在 DB facade 使用 insert 方法。如同 select,這個方法第一個參數是使用原生 SQL 查詢,第二個參數則是綁定:

DB::insert('insert into users (id, name) values (?, ?)', [1, 'Dayle']);

執行一個 Update 陳述式

update 方法用於更新已經存在於資料庫的記錄。將會回傳該語法影響的行數:

$affected = DB::update('update users set votes = 100 where name = ?', ['John']);

執行一個 Delete 陳述式

delete 方法用於刪除已經存在於資料庫的記錄。如同 update,受影響的行數將會被回傳:

$deleted = DB::delete('delete from users');

執行一般陳述式

某些資料庫語句不應該回傳任何值。對於這種類型的操作,你可以在 DB facade 使用 statement 方法:

DB::statement('drop table users');

監聽查詢事件

如果你希望能夠接收到應用程式的每一筆 SQL 查詢,你可以使用 listen 方法。這個方法對於記錄查詢跟除錯非常有用你可以在服務容器註冊你的查詢監聽器:

<?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 方法來執行資料庫交易中的一組操作。如果在交易的閉包內拋出例外,交易會自動的被還原。如果閉包執行成功,交易將自動提交。你不需要擔心在使用 transaction 方法時手動還原或提交:

DB::transaction(function () {
    DB::table('users')->update(['votes' => 1]);

    DB::table('posts')->delete();
});

處理 Deadlock

transaction 方法接受一個可選的第二個參數,它定義了當發生 deadlock 時,交易應該重新嘗試的次數。一旦嘗試的次數被用完,將會拋出異常:

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 的交易方法控制查詢建構器Eloquent ORM 的交易。