wp_delete_post()はゴミ箱移動と完全削除をforce_deleteで分ける
公開日: 執筆:佐藤
wp_delete_post()の第二引数$force_deleteをfalseにしても、必ずゴミ箱へ移るとは限りません。標準の投稿または固定ページで、まだゴミ箱になく、ゴミ箱の保存日数が有効な場合にwp_trash_post()へ進みます。条件から外れると、投稿本体と関連データを完全に削除します。
削除処理を書く前に、対象の投稿形式、現在の状態、復元の要否を決めます。$force_deleteは「削除するかどうか」ではなく、「ゴミ箱を経由できる条件でも完全削除するか」を選ぶ引数です。
falseでも条件によって完全削除になる
WordPress 3.9.2のwp_delete_post()は、次の形で定義されています。
wp_delete_post( $postid, $force_delete );
第二引数の初期値はfalseです。ただし、ゴミ箱へ移す分岐には複数の条件があります。
$force_deleteがfalseである- 投稿形式が
postまたはpageである - 現在の状態が
trashではない EMPTY_TRASH_DAYSが有効である
すべてを満たすと、wp_delete_post()はwp_trash_post()の結果を返します。ゴミ箱にある投稿をもう一度渡す、ゴミ箱の保存日数が無効、または標準の投稿と固定ページ以外という場合は、この分岐を通りません。
したがって、次のコードは「安全のため必ずゴミ箱へ移すコード」ではありません。呼出し前に対象の投稿形式と状態を確認する必要があります。
// $post_id、権限、requestの正当性を確認した後の説明用コード
$result = wp_delete_post( $post_id, false );
if ( ! $result ) {
// 対象がない、または削除に失敗した場合の処理
}
復元可能な操作だけを許す機能なら、対象をpostまたはpageへ限定し、現在の状態を確認してwp_trash_post()を呼ぶ方が意図を示しやすくなります。
trueは標準投稿のゴミ箱を経由しない
第二引数へtrueを渡すと、標準の投稿と固定ページでもゴミ箱へ移す分岐を通りません。
// 復元不要と確認し、権限とrequestを検証した後だけ実行する説明用コード
$result = wp_delete_post( $post_id, true );
完全削除は、管理画面で一覧から見えなくする処理ではありません。投稿rowを消す前後に、分類、版、コメント、post metaなどの関連データも処理します。実行後にWordPressのゴミ箱から戻すことはできません。
完全削除を使う理由が「一覧へ出したくない」だけなら、非公開、下書き、ゴミ箱のどれで目的を満たせるかを先に確認します。完全削除は、復元不要で、関連データへの影響まで受け入れられる場合に限定します。
完全削除では関連データも処理される
WordPress 3.9.2の処理は、投稿rowだけを削除するものではありません。
| 対象 | 完全削除時の処理 |
|---|---|
| categoryやtagなど | 投稿とのterm relationshipを削除する |
| revision | 対象投稿のrevisionを削除する |
| comment | 対象投稿に付くcommentを完全削除する |
| post meta | 対象投稿のpost metaを削除する |
| 階層を持つ同形式の子投稿 | 削除対象の親へ付け替える |
| attachment | 削除対象へ属するattachmentの親を一階層上へ付け替える |
| 予約公開の予定 | publish_future_postの予定を解除する |
親投稿を消したからといって、その投稿に添付されたmedia fileまで一緒に消す処理ではありません。attachmentは親を付け替えられます。一方、削除対象そのものがattachmentなら、wp_delete_post()はwp_delete_attachment()へ処理を渡します。投稿削除とmedia削除を同じものとして扱わないでください。
分類のtermそのものも、この処理だけで削除するわけではありません。削除するのは、投稿とtermの関係です。ほかの投稿が同じcategoryやtagを使っていれば、termは別に管理されます。
カスタム投稿タイプとattachmentは別に確認する
$force_deleteがfalseなら何でもゴミ箱へ入る、という前提はカスタム投稿タイプで使えません。WordPress 3.9.2のwp_delete_post()がゴミ箱へ送る条件は、投稿形式をpostまたはpageへ限定しています。
カスタム投稿タイプを削除するコードでは、次を先に決めます。
- 復元できる操作として提供するのか。
- 関連するterm、comment、post metaを消してよいのか。
- 階層型なら子投稿をどの親へ移すのか。
- attachmentの親が変わっても運用上問題がないか。
- plugin独自tableなど、
wp_delete_post()の外にある関連データを誰が処理するのか。
hookを使うpluginやthemeもあります。before_delete_post、delete_post、deleted_post、after_delete_postで別の処理が動く可能性があるため、本番データへ直接試さず、同じ構成の検証環境で関連処理を確認します。
権限とrequestの確認は呼出し側が行う
wp_delete_post()は、指定されたIDを削除する低い層の処理です。関数内では、現在の利用者がその投稿を削除できるか、送信されたrequestが管理画面の操作から来たかを確認しません。
管理画面のformや独自の処理から呼ぶ場合は、呼出し前に少なくとも次を確認します。
- 投稿IDを整数として受け取り、取得した投稿が想定する投稿形式か
current_user_can()で、その投稿を削除できる権限があるか- form送信ならnonceを発行し、受信側で同じactionを検証したか
- ゴミ箱移動と完全削除のどちらを利用者が選んだか
- 完全削除前に必要なbackupまたはexportがあるか
functionを呼ぶ作業と、削除してよいと判断する責任は同じではありません。制作会社やpluginへ実装を委託しても、削除対象、復元期限、backup、実行権限、独自データの扱いはサイト所有者が確認できる形で残します。
最初の一手は、wp_delete_post()の呼出し箇所を探し、第二引数だけでなく、対象の投稿形式と現在の状態を書き出すことです。falseを渡しているという理由だけで復元可能だと判断せず、完全削除へ進む条件と、呼出し前の権限確認を一緒に点検します。
関連記事

