【WordPress】古い記事を削除するスクリプトを作ってみた

 

 

 

概要

 

自動投稿で毎日画像ファイルをアップしているといつのまにかサーバー容量がいっぱいになっていることがよくあります。そこで、投稿記事と関連ファイルを対象に古いデータを削除するスクリプトを作ってみました。

 

 

 

環境

 

IDCFクラウド環境

  • サーバー  (仮想マシン・ハードウェア専有マシン)
    S1:200円

  • ボリューム(ディスク)
    基本 15GB:300円

  • オブジェクトストレージサービス
    50GB未満無料
    https://www.idcf.jp/cloud/storage/

  • WordPress仮想マシンKUSANAGIテンプレート使用

 

データベース接続ツールが何も入っていないのであれば、インストールする必要があります。有名なところではphpMyAdminですが、もっと軽くてインストールが簡単なadminerをインストールしてみました。

 

 

 

 

プラグインで削除する方法

 

GOOGLEでキーワードに「WordPress」、「古い記事」、「削除」あたりを入力して検索するとWordPressの削除に関する記事がいろいろできてきます。

「Bulk Delete」というプラグインが最初にでてきたので、早速インストールしてみましたが有料版を購入しないと自動では削除できないようです。

 

 

 インストールして有効化したら、サイドバーに現れます。 投稿記事の一括削除は、「Bulk Delete Posts」を選択します。 他にも、ページごとなどのオプションもありますが、不要なら無視して構わないでしょう。 ちなみにスケージュール設定から自動で削除する設定もできますが、有料版のみとなっています。 月に1回とか、たまにやってあげれば十分だし、削除するのに有料版は不要でしょう。

お金を払ってまで自動化することはないので、Bulk Deleteはいったんあきらめて他を探してみましたが、自動削除のプラグインはほとんど見当たりません。確かに、自動バックアップはあっても自動削除は怖くて使えないのかもしれません。

やっぱり、古いデータをデータベースから自動で削除する仕組みを自分でつくるしかないようです。

 

 

 

投稿関連データのデータ構成

 

WordPressのデータベース構造について調べてみました。

 

WordPressデータベースのER図を見ると、WordPressがさまざまな機能を持つ割にとてもシンプルなテーブル構成です。しかし、その分一つのテーブルに様々な意味を持たせるため、データ構造は複雑になります。

 

次のデータベース関連図およびテーブル一覧はWordPressリファレンス「WordPress codex日本語版 データベース構造」より引用しました

データベース関連図

テーブル一覧

テーブル名 説明 関連インターフェース画面
wp_commentmeta コメントにはメタデータと呼ばれる情報があり、wp_commentmetaに格納されている。
wp_comments WordPress へのコメント・トラックバック・ピンバックデータを格納
wp_links リンク作成で入力されたリンク情報を格納。(この機能は非推奨になりましたが、Links Manager プラグインで有効化できます)
wp_options 管理 > 設定で設定されたオプション設定情報を格納(オプション設定リファレンス参照)。プラグインの設定情報が格納されることも多い。
wp_postmeta メタデータという各投稿記事特有の情報を格納。カスタムフィールドとして使用するほか、各投稿に情報や設定を付加するようなプラグインが、その情報を当テーブルに追加することがある。

(カスタムフィールド)

wp_posts WordPress データの核である投稿記事のほか、ページ、ナビゲーションメニューのデータを格納
wp_terms 投稿およびリンクの分類(カテゴリ・タグ)に使われる語句の基本情報を格納
wp_term_relationships オブジェクト(wp_posts テーブルの各投稿記事wp_links テーブル内の各リンク)と wp_term_taxonomy の(少なくとも 1)カテゴリ・タグとの関連付け情報を格納
wp_term_taxonomy 投稿およびリンクの分類上の語句(カテゴリ・タグ)データを格納
wp_usermeta 各ユーザ特有のユーザ・メタデータを格納
wp_users 登録ユーザ情報を格納

 

実際に、WordPressのデータベースをのぞいてみます。

 

画像データを挿入した記事の場合、投稿データも画像データ(画像ファイルを管理するレコード)もおなじwp_postテーブルに登録されています。画像データは投稿データに紐づくため、画像データのpost_parent項目に投稿データのidが入ります。画像データのサムネイル情報などのメタ情報は、wp_postmetaテーブルに登録されます。

 

  • 投稿データ⇒wp_post
  • 画像データ⇒wp_post ※投稿データとは親子関係(post_parent項目に投稿データのidを設定)
  • メタ情報(ex 画像ファイルパス、サムネイル情報など)⇒wp_postmeta

 

投稿データと画像データ(画像ファイル)の関係については、minoさんのブログ「wordpressで画像はどのようにデータベースに記録されているか」にかなり詳しく説明されています。

 

次に、投稿データとカテゴリの関係ですが、こちらは次のようになっています

 

  • 投稿データ⇒wp_post
  • カテゴリデータ(ex iot_data)⇒wp_terms
  • 分類(ex カテゴリ、ラベル)⇒wp_term_taxonomy
  • カテゴリと投稿データ関連付け⇒wp_term_relationships

 

 

 

削除スクリプトの作成

 

今回の要件として、IoTデータカテゴリ(RaspberryPiから自動送信されたデータが属するカテゴリ)の投稿データを削除対象として、それ以外の記事については削除しません。また記事に紐づく画像データと画像ファイルも削除の対象にすることにします。

 

 

画像ファイル削除SQL

 

厳密にいうとSQLだけで画像データに紐づく画像ファイルの削除はSQLではできません。このSQLで画像ファイル削除用BASHスクリプトを作成します。作成されたBASHスクリプトを実行することで画像ファイルを物理的に削除します。

 

select -- diy_posts.id ID, 
       case when (LOCATE('.',diy_postmeta.meta_value)>1) then
            CONCAT('rm -f ./', 
                    SUBSTR(  diy_postmeta.meta_value
                           , 1
                           , LOCATE('.',diy_postmeta.meta_value)-1)
                           , '*.*')
       else ''
       end 'echo removing image files which are 60 days before system date'
       -- ,date_format(diy_posts.post_date, '%Y-%m-%d') 登録日
       -- ,date_format(now() - INTERVAL 60 DAY, '%Y-%m-%d') 削除基準日
       -- ,diy_posts.post_parent 親ID
       -- ,dp2.post_title 親タイトル
from diy_posts
inner join diy_postmeta
    on diy_postmeta.post_id=diy_posts.id
       and diy_postmeta.meta_key='_wp_attached_file'
inner join diy_term_relationships
    on diy_term_relationships.object_id=diy_posts.post_parent
inner join diy_term_taxonomy
    on diy_term_relationships.term_taxonomy_id=diy_term_taxonomy.term_taxonomy_id
inner join diy_terms
    on diy_terms.term_id=diy_term_taxonomy.term_id
left outer join diy_posts dp2
    on dp2.id=diy_posts.post_parent
where diy_posts.post_type='attachment'
    and  diy_term_taxonomy.taxonomy='category'
    and diy_terms.slug='iot_data'
    and (date_format(diy_posts.post_date, '%Y-%m-%d') < date_format(now() - INTERVAL 60 DAY, '%Y-%m-%d'));
※上記スクリプトのテーブル名プレフィックスdiy_はwp_に読み替えてください。

このSQLでは、画像データの親データ(投稿データ)に紐づくカテゴリがiot_dataかつ60日を経過したものを抽出条件してデータを抽出します。抽出した画像データからファイルのパスを取得して削除コマンドとして出力しています。画像ファイルのパスは、post_meta(postメタ情報)に格納されています。

 

上記削除SQLにより作成された削除用BASHスクリプト

ID 削除用コマンド 登録日 削除基準日 親ID 親タイトル
5 rm -f raspi01_20170314013001-1*.* 2017-03-14 2017-03-27 4 【2017/03/14 01:30:30】定点観測データ
6 rm -f raspi01_20170314013001-2*.* 2017-03-14 2017-03-27 4 【2017/03/14 01:30:30】定点観測データ
10 rm -f raspi01_20170314020001-1*.* 2017-03-14 2017-03-27 9 【2017/03/14 02:00:36】定点観測データ
11 rm -f raspi01_20170314020001-2*.* 2017-03-14 2017-03-27 9 【2017/03/14 02:00:36】定点観測データ
15 rm -f raspi01_20170314023001-1*.* 2017-03-14 2017-03-27 14 【2017/03/14 02:30:34】定点観測データ
16 rm -f raspi01_20170314023001-2*.* 2017-03-14 2017-03-27 14 【2017/03/14 02:30:34】定点観測データ
19 rm -f raspi01_20170314030001-1*.* 2017-03-14 2017-03-27 18 【2017/03/14 03:00:31】定点観測データ
20 rm -f raspi01_20170314030001-2*.* 2017-03-14 2017-03-27 18 【2017/03/14 03:00:31】定点観測データ
23 rm -f raspi01_20170314033002-1*.* 2017-03-14 2017-03-27 22 【2017/03/14 03:30:28】定点観測データ
24 rm -f raspi01_20170314033002-2*.* 2017-03-14 2017-03-27 22 【2017/03/14 03:30:28】定点観測データ

 

登録日、削除基準日、親ID、親タイトルはコメントアウトしているため実際の削除SQL作成の際には出力されません。(デバッグ、確認のため出力しました)

作成されたBASHスクリプトをコマンドラインから実行すれば対象データに紐づく画像ファイルがすべて削除されます。

 

 

投稿データ・画像データ削除SQL

 

次に、削除対象の投稿データと画像データ(wp_post内の対象データ)を削除するSQLを作成して一括削除します。

自動投稿の初期設定カテゴリがiot_dataのため、記事のカテゴリーがiot_dataのデータだけ削除するようにしています。ただし、iot_dataの他に別のカテゴリが紐づけられている場合は、カテゴリ設定時に誤ってiot_dataにチェックした可能性があるので対象としません。

 

delete diy_posts, dp2, tr2
from diy_posts
inner join diy_term_relationships
    on diy_term_relationships.object_id=diy_posts.post_parent
inner join diy_term_taxonomy
    on diy_term_relationships.term_taxonomy_id=diy_term_taxonomy.term_taxonomy_id
inner join diy_terms
    on diy_terms.term_id=diy_term_taxonomy.term_id
inner join diy_term_relationships tr2
    on tr2.object_id=diy_posts.post_parent
inner join diy_term_taxonomy tt2
    on tr2.term_taxonomy_id=tt2.term_taxonomy_id
inner join diy_terms t2
    on t2.term_id=tt2.term_id
left outer join diy_posts dp2
    on dp2.id=diy_posts.post_parent
where diy_posts.post_type='attachment'
    and  diy_term_taxonomy.taxonomy='category'
    and tt2.taxonomy='category'
    and diy_terms.slug ='iot_data'
    and t2.slug<>'iot_data'
    and (date_format(diy_posts.post_date, '%Y-%m-%d') < date_format(now() - INTERVAL 60 DAY, '%Y-%m-%d'));

 

 

 

 

まとめ

 

WordPressコンテンツデータのuploadsフォルダには毎日蓄積される画像ファイルが入っているのでバックアップ(フォルダの圧縮)にはupdatesフォルダだけで膨大なサイズになり圧縮時間も相当なものでした。サーバーのストレージもすぐにいっぱいになって古いデータを削除するのも一苦労でした。

この削除スクリプトを毎日バックアップ前に流せばサーバーのバックアップストレージにもかなり余裕ができて安心です!

 

 

参考

 

wordpressのデータベースをデータベース管理ツールで覗いてみる方法

1:wordpressデータベースへのいざない
2:Adminerを使ってみる
2.1:AdminerはphpMyadminより手軽
2.2:Adminerのダウンロード&インストール
2.3:データベース管理ツール使う上での注意
3:Adminerの使い方
3.1:データベースの見方
4:wordpressのデータベースを覗く
4.1:wordpressのデータベーステーブル
4.2:wordpressのデータ構造
4.2.1:wp_postsテーブル
4.2.2:wp_termsテーブル
4.2.3:wp_term_taxonomyテーブル
4.2.4:wp_term_relationshipsテーブル
4.3:リレーショナルデータベースたる所以
5:まとめ

 

wordpressで画像はどのようにデータベースに記録されているか

1:wordpressの画像に強くなる
1.1:画像情報はデータベースに記録される
1.1.1:wp_postsテーブルでの画像データの記録のされ方
1.1.2:データベース上での投稿・固定ページ・画像の区分け
1.1.3:IDが飛び飛びになるのはなぜか
1.2:サムネイルの作成
1.3:画像の編集
1.4:サムネイルと編集画像
1.4.1:画像のメタデータ
1.4.2:シリアライズデータ
1.4.3:Exif
1.5:記事に使われているかどうか
1.6:アイキャッチ画像
1.6.1:アイキャッチ画像の記録
1.7:記事内の画像の順番は保障されていない
2:まとめ

 

WordPressの投稿データを、カテゴリー別に引っ張ってくるSQL

 

 

Leave a Reply

Your email address will not be published.