Database 用法

正常的資料庫是透過 DB 类別 去互动, 下面的範例会让你感覺到在 Fuel 裡如何使用資料庫。

Database 用法分为幾段:

执行查詢

首先我們使用 DB::query 預处理一个查詢。

// 回傳一个新的 Database_Query
$query = DB::query('SELECT * FROM `users`');

现在我們可以执行查詢:

$query = DB::query('SELECT * FROM `users`');

// 回傳一个新的 Database_MySQLi_Result
$query->execute();

// 或执行在不同的資料庫群組
$query->execute('another_group');
// 或
$query->execute(Database_Connection::instance('another_group'));

// 而且我們可以像这樣串聯:
$result = DB::query('SELECT * FROM `users`')->execute();

選擇資料

首先让我們使用 DB::query 選擇資料, 由於我們要取出此查詢結果, 我們需要让它知道我們要运行什么樣的查詢。


$result = DB::query('SELECT * FROM `users`', DB::SELECT)->execute();

我們也可以使用 DB::select 選擇資料

// 将执行 SELECT `id`, `name` FROM `users`
$result = DB::select('id','name')->from('users')->execute();

或使用 DB::select_array 可以让你动態建立你的列名稱陣列。

// 将执行 SELECT `id`, `name` FROM `users`
$colums = array('id', 'name');
$result = DB::select_array($columns)->from('users')->execute();

如果你想要別名行,使用陣列代替字串。

// 将执行 SELECT `name` as `the_name` FROM `users`;
$result = DB::select(array('name','the_name'))->from('users')->execute();

要選擇相異的值設定 distinct 为 true

// SELECT DISTINCT `name` FROM `users`
$users = DB::select('name')->from('users')->distinct(true)->execute();

print_r($users->as_array());
/*
Array
(
    [0] => Array
        (
            [name] => Dirk
        )

    [1] => Array
        (
            [name] => John
        )

)
*/

結果

执行 Select 查詢将產生一个結果物件,包含請求的資料庫紀錄。 預設情況下,結果被取出做为關聯陣列, 这裡有一个範例如何牽动此行为。

// 将取出結果做为一个關聯陣列。
$result = DB::select('id','name')->from('users')->as_assoc()->execute();

// 将取出結果做为一个物件。
$result = DB::select('id','name')->from('users')->as_object()->execute();

// 将取出結果做为一个 Model_Users 物件。
$result = DB::select()->from('users')->as_object('Model_Users')->execute();

// 将取出結果做为一个 Model_Users 物件(一个來自 Users 模組的模型)。
$result = DB::select()->from('users')->as_object('\\Users\\Model_Users')->execute();

當你傳遞一个类別名稱到 as_object(),確認你引入任何有需要的命名空間。 如果指定类別不存在,as_object() 将被忽略,并且将回傳一个索引陣列。

想知道你取出多少條紀錄?極度简单!


$result = DB::select('*')->from('users')->execute();
// 只要計算結果,它回傳一个整数。
$num_rows = count($result);

要存取这些結果,你可以直接透過結果物件做迴圈,或取得結果陣列。

$result = DB::select()->from('users')->execute();
foreach($result as $item)
{
	// 用 $item 做點什么
}

$result_array = $result->as_array();
foreach($result_array as $item)
{
	// 用 $item 做點什么
}

(選擇性)我們對從 as_array 回傳的陣列指定鍵與值

$result = DB::select()->from('users')->execute();
$on_key = $result->as_array('id');
foreach($on_key as $id => $item)
{
	// $id 将包含紀錄的 id
	// 用 $item 或它的 $id 做點什么
}

$key_value = $result->as_array('id', 'email');
foreach($key_value as $id => $email)
{
	// 现在 $email 将成为 email 欄位。
	// 所以你可以用 $id 或 $email 做點什么
}

過濾

Where 語句

为了在我們的查詢設定條件,我們可以設定 WHERE 條件。 这些範例也適用於更新和刪除。

// 将执行 SELECT * FROM `users` WHERE `id` = 1
$result = DB::select()->from('users')->where('id', 1)->execute();

要影響運算子,像这樣提供它:

// 将执行 SELECT * FROM `users` WHERE `id` = 1
$result = DB::select()->from('users')->where('id', '=', 1)->execute();

// 将执行 SELECT * FROM `users` WHERE `id` IN (1, 2, 3)
$id_array = array(1,2,3);
$result = DB::select()->from('users')->where('id', 'in', $id_array)->execute();

// 将执行 SELECT * FROM `users` WHERE `id` BETWEEN 1 AND 2
$result = DB::select()->from('users')->where('id', 'between', array(1, 2))->execute();

// 将执行 SELECT * FROM `users` WHERE `id` != 1
$result = DB::select()->from('users')->where('id', '!=', 1)->execute();

// 将执行 SELECT * FROM `users` WHERE `name` LIKE "john%"
$who = "john%";
$result = DB::select()->from('users')->where('name', 'like', $who)->execute();

成群的 where 語句也被支援:

// SELECT * FROM `users` WHERE (`name` = 'John' AND `email` = 'john@example.com')
// OR (`name` = 'mike' OR `name` = 'dirk')
$result = DB::select()->from('users')->where_open()
	->where('name', 'John')
	->and_where('email', 'john@example.com')
->where_close()
->or_where_open()
	->where('name', 'mike')
	->or_where('name', 'dirk')
->or_where_close()->execute();

BETWEENIN 也透過 where 方法運作:

// SELECT * FROM `users` WHERE `id` BETWEEN 1 AND 10
$users = DB::select()->from('users')->where('id', 'between', array(1, 10))->execute();

// SELECT * FROM `users` WHERE `name` IN ('john', 'simon', 'dirk')
$users = DB::select()->from('users')->where('name', 'in', array('john', 'simon', 'dirk'))->execute();

Order by 語句

我們使用 order_by function 函式排序資料。

// SELECT * FROM `users` ORDER BY `name` ASC
DB::select()->from('users')->order_by('name','asc');

// SELECT * FROM `users` ORDER BY `name` ASC, `surname` DESC
DB::select()->from('users')->order_by('name','asc')->order_by('surname', 'desc');

// 你可以藉由略去第二个參数來省略方向。
// SELECT * FROM `users` ORDER BY `name`
DB::select()->from('users')->order_by('name');

Limit 和 offset

我們使用 limit 和 offset 函式來限制取回的筆数。請注意,offset 函式只在選擇資料時可用。

// SELECT * FROM `users` LIMIT 1
DB::select()->from('users')->limit(1);

// SELECT * FROM `users` LIMIT 10 OFFSET 5
DB::select()->from('users')->limit(10)->offset(5);

// SELECT * FROM `users` ORDER BY `id` ASC LIMIT 10
DB::select()->from('users')->order_by('id','asc')->limit(10);

更新

我們使用 DB::update 來更新資料, 如果成功执行一个 Update 查詢将回傳一个整数, 代表受影響的筆数。

要更新单一行。

// 将执行 UPDATE `users` SET `name` = "John Random" WHERE `id` = "2";
$result = DB::update('users')
	->value("name", "John Random")
	->where('id', '=', '2')
	->execute();

要更新多个行。

// 将执行 UPDATE `users`
// SET `group` = "Peter Griffon", `email` = "peter@thehindenpeter.com"
// WHERE `id` = "16";
$result = DB::update('users')
	->set(array(
		'name'  => "Peter Griffon",
		'email' => "peter@thehindenpeter.com"
	))
	->where('id', '=', '16')
	->execute();

新增

我們使用 DB::insert 新增資料, 如果成功执行一个 Insert 查詢将回傳一个陣列, 包含新增 ID 和建立列的列表。

// 将执行 INSERT INTO `users`(`name`,`email`,`password`)
// VALUES ("John Random", "john@example.com", "s0_s3cr3t")
list($insert_id, $rows_affected) = DB::insert('users')->set(array(
	'name' => 'John Random',
	'email' => 'john@example.com',
	'password' => 's0_s3cr3t',
))->execute();

你也可以分別設定行和值

// 将执行 INSERT INTO `users`(`name`,`email`,`password`)
// VALUES ("John Random", "john@example.com", "s0_s3cr3t")
list($insert_id, $rows_affected) = DB::insert('users')->columns(array(
	'name', 'email', 'password'
))->values(array(
	'John Random', 'john@example.com', 's0_s3cr3t'
))->execute();

刪除

要刪除資料,使用 DB::delete。 當执行時将回傳受影響的筆数。

// 清空整个 users 表
$result = DB::delete('users')->execute(); // (int) 20

// 执行 DELETE FROM `users` WHERE `email` LIKE "%@example.com"
$result = DB::delete('users')->where('email', 'like', '%@example.com')->execute(); // (int) 7

組合

當選擇資料,你也可以組合其他表到結果。

// 将执行 SELECT * FROM `users` LEFT JOIN `roles` ON `roles`.`id` = `users`.`role_id`
$result = DB::select()->from('users')->join('roles','LEFT')->on('roles.id', '=', 'users.role_id');

// 将执行 SELECT * FROM `users` RIGHT OUTER JOIN `roles` ON `roles`.`id` = `users`.`role_id`
$result = DB::select()->from('users')->join('roles','right outer')->on('roles.id', '=', 'users.role_id');

// 在一个字面值 1 組合,而不是行名
$result = DB::select()->from('users')->join('roles','right outer')->on('roles.id', '=', DB::expr('1'));

轉義

在資料庫呼叫中,欄位和值是預設轉義。在某些情況下,你会希望不要轉義資料,DB 类別提供一个 DB::expr 方法來建立資料庫表達式。如果你不想要一个值被轉義,只要在一个資料庫表達式包住它。

資料庫表達式在处理像是 MySQL 的原生函式(如 COUNT)和預定義常数(如 DEFAULT)時特別有用。

// 設定一个欄位为它的預設
DB::update('users')->where('id', '=', 1)->set(array(
	'some_column' => DB::expr('DEFAULT'),
))->execute();

// SELECT COUNT(*) as count FROM `users`
$result = DB::select(DB::expr('COUNT(*) as count'))->from('users')->execute();

// 取得目前/第一筆結果
$result_arr = $result->current();

// 取得筆数
$count = $result_arr['count'];

賦值查詢

查詢建立器支援賦值查詢,它是一種技術, 能让你在安全可靠的方法指派變数到你手寫查詢。

賦值查詢藉由放置在你的查詢中唯一可辨認的占位符運作。 賦值查詢藉由放置在你的查詢中唯一可辨認的占位符運作。當查詢被编譯执行時(你連接它時!), 查詢建立器将以它們對應的值取代这些占位符。

你可以使用 FuelPHP 标准表示法定義占位符,它是一个以冒號前綴 (:變数名稱)的字串。

$name = 'John'; // 設定我們想要連接的變数
$query = "SELECT * FROM users WHERE username = :name"; // 我們的查詢

// 連接變数并执行查詢,產生 SELECT * FROM users WHERE username = 'John'
$result = DB::query($query)->bind('name', $name)->execute();

變数藉由參照綁定,所以你可以輕易地在你的程式码中,定義你的查詢和賦值, 并在稍後修改綁定的變数。

// 建立查詢物件
$query = DB::query("SELECT * FROM users WHERE username = :name");

$name = 'unknown';                // 設定變数預設值
$query->bind('name', $name);     // 并連接到查詢

// 在一些程式码之後,變更綁定的變数
$name = 'Sally';

// 連接變数并执行查詢,產生 SELECT * FROM users WHERE username = 'Sally'
$result = $query->execute();

因为變数藉由參照綁定,你不能連接一个文字。 如果你这樣做,将得到一个 "Cannot pass parameter 2 by reference" 例外!

// 这将產生一个例外!
$query = DB::query("SELECT * FROM users WHERE username = :name")->bind('name', 'value')->execute();

你可以使用 param() 方法指派值:

// 这会運作
$query = DB::query("SELECT * FROM users WHERE username = :name")->param('name', 'value')->execute();

最後,你可以使用 parameters() 方法,如果你想要混合兩者的話:

// 建立查詢物件
$query = DB::query("SELECT * FROM users WHERE username = :name AND state = :state");

$name = 'John'; // 設定我們想要連接的變数

// 連接變数和文字
$query->parameters(array('name' => &$name, 'state' => 'new'));

// 并执行查詢,產生 SELECT * FROM users WHERE username = 'John' AND state = 'new'
$result = $query->execute();

有些框架使用問號做为占位符,这適用於它們,因为它們的賦值系统是定位的, 第一个問號被第一个綁定的變数取代,以此类推。 在 FuelPHP 中,賦值的順序是不相關的, 在占位符和綁定的變数之間是一對一的連結, 这也意味著,你可以在单一查詢中多次使用相同的占位符。

快取查詢

查詢建立器也支援快取查詢的結果,以幫助你減低你的資料庫存取。 为了實现此目标,它在幕後使用 Cache 类別, 但处理快取的取回和再生。
cached() 方法使用 3 个參数:到期時間(以秒为单位的快取有效期); 第二个參数为查詢設定一个自訂的鍵(預設是一个查詢的 md5 雜湊); 一个布林可用來表示你不想要快取空結果。 使用一个自訂快取鍵将能让你更易於手动刪除特定查詢, 及組合一組查詢快取進特定的目录。

// 执行一个查詢并快取它 1 小時
// 如果你下一次执行確切相同的查詢,它将回傳快取的結果。
// 这将发生在快取的 3600 秒內,否則将执行
// 并且產生另一次快取。
$query = DB::query("SELECT * FROM users")->cached(3600)->execute();

// 你可以指定一个鍵來处理快取結果的刪除,如果你
// 知道該鍵将被更新和在它顯示前需要被刪除的話是有用的。
// 空查詢結果将不会被快取。
$query = DB::query("SELECT * FROM users")->cached(3600, "foo.bar", false)->execute();

// 從快取刪除前一个查詢
Cache::delete("foo.bar");
// 或刪除在 "foo" 目录中的所有快取
Cache::delete_all("foo");

// 預設情況下所有查詢被放在 "db" 目录
// 因此,不手动設定其中的鍵,要刪除所有查詢快取
Cache::delete_all("db");