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();
BETWEEN 和 IN 也透過 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");