Bug(バグ) #3738
Youichi Kimura さんがほぼ10年前に更新
h3. Overview (現象) メンバーのプロフィール画像やコミュニティ画像などの file テーブルを介して格納される画像について、ブラウザ上で画像を変更・削除しても対応する file, file_bin レコードがデータベース上に残ったまま削除されない。 削除されずに残った画像は管理画面のアップロード画像リスト (@/pc_backend.php/monitoring@) からも確認できる。 対象となるテーブル: * OpenPNE コア ** activity_image ** banner_image ** community ** member_image (#453 **修正済み**) ** oauth_consumer * 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 h3. Causes (原因) <pre><code class="yaml"> 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 } </code></pre> 例えば上記の様な DB スキーマの定義があったとき、外部キー制約があるため file のレコードが削除されると対応する hoge_image のレコードが削除されるが、逆に hoge_image のレコードが削除されても file のレコードは削除されない。そのため hoge_image のレコードを削除する際に対応する file のレコードを明示的に削除する必要がある。 h3. Way to fix (修正内容) h4. HogeImage を削除する際に関連する File が削除されるようにする <pre><code class="php"> class HogeImage extends BaseHogeImage { public function preDelete($event) postDelete($event) { $this->File->delete(); } } </code></pre> File を参照するモデルのクラスに @preDelete()@ @postDelete()@ メソッドを定義し、その中で @$this->File->delete();@ を実行することで関連する file テーブルのレコードも削除されるようになる。 h4. Hoge を削除する際に関連する HogeImage を明示的に削除する hoge のレコードを削除した場合は、外部キー制約の @ON DELETE CASCADE@ によりそれを参照する hoge_image のレコードも削除される。しかしこれは DBMS 側で行われるもので Doctrine は関知しないため、削除時に @HogeImage::preDelete()@ @HogeImage::postDelete()@ は実行されない。 これでは Hoge の delete() メソッドを呼び出した場合には前述の修正に関わらず File から画像が削除されず残ってしまうため、@Hoge::preDelete()@ から画像が削除されず残ってしまうため、@Hoge::postDelete()@ から @$this->HogeImage->delete();@ を明示的に呼び出す必要がある。 <pre><code class="php"> class Hoge extends BaseHoge { public function preDelete($event) postDelete($event) { // HogeImage::preDelete() HogeImage::postDelete() を実行させるために明示的に削除する $this->HogeImage->delete(); } } </code></pre>