Backport(バックポート) #3772
完了fileを参照するテーブル(activity_imageなど)のレコード削除時に対応するfileレコードが削除されない
100%
説明
Overview (現象)¶
メンバーのプロフィール画像やコミュニティ画像などの file テーブルを介して格納される画像について、ブラウザ上で画像を変更・削除しても対応する file, file_bin レコードがデータベース上に残ったまま削除されない。
削除されずに残った画像は管理画面のアップロード画像リスト (/pc_backend.php/monitoring
) からも確認できる。
対象となるテーブル:
- OpenPNE コア
- opAlbumPlugin (#2447)
- album
- album_image
- opCommunityTopicPlugin (#2591)
- community_event_image
- community_event_comment_image
- community_topic_image
- community_topic_comment_image
- opDiaryPlugin (#106 修正済み)
- diary_image
- diary_comment_image
- opMessagePlugin (#190)
- message_file
Causes (原因)¶
HogeImage:
columns:
id: { type: integer(4), primary: true, autoincrement: true }
hoge_id: { type: integer(4), notnull: true }
file_id: { type: integer(4), notnull: true }
relations:
Hoge: { onDelete: cascade }
File: { onDelete: cascade }
例えば上記の様な DB スキーマの定義があったとき、外部キー制約があるため file のレコードが削除されると対応する hoge_image のレコードが削除されるが、逆に hoge_image のレコードが削除されても file のレコードは削除されない。そのため hoge_image のレコードを削除する際に対応する file のレコードを明示的に削除する必要がある。
Way to fix (修正内容)¶
HogeImage を削除する際に関連する File が削除されるようにする¶
class HogeImage extends BaseHogeImage
{
public function preDelete($event)
{
$this->File->delete();
}
}
File を参照するモデルのクラスに preDelete()
メソッドを定義し、その中で $this->File->delete();
を実行することで関連する file テーブルのレコードも削除されるようになる。
Hoge を削除する際に関連する HogeImage を明示的に削除する¶
hoge のレコードを削除した場合は、外部キー制約の ON DELETE CASCADE
によりそれを参照する hoge_image のレコードも削除される。しかしこれは DBMS 側で行われるもので Doctrine は関知しないため、削除時に HogeImage::preDelete()
は実行されない。
これでは Hoge の delete() メソッドを呼び出した場合には前述の修正に関わらず File から画像が削除されず残ってしまうため、Hoge::preDelete()
から $this->HogeImage->delete();
を明示的に呼び出す必要がある。
class Hoge extends BaseHoge
{
public function preDelete($event)
{
// HogeImage::preDelete() を実行させるために明示的に削除する
$this->HogeImage->delete();
}
}