2005-03-07 アーカイブ

http://hxxk.jp/2005/03/07/

mt_placement と mt_entry の齟齬による記事保存エラーの対処

記事データ

投稿者

望月真琴

投稿日時

2005-03-07T18:22+09:00

タグ
概要

Can't call method "status" without a package or object reference at system directory/lib/MT/Template/Context.pm line 666. で書いていた、記事の保存ができない件ですが、解決したので記録しておこうと思います。 結局は mt_placement テーブルと mt_entry テーブルのレコードの齟齬により、エラーが起こっていたようです。

リプライ

リプライはまだありません。

記事本文

解決しました

Can't call method "status" without a package or object reference at system directory/lib/MT/Template/Context.pm line 666. で書いていた、記事の保存ができない件ですが、解決したので記録しておこうと思います。

なお、 Movable Type の使用環境として、データベースに MySQL を利用し、その管理には phpMyAdmin 2.5.4 を用いました。 また、 Movable Type のバージョンは 3.151-ja です。

  1. 大まかな経緯と原因
  2. Context.pm をカスタマイズしてエラーメッセージを分かりやすくする
  3. カスタマイズ後のエラーメッセージ
  4. 復旧手順
  5. まとめ ?

大まかな原因と経緯

大まかな原因としてはデータベースの中におかしなレコードが何らかの原因で存在しており、それによって記事保存時のエラーが発生していました。 そのレコードを削除することで正常に動作するようになりました。

その原因となるレコードのおおよその作成日時も見当がつきましたが、特段おかしなことは無かったと思います。

Context.pm をカスタマイズしてエラーメッセージを分かりやすくする

Movable Type 3.151 の Context.pm の記述では、今回のようなトラブルが起こった場合に、 Can't call method "status" without a package or object reference at system directory/lib/MT/Template/Context.pm line 666. というエラーメッセージが出力されます。

私は perl について不勉強だったので、とぴあさん ( Clovery leaf pieces ) に Context.pm のソースを見ていただいたところ、 MT::Category もしくは MT::Placement あたりが怪しいとのこと。 そこで、 Context.pm の記述に一行書き加えて、以下のようにカスタマイズするよう勧められました。

for my $entry_id (@ids) {
    my $entry = MT::Entry->load($entry_id);
    if (!ref($entry)) { die "illegal entry id $entry_id on placement table"; }
    push @entries, $entry
        if $entry->status == MT::Entry::RELEASE();
}

em 要素で強調した部分が追加行です。

カスタマイズ後のエラーメッセージ

復旧に手一杯でスクリーンショットを取るのを完全に忘れていたのですが、前項のようにカスタマイズした後のエラーメッセージは以下のようになります。

エラーが発生しました:

illegal entry id 566 on placement table at system directory/lib/MT/Template/Context.pm line 666

illegal entry id 566 on placement table というのは、 mt_placement テーブルにおける placement_entry_id フィールドに、何かおかしなレコードが混じっている、といった感じの意味です。 今回のケースは placement_entry_id フィールドの値が 566 であるレコードが変だということになります。

placement_entry_id フィールドの値と、 mt_entry テーブルにおける entry_id フィールドの値が同じレコードは、同一のエントリを指しています。 例えば、 hxxk.jp 全体の現時点での最新エントリは 本日の TBS の番組はほぼ全て放送中止 ? ですが、このエントリは placement_entry_id フィールドの値も entry_id フィールドの値もどちらも 644 となっています。

復旧手順

そして、 illegal entry id 566 と示されたエントリが実際にあるかと言うと……ありません。

正確に言うと、以前下書き状態か何かで作成して、既に削除したエントリなのです。 mt_entry テーブル上にも entry_id : 566 のレコードはありません。 しかし、 mt_placement テーブル上には placement_entry_id : 566 のエントリは残っています。 他のレコードを見る限り、 Movable Type の管理画面から「エントリを削除」で削除したエントリに関するレコードは mt_entry テーブルにも mt_placement テーブルにも残らないはずです。

そこで、次のような手順で該当レコードを削除しました。

  1. まずデータベースの dump を取ります。 ( 万一に備えて、データベースをいじくる前の状態を保存するのです。 )
  2. Context.pm をカスタマイズしてエラーメッセージを分かりやすくするを参考に、 Context.pm の記述をカスタマイズし、サーバに put します。
  3. Movable Type の管理画面から、エラーとなる記事の保存を再度行います。
    1. エラーメッセージが出力されるので、その entry_id をメモします。
    2. phpMyAdmin にて、 mt_entry テーブルの entry_id フィールド上に、その id を持つレコードが無いことを確認。
    3. phpMyAdmin にて、 mt_placement テーブルの placement_entry_id フィールド上で、その id を持つレコードを消去。 ( なお、複数のカテゴリを指定したエントリの場合、カテゴリ数の分だけ同じ placement_entry_id の値を持つレコードが存在するので、消去漏れが無いように注意して下さい。 )
  4. 再度 Movable Type の管理画面から、エラーとなる記事の保存を行います。
    • 場合によっては違う entry_id でエラーメッセージが再度表示されるので、その場合は「エラーメッセージが出力されるので、その entry_id をメモします」の手順から繰り返します。
    • 記事の保存を行ってエラーが出なければ復旧完了です。

まとめ ?

結局のところ、「どういったエラーが原因で保存ができなくなっているか」は分かりましたけど、「何故このエラーが発生したのか」は分からず仕舞い。 あくまで想像ですが、「管理画面からエントリを削除した際に、何らかの原因で mt_placement テーブルに削除したはずのレコードが残ってしまった」という感じだと私は思います。 その残骸レコードを消すとエラーは無くなったわけですし。

最後に、 IRC で丁寧にエラーを探って下さったとぴあさん ( Clovery leaf pieces ) に感謝の意を込めつつ記事を締めくくろうと思います。

リプライ

リプライはまだ送られていないか、管理者の承認待ち状態です。 この記事に対するご意見やご質問、ご感想などありましたら個別記事ページの送信フォームからお送り下さい。

補足情報

著作、講演、制作実績など