記事本文
解決しました
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 です。
大まかな原因と経緯
大まかな原因としてはデータベースの中におかしなレコードが何らかの原因で存在しており、それによって記事保存時のエラーが発生していました。 そのレコードを削除することで正常に動作するようになりました。
その原因となるレコードのおおよその作成日時も見当がつきましたが、特段おかしなことは無かったと思います。
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 テーブルにも残らないはずです。
そこで、次のような手順で該当レコードを削除しました。
- まずデータベースの dump を取ります。 ( 万一に備えて、データベースをいじくる前の状態を保存するのです。 )
- Context.pm をカスタマイズしてエラーメッセージを分かりやすくするを参考に、 Context.pm の記述をカスタマイズし、サーバに put します。
- Movable Type の管理画面から、エラーとなる記事の保存を再度行います。
- エラーメッセージが出力されるので、その entry_id をメモします。
- phpMyAdmin にて、 mt_entry テーブルの entry_id フィールド上に、その id を持つレコードが無いことを確認。
- phpMyAdmin にて、 mt_placement テーブルの placement_entry_id フィールド上で、その id を持つレコードを消去。 ( なお、複数のカテゴリを指定したエントリの場合、カテゴリ数の分だけ同じ placement_entry_id の値を持つレコードが存在するので、消去漏れが無いように注意して下さい。 )
- 再度 Movable Type の管理画面から、エラーとなる記事の保存を行います。
- 場合によっては違う entry_id でエラーメッセージが再度表示されるので、その場合は「エラーメッセージが出力されるので、その entry_id をメモします」の手順から繰り返します。
- 記事の保存を行ってエラーが出なければ復旧完了です。
まとめ ?
結局のところ、「どういったエラーが原因で保存ができなくなっているか」は分かりましたけど、「何故このエラーが発生したのか」は分からず仕舞い。 あくまで想像ですが、「管理画面からエントリを削除した際に、何らかの原因で mt_placement テーブルに削除したはずのレコードが残ってしまった」という感じだと私は思います。 その残骸レコードを消すとエラーは無くなったわけですし。
最後に、 IRC で丁寧にエラーを探って下さったとぴあさん ( Clovery leaf pieces ) に感謝の意を込めつつ記事を締めくくろうと思います。
![[改訂新版]実践 Web Standards Design - Web標準の基礎とCSSレイアウト&Tips](http://lh3.jp/files/images/2011/hopbook.png)

