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>
円

Facebook

Twitter

このアーカイブについて

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

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

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

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

Powered by Movable Type 6.2.6