Laravel 文件閱讀:資料庫起步

zhangbao發表於2017-08-24

翻譯、衍生自:https://learnku.com/docs/laravel/5.4/database

簡介

Laravel 讓開發者與多種資料庫的互動變得非常簡單,主要是利用 查詢語句構造器Eloquent ORM 幫您產生與業務邏輯對應的原生 SQL 語句,避免了開發者手動書寫 SQL 語句帶來的煩惱。現支援的資料庫如下:

  • MySQL
  • Postgres
  • SQLite
  • SQL Server

配置

資料庫配置檔案是 config/database.php。你可以根據實際情況,修改或新增你的資料庫資訊,指定預設使用的資料庫連線(database connections)。

配置 SQLite

配置 SQLite 需要先建立一個資料庫,使用 touch database/database.sqlite 建立,然後再配置你的環境變數——使用絕對路徑指向這個新建立的資料庫。

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

配置 SQL Server

Laravel 在配置檔案 config/database.php 中,已經為您預設了 SQL Server 的連線資訊,只需要按照實際情況修改即可:

'sqlsrv' => [
    'driver' => 'sqlsrv',
    'host' => env('DB_HOST', 'localhost'),
    'database' => env('DB_DATABASE', 'forge'),
    'username' => env('DB_USERNAME', 'forge'),
    'password' => env('DB_PASSWORD', ''),
    'charset' => 'utf8',
    'prefix' => '',
],

讀 & 寫連線

有時,您希望專案使用兩種資料庫——一種負責讀,也就是用來執行 select 語句;另一種負責寫,用來執行 insertupdatedelete 語句。Laravel 使之變得輕而易舉,無論您是使用原生查詢、查詢語句構造器還是Eloquent ORM,都會始終使用正確的連線。

具體讀 & 寫連線的配置方式,看下面的例子可知:

'mysql' => [
    'read' => [
        'host' => '192.168.1.1',
    ],
    'write' => [
        'host' => '196.168.1.2'
    ],
    'driver'    => 'mysql',
    'database'  => 'database',
    'username'  => 'root',
    'password'  => '',
    'charset' => 'utf8mb4',
    'collation' => 'utf8mb4_unicode_ci',
    'prefix'    => '',
],

我們為配置資訊新增了兩個鍵:readwrite。兩個鍵裡又包含 host 鍵。在 mysql 中,其餘的配置資訊是讀 & 寫連線共用的配置資訊。

在上面例子裡,192.168.1.1 這臺主機用來「讀」, 196.168.1.2 這臺主機用來「寫」。而其餘像使用者名稱、密碼、資料庫編碼等都是兩個連線共用的配置。

使用多資料庫連線

DB 門面提供了 connection 方法,用來獲得某個連線。用它就可以實現使用多資料庫連線的需求。給 connection 傳遞是一個「連線名」,這個連線名必然是要在 config/database.php 裡配置的。

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

您可以用連線例項的 getPdo 方法獲得底層 PDO 例項。

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

執行原生 SQL 查詢

使用 DB 門面可以完成每種型別的查詢:selectupdateinsertdeletestatement

執行 select 查詢

使用 DB 門面的 select 方法可執行查詢:

<?php

namespace App\Http\Controllers;

use Illuminate\Support\Facades\DB;
use App\Http\Controllers\Controller;

class UserController extends Controller
{
    /**
     * Show a list of all of the application's users.
     *
     * @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 語句

使用 DB 門面的 insert 方法插入資料。形如 select 方法,DB:insert 的第一個引數是原生 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 語句

update 方法用來從資料庫中刪除記錄,類似 update 方法,返回的結果是刪除的記錄數目。

執行一般語句

「一般語句」指沒有返回結果的 SQL 語句。對於這類操作,可以使用 DB 門面上的 statement 方法。

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

監聽查詢事件

如果你要查閱 Laravel 底層執行的 SQL 語句,可以使用 listen 方法,這個方法會在程式執行 SQL 語句時呼叫。這對 debug 程式和記錄 SQL 語句非常有用。你可以在服務提供者 AppServiceProvider 中註冊、監聽查詢事件。

<?php

namespace App\Providers;

use Illuminate\Support\Facades\DB;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        DB::listen(function ($query) {
            // $query->sql
            // $query->bindings
            // $query->time
        });
    }

    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

資料庫事務

你可以用 DB 門面的 transaction 方法在一個事務裡執行一系列操作。如果事務閉包裡丟擲異常,那麼事務就會自動回滾。如果閉包執行成功,那麼事務就會自動提交。使用 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);

手動使用事務

如果你要完全手動控制事務的回滾和提交,就要用 BD 門面的 beginTransaction 方法了:

DB::beginTransaction();

使用 rollBack 方法回滾事務:

DB::rollBack();

最後,使用 commit 方法提交事務:

DB::commit();

相關文章