PowerCMS X ブログ

2021-07-05

様々な条件でSELECT文を生成する (PADOBaseModel の loadメソッド詳説)

PADOBaseModelクラスの loadメソッドとは PowerCMS Xでデータベースに対して SELECT文を発行するしくみで、PowerCMS Xのデータベース操作の肝となるメソッドです。

PADOBaseModelクラスのオブジェクト生成

PowerCMS X (Prorotypeクラス) のオブジェクトが $app の時、$app->db が PADOクラス、さらに、以下のようにしてオブジェクトを生成します。

$app = Prototype::get_instance();
$entry = $app->db->model( 'entry' ); // PADOBaseModel (記事モデル)

PowerCMS Xのデータベースのスキーマと命名規則

テーブル名は 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_)やカラム名の先頭の「モデル名_」は省略して指定します。

loadメソッドのベーシックなサンプル

$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=?;

loadメソッドの詳説

SELECT文を発行してオブジェクトを返します。

$app->db->model('モデル名')->load( [ $terms, $args, $cols, $extra, $ex_vars ] );

パラメタ

  1. mixed $terms : 数値(ID) または、カラム名と値の配列、またはSQL文
  2. array $args : ソート順やlimit/offset等のオプションの配列、または第一引数にSQL文を指定した時は placeholderの配列
  3. mixed $cols : SELECT対象のカラム(配列またはカンマ区切りの文字列)または'*' (すべて)
  4. string $extra : SELECT文の WHERE句に追加する SQL(インジェクション対策はコード中で行う必要があることに注意)
  5. array $ex_vars : 第4引数に指定した placeholder に対する値の配列

戻り値

  • mixed $objects(s) : 数値(ID)を渡した時は単一のオブジェクト、それ以外の時はオブジェクトの配列

1. ID指定で単一のレコードを取得

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が返ります。

2. 配列(ハッシュ) $terms 指定での load

第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';

3. 第2引数 $args の指定

第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」であっても、返り値は常に配列となることに注意してください。

第2ソートキーの指定

キー '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' );

4. 第3引数 $cols の指定

第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';

5. 第4引数 $extra の指定

第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);

6. 第5引数 $ex_vars の指定

第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;

7. 第1引数にSQL文を指定する

数値や $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 );

8. 第1引数にSQL文を指定した時は、第2引数に placeholderに対応する値の配列を指定

$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メソッドとよく似たメソッド

loadメソッドとよく似たメソッドに以下のメソッドがあります。

load_iter メソッド

戻り値が PDOStatement であることを除き、loadメソッドとの違いはありません。

$sth = $app->db->model('モデル名')->load_iter( [ $terms, $args, $cols, $extra, $ex_vars ] );
$objects = $sth->fethAll();

get_by_key メソッド

loadメソッドを呼び出し、該当するものがある時、最初にマッチした単一のオブジェクトを返します(配列ではなく、単一のオブジェクトが返ります)。
該当するものがない時は、$termsが配列指定の時、その条件でオブジェクトを新規に生成し(第2引数以下の引数は無視されます)、単一のオブジェクトを返します。

$obj = $app->db->model('モデル名')->get_by_key( [ $terms, $args, $cols, $extra, $ex_vars ] );
if (! $obj->id ) {
    // オブジェクトがマッチしなかった時に生成された新規オブジェクト
    $obj->save();
}

countメソッド

loadメソッドと同じ条件でオブジェクトをカウントし、マッチした数値を返します。

$count = $app->db->model( 'entry' )->count( ['title' => 'Welcome!'] );
// 発行されるSQL文
// SELECT COUNT(entry_id) FROM mt_entry WHERE ( entry_title = 'Welcome!' );

カテゴリー:技術情報 | プラグイン

投稿者:Junnama Noda

ブログ内検索

アーカイブ