2008年11月アーカイブ

# 何回も書いてる気がするなぁ、これ。

残念ながら...かなりしんどいことになる気がします。エントリーが1,000あって、最初と最後のエントリーだけが「カテゴリーA」に属していて、500番目のエントリーを「カテゴリーA」にしよう、と思ったら(伝わるかな?)

    my $terms;
$terms->{category_id} = $cat->id;
my $prev = $e->previous(1, $terms);
my $res = '';
while ($prev && !$prev->is_in_category($cat)){
$terms->{category_id} = $cat->id;
$prev = $prev->previous(1, $terms);
}

500番目のエントリーから始まって、ひとつ前エントリーを読み込んで(ここで1回SQL投げる)のカテゴリチェック、違ったら次のエントリーの、ってのを500回程繰り返してエントリー1まで来て、お! あったあった。で、今度はNext処理で500回程...(以下略...ってか、これ以前に500エラーになるかもしれません)

いささか極端な例ですが、いずれにしても効率が良くありません (この件については以前にも書いてますね)。

ちなみに、$terms->{category_id}は効きません(多分(追記:MT2.x?の頃は効いたのではないかな。category_idがmt_entryテーブルのカラムだった時代))。$terms->{by_category} が指定できるっぽいですがMT4.2ではエラーになります(MT4.1ならOK。そもそも4.1ならドキュメントにはありませんが by_category="1" と by_author="1" がテンプレートタグのモディファイアで指定できるようになっています)。

本題。

/lib/MT/Object.pmの sub nextprev が4.1→4.2で変わっていて、

    # Selecting the adjacent object can be tricky since timestamps
# are not necessarily unique for entries. If we find that the
# next/previous object has a matching timestamp, keep selecting entries
# to select all entries with the same timestamp, then compare them using
# id as a secondary sort column.

ああ、これ考えてたんだ...全く同じタイムスタンプのエントリーが複数あったときにどーすんだっていう件。4.1ではエントリーをループの中で比較して、タイムスタンプが同じだったらidで比較してるみたい。MT4.2ではSQL一発にシンプルに変更されているのですが、おそらくこの部分が関係して<MTEntryNext by_category="1">でウチの環境ではエラーを吐いてしまいます。ドキュメントには(多分)ないのでバグではなく仕様? なのかもしれないけど、標準でサポートされると幸せになれる人が多いかも。

で、もう一つ。not指定してるので確かにそのエントリー自身は出て来ないですが同一タイムスタンプの時の挙動(前後の指定)が (ウチの環境では) おかしい (複数のページで同じエントリーが出てくる)。

レアケースっていえばレアケースだけど、気持ち悪いので作りました。

  • mt:entrynext,mt:entryprevious,mt:pagenext,mt:pagepreviousタグを上書きします。
  • 同じタイムスタンプのエントリーが複数あったときはentry_idで比較して順番を決めます。
  • by_category="1" と by_author="1" が指定できます(同一カテゴリー/投稿者のエントリーの前後を取得できます)。
  • by_field="modified_on"のようにソートのカラムを指定できます(デフォルトはcreated_on)

例:

<mt:entrynext by_author="1" by_category="1" by_field="created_on">
<a href="<mt:entrypermalink>"><mt:entrytitle="escape="html"></a>
</mt:entrynext>

21:00追記
よく考えたら2つのキーで同時にソートできるわ。

$terms->{ id } = { '<' => $entry->id };
$params->{ limit } = 1;

以下修正箇所。これでload_iterでループさせる必要がなくなった。最多でもオブジェクト2つから特定できるようになったな。これでどうでしょう?

     if ( $count > 1 ) {
if ( $meth eq 'next' ) {
$terms->{ id } = { '<' => $entry->id };
} else {
$terms->{ id } = { '>' => $entry->id };
}
$params->{ limit } = 1;
my $e = $class->load( $terms, $params );
return $e if defined $e;
# my $iter = $class->load_iter( $terms, $params );
# my $match;
# while ( my $e = $iter->() ) {
#    return $e if $match;
#    last if $match;
#    if ( $e->id == $entry->id ) {
#        $match = 1;
#    }
# }
}

Q(俺):カテゴリーのループの中で、自分(エントリー)が属している場合に真を返すMTタグってあんの?

A(まくあぷ担当):IDとかLabelをSetVarしてですね...

(俺)嘘、あり得へん!

<select name="toplevelcategoy">
<mt:toplevelcategories>
<option value="<mt:categoryid>"
<mt:ifentryisincategory>selected="selected"</mt:ifentryisincategory>>
<mt:categorylabel>
</option>
</mt:toplevelcategories>
</select>

備忘録。エントリーをカテゴリーID順にソートしてロードする(join, join_on)。

my $blog      = $app->blog;
my $class     = 'entry';
my $direction = 'derection';
my $offset    =  0;
my $limit     = 10;
my $terms = { 
blog_id => $blog->id,
class   => $class,
status  => MT::Entry::RELEASE(),
};
my $params = { join => MT::Placement->join_on( 'entry_id',
{ is_primary => 1 },
{ sort => 'category_id',
direction => $direction,
unique => 1,
offset => $offset,
limit => $limit, } )
};
my @entries = MT::Entry->load( $terms, $params );

カテゴリー指定のないエントリーは取り出せない。

久しぶりに書いたと思ったらMTネタ本日3発目!

CMSContextプラグインにentry_idモディファイアを渡すとそのIDのエントリーのctxがセットされるようにした。

<mt:cmscontext entry_id="$id">
<!--ここでエントリーの各種データを取り出せます。-->
</mt:cmscontext>

どんなところで使うの? (多分、こんな使い方する人殆どおらんと思うけど...思うんやけどね、ウチでは日常茶飯事なのです)

ブログ記事とかウェブページの一覧画面で、tmpl/cms/include/entry_table.tmpl(alt-tmplとかで代替テンプレートを指定して)のtrタグから/trタグを<mt:cmscontext entry_id="$id">〜</mt:cmscontext>で囲む。と、各エントリーのカスタムフィールド値とかがブログ記事とかウェブページの一覧画面で取り出せます。

MT::Entryを毎行ごとにロードしてるので無駄っちゃぁ無駄だけど、各行のctxに突っ込まれてないから仕方ない。

※ 例:一番右側の「東京」とか「大阪」ってのがカスタムフィールドの値を取り出してるところです。

拡張したエントリー一覧画面

MTCSの拡張とか。

| コメント(0) | トラックバック(0)

MTCSでコミュニティ系のサイトを作る時にMTCSのプロフィールの編集画面からプロフィールを保存した時に処理を割り込ませたいって時、ありますよね(え、無い?)。mt_authorを拡張して(正確にはmt_authorテーブルを拡張するとエラーになっちゃうからauthor_metaとか別のテーブルとか作ってユーザーのいろんなデータを保存したい時(且つ独自拡張した項目の必須項目チェックしたい)とか。

標題の「MTCSの拡張」に限らずこの手の拡張をする時にコードに手を入れずに該当の処理をオーバーライドする方法についてのメモ。

1.プラグイン(アドオン)のIDを調べて(この場合は「community」)

/mt/addons/Community.pack/lib/MT/App/Community.pm

#(略)
sub id { 'community' }
#(略)

2.上書きしたい部分はどこか? を探して

/mt/addons/Community.pack/config.yaml

name: Community Pack
#(中略)
applications:
cms:
methods:
#(中略)
community:
handler: MT::App::Community
methods:
#(中略) ↓ココ
save: $Community::MT::App::Community::save_profile_method

3.プラグインで上書きする

sub init {
my $community = MT->component( 'community' );
my $r = 
$community->registry( 'applications', 'community', 'methods' );
$r->{save} = ¥&save_profile_method;
}
sub save_profile_method {
# ここにオーバーライドする処理を書く!
}

MT::Core(メソッドとかテンプレートタグ)を上書きする場合はcomponent('core')に対してオーバーライドする。

sub init {
my $core = MT->component('core');
my $r = $core->registry('tags', 'block');
$r->{Entries} = ¥&_hdlr_entries;
}

と、いうことで、さぁ、コミュニティサイトをつくろう(笑)!

税抜き価格から税込み価格を算出して、切り捨て、切り上げ、四捨五入して、3桁ごとにカンマ入れて出力する...ってどうやるの?

<p>四捨五入</p>
<MTSetVarBlock name="RoundValue">
<SCRIPTlanguage="JavaScript">
<!--
document.write(Math.round(4.321));
//-->
</SCRIPT>
</MTSetVarBlock>
<MTGetVar name="RoundValue">

ううむ...JavaScriptなのか?

ううむ...プラグインなのか? (今回はダイナミックパブリッシングなんだよ...)

面倒くさいのは面倒くさいけどできないこともないよーな気がしてさ。

例:entrypriceというカスタムフィールドを作って税抜き価格(数字)を入れておいて、税込み価格計算して切り捨て、切り上げ(小数点以下1桁)、四捨五入して3桁ごとにカンマ入れて出力する。

<mt:setvarblock name="price"><mt:entryprice></mt:setvarblock>
税抜価格: <$mt:var name="price" numify=","$> 円<br />
<mt:setvarblock name="price"><$mt:var
name="price" value="1.05" op="*"$></mt:setvarblock>
税込価格: <$mt:var name="price" numify=","$> 円<br />
<mt:setvarblock
name="one_tenth"><$mt:var name="price"
regex_replace="/^[0-9]*¥.(.).*$/","$1"$></mt:setvarblock>
<mt:setvarblock name="price"><$mt:var
name="price" regex_replace="/¥..*/",""$></mt:setvarblock>
切り捨て: <$mt:var name="price" numify=","$> 円<br />
切り上げ:
<mt:if name="one_tenth" ne="$price">
<mt:if name="one_tenth" gt="0">
<$mt:var name="price" op="+" value="1" numify=","$>
<mt:else>
<$mt:var name="price" numify=","$>
</mt:else>
</mt:if>
<mt:else>
<$mt:var name="price" numify=","$>
</mt:else>
</mt:if>
円
<br />
四捨五入:
<mt:if name="one_tenth" ne="$price">
<mt:if name="one_tenth" gt="4">
<$mt:var name="price" op="+" value="1" numify=","$>
<mt:else>
<$mt:var name="price" numify=","$>
</mt:else>
</mt:if>
<mt:else>
<$mt:var name="price" numify=","$>
</mt:else>
</mt:if>
円

ウェブページ

OpenID対応しています OpenIDについて
Powered by Movable Type 5.04

このアーカイブについて

このページには、2008年11月に書かれたブログ記事が新しい順に公開されています。

前のアーカイブは2008年10月です。

次のアーカイブは2008年12月です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。