PowerCMS X ブログ
2021-07-05
PADOBaseModelクラスの loadメソッドとは PowerCMS Xでデータベースに対して SELECT文を発行するしくみで、PowerCMS Xのデータベース操作の肝となるメソッドです。
PowerCMS X (Prorotypeクラス) のオブジェクトが $app の時、$app->db が PADOクラス、さらに、以下のようにしてオブジェクトを生成します。
$app = Prototype::get_instance();
$entry = $app->db->model( 'entry' ); // PADOBaseModel (記事モデル)
テーブル名は prefix(mt_)+モデル名となります。「記事」モデルであれば「mt_entry」、「ページ」モデルであれば「mt_page」となります。
カラム名は、モデル名_+カラム名となります。記事のタイトルは「entry_title」、カテゴリのラベルは「category_label」となります。
すべてのテーブルには「モデル名_id」という、INTEGER PRIMARY KEY, AUTOINCREMENT が設定されたカラムが作成されます。記事モデルの場合は「entry_id」です。
リレーション型のカラムは「疑似カラム」で、テーブルにカラムは作成されません。
リレーション型のカラムに値をセットすると「mt_relation」テーブルに relation_from_obj, relation_from_id, relation_to_obj, relation_to_id, relation_order というレコードを生成します。
loadメソッドや PowerCMS Xのデータベース操作においては、prefix(mt_)やカラム名の先頭の「モデル名_」は省略して指定します。
$app->db->model( 'entry' )->load( ['title' => 'PowerCMS X'] );
発行されるSQL文は以下となります。
SELECT * FROM mt_entry WHERE entry_title='PowerCMS X';
※ 実際には(これ以下のSQL文も) 疑問符 placeholder が使われます。
SELECT * FROM mt_entry WHERE entry_title=?;
SELECT文を発行してオブジェクトを返します。
$app->db->model('モデル名')->load( [ $terms, $args, $cols, $extra, $ex_vars ] );
IDが1の記事を取得する
$entry = $app->db->model( 'entry' )->load( 1 );
$entry = $app->db->model( 'entry' )->load( '1' );
// 発行されるSQL文
// SELECT * FROM mt_entry WHERE entry_id=1;
数値指定の場合、戻り値は単一の PADOBaseModelオブジェクトとなります。指定したIDが存在しない場合は NULLが返ります。
第1引数が配列 $terms の場合、戻り値は常にオブジェクトの配列(該当するものがない場合は空の配列)となります。
$app->db->model( 'entry' )->load( ['title' => 'PowerCMS X', 'basename' => 'powercmsx'] );
// 発行されるSQL文
// SELECT * FROM mt_entry WHERE entry_title='PowerCMS X' AND entry_basename='powercmsx';
値に配列を指定することもできます。
$app->db->model( 'entry' )->load( ['title' => ['like' => '%PowerCMS X%'], 'status' => ['IN' => [1, 2, 3] ] ] );
// 発行されるSQL文
// SELECT * FROM mt_entry WHERE entry_title LIKE '%PowerCMS X%' AND entry_status IN (1,2,3);
// ※ $app->db->escape_like( 'PowerCMS X', true, true ); で、'%PowerCMS X%' が取得できます
// (%や_をエスケープして、第2, 第3引数指定で前後に「%」を付けます)。
$entries = $app->db->model( 'entry' )->load( ['keywords' => ['IS NULL' => 1] ] );
// 発行されるSQL文
// SELECT * FROM mt_entry WHERE entry_keywords IS NULL;
$entries = $app->db->model( 'entry' )->load( ['published_on' => ['BETWEEN' => ['2021-07-01 00:00:00', '2021-07-31 23:59:59'] ] );
// 発行されるSQL文
// SELECT * FROM mt_entry WHERE entry_published_on BETWEEN '2021-07-01 00:00:00' AND '2021-07-31 23:59:59';
第1引数 $terms に配列を指定した場合、第2引数にLIMIT, OFFSET, ORDER BY, JOIN 句を指定できます。
$app->db->model( 'entry' )->load( ['title' => 'PowerCMS X'], ['sort' => 'id', 'direction' => 'descend', 'limit' => 10, 'offset' => 5] );
// 発行されるSQL文
// SELECT * FROM mt_entry WHERE entry_title='PowerCMS X' LIMIT 10 OFFSET 5 ORDER BY entry_id DESC
※ limit指定が「1」であっても、返り値は常に配列となることに注意してください。
キー 'sort' に対してハッシュ配列で指定することで複数のソート条件を指定することができます。
['sort' => ['delete_flag' => 'ascend', 'id' => 'descend'] ]
// ORDER BY urlinfo_delete_flag ASC,urlinfo_id DESC (urlinfoモデルの例)
JOIN句を組み立てるには以下のようにします。以下は id=1のassetオブジェクトのサムネイル(meta)とURLオブジェクトをあわせて取得する例です。
$args = ['join' => ['urlinfo', 'meta_id'], 'distinct' => 1];
$thumbnails = $app->db->model( 'meta' )->load( ['object_id' => 1, 'model' => 'asset', 'kind' => 'thumbnail'], $args );
// 発行されるSQL文
// SELECT DISTINCT mt_meta.*,mt_urlinfo.* FROM mt_meta JOIN mt_urlinfo ON mt_meta.meta_id=mt_urlinfo.urlinfo_meta_id WHERE ( meta_object_id = 1 AND meta_model = 'asset' AND meta_kind = 'thumbnail' );
第1引数 $terms に配列もしくは数値を指定した場合、第3引数 $cols に SELECT対象のカラムを指定できます。指定できるのはカンマ区切りのテキストもしくは配列です。
$entry = $app->db->model( 'entry' )->load( 1, null, 'id,title' );
// 発行されるSQL文
// SELECT entry_id,entry_title FROM mt_entry WHERE entry_id=1;
$app->db->model( 'entry' )->load( ['title' => 'PowerCMS X', null, ['id', 'title'] );
// 発行されるSQL文
// SELECT entry_id,entry_title FROM mt_entry WHERE entry_title='PowerCMS X';
第1引数 $terms に配列もしくは数値を指定した場合、第4引数にWHERE句に追加するSQL文を指定できます。
$extra = 'AND entry_workspace_id IN (1, 2, 3)';
$app->db->model( 'entry' )->load( ['title' => 'PowerCMS X', null, null, $extra );
// 発行されるSQL文
// SELECT * FROM mt_entry WHERE entry_title='PowerCMS X' AND entry_workspace_id IN (1, 2, 3);
第4引数にSQL文を指定する時、第5引数に第4引数に対する placeholderを指定できます(配列)。
$extra = 'AND entry_keywords=? AND entry_status=?';
$ex_vars = ['PowerCMS X', 4];
$app->db->model( 'entry' )->load( ['title' => 'PowerCMS X', null, null, $extra, $ex_vars );
// 発行されるSQL文
// SELECT * FROM mt_entry WHERE entry_title='PowerCMS X' AND entry_keywords='PowerCMS X' AND entry_status=4;
数値や $terms配列の代わりに、第1引数にSQL文を指定することができます。当然ですが、ユーザーから受け取った任意の値をそのままSQL文に含めてはいけません。第1引数にSQL文を指定する場合は第2引数に placeholder (配列)を渡すことができます。
$sql = 'SELECT * FROM mt_entry WHERE entry_title='PowerCMS X';
// 発行されるSQL文
// $app->db->model( 'entry' )->load( $sql );
$sql = 'SELECT * FROM mt_entry WHERE entry_title=?';
$vars = ['PowerCMS X'];
$app->db->model( 'entry' )->load( $sql, $vars );
// 発行されるSQL文
// SELECT * FROM mt_entry WHERE entry_title=?;
// ↓
// SELECT * FROM mt_entry WHERE entry_title='PowerCMS X';
loadメソッドとよく似たメソッドに以下のメソッドがあります。
戻り値が PDOStatement であることを除き、loadメソッドとの違いはありません。
$sth = $app->db->model('モデル名')->load_iter( [ $terms, $args, $cols, $extra, $ex_vars ] );
$objects = $sth->fethAll();
loadメソッドを呼び出し、該当するものがある時、最初にマッチした単一のオブジェクトを返します(配列ではなく、単一のオブジェクトが返ります)。
該当するものがない時は、$termsが配列指定の時、その条件でオブジェクトを新規に生成し(第2引数以下の引数は無視されます)、単一のオブジェクトを返します。
$obj = $app->db->model('モデル名')->get_by_key( [ $terms, $args, $cols, $extra, $ex_vars ] );
if (! $obj->id ) {
// オブジェクトがマッチしなかった時に生成された新規オブジェクト
$obj->save();
}
loadメソッドと同じ条件でオブジェクトをカウントし、マッチした数値を返します。
$count = $app->db->model( 'entry' )->count( ['title' => 'Welcome!'] );
// 発行されるSQL文
// SELECT COUNT(entry_id) FROM mt_entry WHERE ( entry_title = 'Welcome!' );