MovableTypeでサイトを構築していると、カスタムフィールドを使ってあれやこれや結構ややこしいことをしたくなります。(JOINまみれになるのであんまりよくないのですが・・・)
その場合、プラグインを作ったりするのですが、カスタムフィールドで検索するのに search_by_meta
を使うのが便利です。
Loading any Object (Entry, Page...) Based on a Custom Field Value
そんな search_by_meta
ですが、実は第三引数と第四引数で検索条件を追加で指定することができます。(MT5.2で確認)
=item * Class->search_by_meta( $key, $value, [ \%terms [, \%args ] ] )
Returns objects that have a C<$key> metadata value of C<$value>. Further restrictions on the class may be applied through the optional C<%terms> and C<%args> parameters.
メタテーブル(mt_entry_meta
)で検索する
注意すべきは検索条件といっても、メタテーブルの検索条件と言うこと。
メタテーブルとはたとえば記事テーブル mt_entry
に対する mt_entry_meta
のこと。
たとえばオブジェクトのIDで絞り込むなら以下のような感じでOK
my $class = MT->model( 'entry' );
my @ids = (1, 2, 3);
my %terms = ( entry_id => \@ids );
my %args = ();
my @entries = $class->search_by_meta( 'field.field_name',
'somevalue',
\%terms,
\%args );
発行されるSQLはこうなる。
SELECT entry_meta_entry_id
FROM mt_entry_meta, mt_entry
WHERE
(entry_meta_entry_id IN ('1','2', '3')) AND
(entry_meta_vchar_idx = 'somevalue') AND
(entry_meta_type = 'field.field_name')
対象のオブジェクトのテーブルで(mt_entry
)検索したい
JOINを使うことで mt_entry
のカラムを検索条件に含めることができる。
たとえば、ある期間内に公開された記事に対して、カスタムフィールドで検索をかけるには以下のようにする。
my $class = MT->model( 'entry' );
my $start = '20131001000000'; # 2013/10/01
my $end = '20131031000000'; # 2013/10/31
my %join_terms = (
id => \"= entry_meta_entry_id",
authored_on => [$start, $end],
);
my %join_args = (
range => {
authored_on => 1
}
);
my %terms = ();
my %args = (
'join' => $class->join_on(undef, \%join_terms, \%join_args)
);
my @entries = $class->search_by_meta( 'field.field_name',
'somevalue',
\%terms,
\%args );
この場合発行されるSQLはこうなる。
SELECT entry_meta_entry_id
FROM mt_entry_meta, mt_entry
WHERE
(entry_meta_vchar_idx = 'somevalue') AND
(entry_meta_type = 'field.field_name') AND
(
(entry_authored_on > '2013-10-01 00:00:00') AND
(entry_authored_on < '2013-10-31 00:00:00')
) AND
(entry_id = entry_meta_entry_id)
なお、 entry_meta_entry_id
をハードコーディングするのが気持ち悪ければ以下のような感じで無理矢理作ることもできるっぽい。
my $meta_class = $class->meta_pkg;
my $meta_pk = $meta_class->primary_key_tuple->[0]; # entry_id
my $col = $meta_class->datasource . '_' . $meta_pk; # entry_meta_entry_id
カスタムフィールドの仕様上JOINだらけになるのはやむを得ない。 が、がんばればこのように生SQLに頼らず検索することはできる。
参考