プロジェクト

全般

プロフィール

Bug(バグ) #3738

Youichi Kimura さんがほぼ10年前に更新

h3. Overview (現象) 

 メンバーのプロフィール画像やコミュニティ画像などの file テーブルを介して格納される画像について、ブラウザ上で画像を変更・削除しても対応する file, file_bin レコードがデータベース上に残ったまま削除されない。 

 削除されずに残った画像は管理画面のアップロード画像リスト (@/pc_backend.php/monitoring@) からも確認できる。 

 対象となるテーブル: 

  * OpenPNE コア 
  ** activity_image (#3752) 
  ** banner_image 
  ** community (#3753) 
  ** 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) 
   { 
     $this->File->delete(); 
   } 
 } 
 </code></pre> 

 File を参照するモデルのクラスに @preDelete()@ メソッドを定義し、その中で @$this->File->delete();@ を実行することで関連する file テーブルのレコードも削除されるようになる。 

 h4. Hoge を削除する際に関連する HogeImage を明示的に削除する 

 hoge のレコードを削除した場合は、外部キー制約の @ON DELETE CASCADE@ によりそれを参照する hoge_image のレコードも削除される。しかしこれは DBMS 側で行われるもので Doctrine は関知しないため、削除時に @HogeImage::preDelete()@ は実行されない。 
 これでは Hoge の delete() メソッドを呼び出した場合には前述の修正に関わらず File から画像が削除されず残ってしまうため、@Hoge::preDelete()@ から @$this->HogeImage->delete();@ を明示的に呼び出す必要がある。 

 <pre><code class="php"> 
 class Hoge extends BaseHoge 
 { 
   public function preDelete($event) 
   { 
     // HogeImage::preDelete() を実行させるために明示的に削除する 
     $this->HogeImage->delete(); 
   } 
 } 
 </code></pre> 

戻る