MTEntryNext,Previousの拡張(とか改良?とか)。

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

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

残念ながら...かなりしんどいことになる気がします。エントリーが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;
        #    }
        # }
    }

トラックバック(1)

トラックバックURL: http://junnama.alfasado.net/cgi/mt/mt-tb.cgi/53

要は、 ブログ記事に同一カテゴリーのブログ記事の前後リンクを表示する(Movable Type 4.2/Movable Type 5対応) MTEntry... 続きを読む

コメント(1)

MT4.25に本記事のプラグインを導入してみた所、
MT:EntryNextは前記事がある時に前記事のデータを呼び出し
MT:EntryPreviousは次記事がある時に次記事のデータを呼び出す
とMT:EntryNextとMT:EntryPreviousの機能・動作が逆転するようになりました。
プラグインを無効化すれば逆転現象が起こらなくなるのでプラグインが原因だと思います。
MT:PageNextとMT:PagePreviousについては検証していないのでわかりません。

ついでにもう一つ。

TypeKey IDを使ってサインインしようとしたらエラーが発生してサインインできませんでした。
TypeKeyがTypePad Connectへ移行を始めた事と関係があるのでしょうか?

コメントする

Facebook

Twitter

このブログ記事について

このページは、Junnama Nodaが2008年11月19日 17:24に書いたブログ記事です。

ひとつ前のブログ記事は「IfEntryIsinCategoryプラグイン。」です。

次のブログ記事は「yamlで作るMTプラグイン。」です。

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

Powered by Movable Type 6.2.6