▶ 技術めも
PHP シンプルORM Active Record
オフィシャルサイト
http://www.phpactiverecord.org/
シンプルORM。PHP5.3以上
composer require php-activerecord/php-activerecord
初期設定
イニシャライズ
require_once 'php-activerecord/ActiveRecord.php';
ActiveRecord\Config::initialize(function($cfg)
{
$cfg->set_model_directory(dirname(__FILE__).'/classes/models'); // ← modelの置き場所
$cfg->set_connections(array(
'development' => 'mysql://username:password@localhost/database_name', // ← DB接続情報
));
});
モデル
set_model_directory() で指定したディレクトリにモデルclassを配置
メソッドでビジネスロジックを記載
class User extends ActiveRecord\Model
{
static $table_name = 'users'; // ← テーブル名(デフォルト:小文字クラス名+s)
static $primary_key = 'id'; // ← プライマリーカラム(デフォルト:id)
static $connection = 'production'; // ← コネクション名(デフォルト:development)
static $db = 'mydb'; // ← DB名(コネクション設定で指定されていたら不要)
}
テーブル名は複数形(books)推奨
クラスの名前はテーブル名の単数形(Book)。
class Book extends ActiveRecord\Model {}
特別なパターンもある(テーブル名が "people")
class Person extends ActiveRecord\Model {}
SELECT
http://www.phpactiverecord.org/projects/main/wiki/Finders
find
Book::find(2); // プライマリーキーでの指定
プライマリーキーを複数記載可能
Book::find(2,3);
下記でも同じ動作になる
Book::find(array(2,3));
引数に first, last, all を指定可能
Book::find('first');
Book::find('last');
Book::find('all');
下記でも同じ動作になる
Book::first();
Book::last();
Book::all();
SQL記載
$book = Book::find_by_sql('select title from `books`'); // SQLを記載
条件 WHERE
第2引数に 条件Array を 'conditions' で設定する
キー'conditions'の値は、配列で複数指定する
「?」が置き換えられる(sprintf記法)
$options = array('conditions' => array('price < ?', 15.00));
Book::find('all', $options);
下記でも同じ動作になる
$options = array('conditions' => array('price < ?', 15.00));
Book::all($options);
複数の?の場合(sprintf記法)
$options = array('conditions' => array('genre = ? AND price < ?', 'Romance', 15.00));
Book::find('all', $options);
IN 条件の場合は、?に入る値を配列で指定
$options = array('conditions' => array('author_id in (?)', array(1,2,3)));
Book::find('all', $options);
条件 LIMIT, OFFSET, ORDER
第2引数に 条件Array を 'limit','offset','order' で設定する
$options = array('limit' => 2);
Book::find('all', $options);
下記でも同じ動作になる
$options = array('limit' => 2);
Book::all($options);
LIMIT, OFFSET 指定する場合
Book::find('all', array('limit' => 10, 'offset' => 5));
ORDER BY を指定する場合
Book::find('all', array('order' => 'title desc'));
Book::find('all', array('order' => 'price desc, title asc'));
取得するカラムを指定
取得するカラムを 'select' で指定する
id, title だけを取得( SELECT id, title FROM books
)
Book::find('all', array('select' => 'id, title'));
取得した情報を as で別カラム名に変更
Book::find('all', array('select' => 'avg(price) as avg_price, avg(tax) as avg_tax'));
JOIN
条件Arrayで 'joins' を指定
$joinOption = 'LEFT JOIN authors a ON(books.author_id = a.author_id)';
$book = Book::find('all', array('joins' => $joinOption));
→ SELECT books
.* FROM books
LEFT JOIN authors a ON(books.author_id = a.author_id)
GROUP, HAVING
条件Arrayで 'group' を指定
Book::find('all', array('group' => 'price'));
条件Arrayで 'having' を指定
Book::find('all', array('group' => 'price', 'having' => 'price > 45.00'));
ダイナミック Finder
findby[カラム名] メソッド で条件にあったデータを取得
$book = Book::find_by_title('War and Peace');
__find_allby[カラム名] メソッド__ で条件にあった複数のデータを取得
$books = Book::find_all_by_discounted(1);
__find_allby[カラム名]and[カラム名]__ で複数の条件にあった複数のデータを取得
1つのデータを取得する場合は、findby[カラム名]and[カラム名]
$books = Book::find_all_by_discounted_and_author_id(1, 5);
→ SELECT * FROM books
WHERE discounted = 1 AND author_id = 5
__find_allby[カラム名]or[カラム名]__ で複数の条件のどれかにあった複数のデータを取得
1つのデータを取得する場合は、findby[カラム名]or[カラム名]
$books = Book::find_by_discounted_or_price(1, 5.00);
→ SELECT * FROM books
WHERE discounted = 1 OR price = 5.00
CREATE
http://www.phpactiverecord.org/projects/main/wiki/Basic_CRUD
new でオブジェクトを作成。情報を入れて save()
$post = new Post();
$post->title = 'My first blog post!!';
$post->author_id = 5;
$post->save();
オブジェクトを作成するときに、情報を入力することも可能
$attributes = array('title' => 'My first blog post!!', 'author_id' => 5);
$post = new Post($attributes);
$post->save();
createメソッドを使用するとダイレクトに作成(saveメソッド不要)
$attributes = array('title' => 'My first blog post!!', 'author_id' => 5);
$post = Post::create($attributes);
UPDATE
オブジェクトを取得して、情報を書き込んで save()
$post = Post::find(1);
echo $post->title;
$post->title = 'Some real title';
$post->save();
UPDATE or INSERT
もしオブジェクトがあれば UPDATE、なければ INSERT を行いたいときは、empty で評価
$post = Post::find_by_title('Some real title');
if (empty($post)) {
$post = new Post();
$post->title = 'Some real title';
}
$post->author = 'Dr.Anyone';
$post->price = 18;
$post->save();
複数一斉UPDATE
デーブルのオブジェクトを取得、UPDATE内容と条件を引数で指定
Model::table()->update(AttributesToUpdate, WhereToUpdate);
$updateValues = array('title' => 'Massive title!');
$whereOptions array('id' => array(1, 3, 7));
Post::table()->update($updateValues, $whereOptions);
【注意】ダイレクトに引数に並列を指定すると、動かない(php5.3)
https://github.com/kla/php-activerecord/issues/151
DELETE
オブジェクトを取得して deleteメソッド実行
$post = Post::find(1);
$post->delete();
複数一斉DELETE
デーブルのオブジェクトを取得、DELETE条件を引数で指定
Model::table()->delete(WhereToDelete);
$whereOptions = array('id' => array(5, 9, 26, 30));
Post::table()->delete($whereOptions);
第1引数に「条件文字列」を記載したら動いた(個人的メモ)
Post::table()->delete('DATE_ADD(created_at,INTERVAL 1 HOUR) < NOW()');
【注意】ダイレクトに引数に並列を指定すると、動かない(php5.3)
https://github.com/kla/php-activerecord/issues/151
特記事項
複数一斉DELETE で Warning
第1引数に「条件文字列」を記載して一斉削除する場合、Warning が表示される
Post::table()->delete('DATE_ADD(created_at,INTERVAL 1 HOUR) < NOW()');
Warning: Invalid argument supplied for foreach() in /home/lib/activerecord/lib/Table.php on line 387
理由は引数の文字列を foreach 処理を行なっているから。
だがその後の処理で文字列だった場合、SQLをダイレクト実行しているので記載的には問題ない。
コードを変更して対応する場合は、下記の1行を Table.php のメソッドに追加。
private function &process_data($hash)
{
if (!$hash)
return $hash;
if (is_string($hash)) return $hash; // ★ 2013.06.09 add tatenosystem
foreach ($hash as $name => &$value)
{
if ($value instanceof \DateTime)
{
if (isset($this->columns[$name]) && $this->columns[$name]->type == Column::DATE)
$hash[$name] = $this->conn->date_to_string($value);
else
$hash[$name] = $this->conn->datetime_to_string($value);
}
else
$hash[$name] = $value;
}
return $hash;
}