Database 使い方
通常のデータベース命令は、DB クラスを通じて実行することになります。
Fuel ではどのようにデータベースを取り扱うかを以下の例で確認してみてください。
データベースの使用法は大きく2つに分けられます:
クエリの実行
始めに、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();
SELECT 文
まずは 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モジュールのmodel)
$result = DB::select()->from('users')->as_object('\\Users\\Model_Users')->execute();
クラス名を as_object() に渡す場合、必要があれば namespace を含めてください。もし指定されたクラスが存在しない場合、
as_object() は無視され、インデックス付きの配列が返却されるでしょう。
何レコードが取得できたか知りたいって?それは超シンプルです!
$result = DB::select('*')->from('users')->execute();
// ただ結果をカウントするだけ。int が返ります。
$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 には電子メールのフィールドが入るので
// $id や $email に関する処理ができる
}
抽出条件
WHERE 句
クエリに条件を追加するために、私たちは、WHERE 句をセットすることができます。
これらの例は、UPDATE句とDELETE句にも当てはまります。
// 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('id', '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 メソッドを使用します。
//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');
// 2 番目の引数を省略すれば、order by の昇順降順を省くことができます。
// 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('users')->order_by('id','asc')->limit(10);
UPDATE 文
データを更新するためには、DB::updateを使用します。
もし更新クエリの実行が成功した場合には、更新が影響したレコード数を
整数値で返却します。
1 カラムを更新する
// 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();
INSERT 文
データをインサートするには、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();
DELETE 文
レコードを削除するには、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 を提供します。もし値をエスケープされるのを望まない場合、データベース表現の中でそれを囲んでください。
データベース表現は COUNTのようなMySQLのネイティブ関数 やDEFAULT のような定数を扱う際に特に有用です。
// カラムにデフォルト値でセットする
DB::update('users')->where('id', '=', 1)->set(array(
'some_column' => DB::expr('DEFAULT'),
))->execute();
// SELECT COUNT(*) FROM `users`
$result = DB::select(DB::expr('COUNT(*) as count'))->from('users')->execute();
// 現在(先頭)の結果セットを取得
$result_arr = $result->current();
// 行数を取得
$count = $result_arr['count'];
値のバインド
クエリービルダは、安全かつ確実なやり方で手書きのクエリに変数を割り当てる、
バインディング機能を提供します。
クエリバインディングは、 SQLの中でユニークなプレースホルダを置くことにより動作します。 クエリビルダは、
(バインドした時ではなく)クエリが実行のためにコンパイルされる際に、
これらのプレースホルダを対応する値で置換します。
あなたはFuelPHP標準記法を使用して、プレースホールダーを定義します。それはコロンから始まる文字列です。
例 (:varname)
$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();
最後に、あなたが 2 つを混ぜたい場合、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では、順番によるバインディングは適切ではなく、プレースホールダーと値には1対1の対応があります。
それは同様に、1 つのクエリでプレースホルダを複数回使用できることを意味します。
クエリキャッシュ
クエリビルダは、クエリ結果のキャッシュもサポートします。これによりデータベースアクセスを減らすことができます。
これは、バックエンドでキャッシュクラスを使用し、キャッシュの読み込みと再生成の両方を行います。
cached()
メソッドは、3つの引数をとります: 第一引数は有効期限 (キャッシュが有効となる秒数)、
第二引数は、クエリのカスタムキー (デフォルトでは、SQLのmd5 ハッシュ値)、そして最後は、あなたが空の結果をキャッシュしたくないか
を指定する、boolean値です。 カスタムキャッシュキーを使用すると、
手動で特定のクエリのキャッシュを削除したり、特定の階層へクエリキャッシュのセットを
グループ化したりできるようになります。
// クエリを実行し、1時間キャッシュします。
// もしまったく同じクエリが次回実行された場合、キャッシュされた値が返ります。
// これは、 3600 秒間有効です。もし有効期限後にクエリが実行された場合、
// 再度クエリが走り、再度 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");