PrestaShopのグローバル設定テーブルの仕組みにより、モジュールのアンインストールルーチンが、全く無関係な拡張機能に属する設定を誤って消去してしまうことが容易に起こり得ます。Configuration::deleteByName('width') を一度呼び出すだけで、別のショップのカスタム幅の値を消去してしまうことがあり、ショップオーナーを困惑させ、問題のモジュールは一見無害に見えるまま放置されてしまいます。
なぜ共有設定テーブルが重要なのか
PrestaShopは、すべてのモジュールの設定を、キーと値のみを保持する単一のテーブルに保存しています。このテーブルには、どのモジュールがその行を作成したかを記録するカラムはなく、命名規則も強制されません。その結果、「width」や「API_DATE_FROM」といった同じキーを偶然使用した2つのモジュールは、同じデータベース行を読み書きすることになります。最後に書き込まれた値が優先され、その後の削除操作は両方のモジュールに対してその行を削除してしまいます。
アンインストールコードがデータ消去ツールと化すとき
一般的なアンインストールメソッドは以下の通りです:
public function uninstall()
{
return Configuration::deleteByName('width');
}
意図としてはモジュール自身の設定をクリーンアップすることですが、キーに名前空間(namespace)が設定されていないため、そのステートメントは「width」という名前のあらゆる行を削除してしまいます。警告ログも出ず、例外もスローされません。行はただ消えるだけです。ショップオーナーの他のモジュールは、静かに設定を失い、動作が不安定になる可能性があります。
この問題は、バージョンアップの際に特に発生しやすくなります。バージョン1.0から2.0へ移行する開発者は、MY_MODULE_WIDTHのような接頭辞(prefix)付きのキーで値を保存し始めるかもしれません。古い接頭辞のないエントリを「クリーンアップ」するために、レガシーデータのみを削除しているつもりで、アンインストールルーチンに削除呼び出しを追加します。しかし実際には、同じ汎用的なキーの下に保存されている他の拡張機能のデータも削除してしまっているのです。
監査で判明したこと
57個の公開モジュールリポジトリを監査した結果、繰り返されるパターンが明らかになりました:
- 多くのモジュールが、モジュール名に由来する接頭辞なしで、「width」、「height」、「API_DATE_FROM」といった汎用的なキーを使用しています。
- いくつかのアンインストールメソッドには、これらの汎用的なキーを対象とした
Configuration::deleteByNameの呼び出しが含まれています。 - この問題は特定の開発者や特定の種類のモジュールに限ったことではなく、共有テーブルの設計自体がシステム的なリスクとなっています。
監査では、他のモジュールの設定が削除されたことをショップオーナーに知らせるようなログやエラーメッセージは見つかりませんでした。唯一の症状は、設定が突然失われることであり、ショップオーナーはそれをキャッシュの問題や自身のコードのバグによるものだと考えてしまうかもしれません。
モジュール開発者のためのより安全なプラクティス
- すべてのキーに名前空間を適用する – すべての設定キーの先頭にモジュールの技術的な名前を付加します(例:
my_module_width)。これにより、個別の所有権カラムに頼ることなく、一意の識別子を作成できます。 - 古い接頭辞のないキーの削除を避ける – テーブル内にいくつかの古い行を残しておいても、ストレージへの影響はほとんどなく、二次被害のリスクを排除できます。
- 削除前に所有権を確認する – 削除が本当に必要な場合は、まずそのキーの値が自身のコードによって設定されたものであることを確認してください(例えば、そのモジュールだけが知っているマーカー値を保存しておくなど)。
- アンインストールメソッドを監査する – コードベース内で
deleteByNameの呼び出しを検索します。各箇所を確認し、キーに一意の名前空間が設定されていることを確認する必要があります。 - 命名規則を文書化する – モジュールのREADMEに短いガイドラインを含め、将来のコントリビューターが接頭辞付きキーの重要性を理解できるようにします。
モジュール間での誤った削除をテストする方法
本番環境のショップに到達する前にバグを検出するための実用的な方法:
- 設定テーブルにデータを投入する – 別のモジュールに属するキー(例:
other_module_setting=>test)をあらかじめ設定しておきます。 - 制御された環境でモジュールのアンインストールルーチンを実行します。
- アンインストール完了後、投入したキーがまだ存在していることを検証(Assert)します。
モジュールのユニットテストスイートでこのチェックを自動化することで、将来的に誤った deleteByName の呼び出しが導入された場合にテストが失敗し、レビューを促すことができます。
ショップオーナーが注意すべき点
ショップオーナーがデータベースの内部行を目にすることはめったにありませんが、症状に気づくことはできます。モジュールを無効化またはアンインストールした後、別の拡張機能の設定が突然デフォルトに戻ってしまう場合です。もしそのようなことが起きたら、開発者にモジュールのアンインストールコードがグローバル設定テーブルを適切に扱っているか確認するよう依頼してください。モジュールが使用するすべての設定キーのリストを要求し、明確な接頭辞のないキーがあれば、それは警告サインです。
まとめ
PrestaShopの設計では、設定テーブルが共有リソースとなっているため、不注意なアンインストール処理によって、他のモジュールの設定が跡形もなく消去されてしまう可能性があります。キーに名前空間を設け、過度なクリーンアップを控え、他モジュールのエントリを保護するシンプルなテストを追加することで、開発者はサイレントなデータ消失を防ぎ、マーチャントのショップの安定性を維持できます。必要な労力は最小限ですが、設定が失われた際のコスト(顧客からの苦情、サポートチケットの増加、評判の低下など)は、はるかに大きくなる可能性があります。
