WordPressの人気プラグインを紹介するWebアプリ開発

Webアプリを作りたくって、ここしばらくジタバタしてました。久しぶりの投稿です (^^)

Webアプリと言ってもなんか漠然としていますが、WordPressで動作させているプラグインも全てWeb上で動作しているプログラムなのでWebアプリと言えなくもありません

今までいくつかのWordPressプラグインを作った経験を活かして、WordPressを使ったWebアプリ(何かデータを収集して結果を表示する)を作る時のポイント等を紹介します

アプリの本質的な部分を作りこめば、後はWordPressの持っている機能を利用することで全体の作業はかなり楽になります

準備

WordPressのプラグイン開発環境と同じです

ちょっと古い記事ですが、下記を参考に環境を作成して下さい

2014/10/1現在の最新の NetBeans は Ver8.0.1 ですが、同じ手順で構築できるはずです

プラグインの作り方に関しては、プログラム開発雑記 を参照して下さい。作成から公開までの手順を紹介しています。

ちなみに今回のWebアプリは、プラグインとして開発していきますが、自サイトで使用するだけなので、手抜き出来るところは手抜きして簡単に済ませます (^^)

 

処理内容

WordPressの人気プラグインの表示

WordPressの人気プラグインは、WordPress管理画面のプラグイン新規追加ページから人気プラグインを表示することで確認出来ますが、あまり使い勝手がよくありません

WordPress4.0 からはデザインが変わりプラグインアイコンも表示されて改善されましたが、カテゴリー別に人気のプラグイン等を知ることは出来ません

そこでこの人気プラグインデータを取得して、主要なカテゴリー別に人気のプラグインを表示するものを作成してみます

カテゴリーに分けることがこのアプリの肝ですね

こんな感じに人気プラグインをカテゴリー毎に表示します

WP-人気プラグイン例

この人気プラグインの表示は WordPress プラグインアンテナ から確認出来ます

 

動作条件

レンタルサーバーのWordPress上で動作させます

通常は、ブログとして運用しているサイトに人気プラグインランキング表示用の固定ページを用意してそこに収集したプラグインデータを処理した結果を表示します

 

データ収集

プラグインデータの収集は、WordPress.org API がありますが資料はほとんどありません (^_^;)

WordPress.org API 概要 の Plugins にある下記リンクが参考になります

http://dd32.id.au/projects/wordpressorg-plugin-information-api-docs/

http://wp.tutsplus.com/tutorials/plugins/communicating-with-the-wordpress-org-plugin-api/

後は、WordPressの管理画面でも同等の処理を行っていますので、ソースコードから plugins_api() 関数あたりを調べてみてください

NetBeans から実際に使用しているところでブレイクさせて、リクエストと取得データを確認するのが分かりやすいです

plugins_api の query_plugins アクションで取得可能な値は4種類あるようです

  • popular 人気プラグイン(ダウンロード数)
  • new 新規プラグイン
  • updated 更新プラグイン
  • top-rated 人気プラグイン(評価値)

今回は、popularnewでそれぞれ500個のプラグインデータを取得します

特に認証を必要とするわけではありませんので、データとしては取得しやすいと思います
但し、認証がない代わりに情報を制限することで間接的に乱用されないようにしているのかも知れませんので、アクセス過多にならないよう注意して使用します

こんな関数を作りデータ収集を行ってみました

//WordPress.org からプラグイン情報取得
//  $tmpdt 取得中間データ
// $type  人気ダウンロード:popular 人気高評価:top-rated 新規:new 更新:updated
//  $max   取得データ数
// プラグイン毎のname, slug, version, author, etc 等の情報が取得できる 
//  ※fields でいくつかのデータの取得有無を指定可能(description はデータ量が多いので取得しない)
//    取得データ数はタイムアウトを起こさないように100個単位で処理(最大10ページに制限)
//    特にページ数が多くなると高い確率でタイムアウトとなるので10秒待ってからリトライを1回だけ行う
public function plugins_getinfo(&$tmpdt, $type, $max)
{
    @set_time_limit(120);        //可能なら最大実行時間を2分にする

    $page = 1;
    $pagemax = 10;
    $plugins = array();
    for($n = $max; $n > 0; $n -= 100){
        $count = ($n > 100)? 100 : $n;
        $args = array('browse'  => $type,
                      'page'    => $page,
                      'per_page'=> $count,
                      'fields'  => array(
                                    'version'       => true,
                                    'added'         => true,
                                    'last_updated'  => true,
                                    'rating'        => true,
                                    'ratings'       => false,
                                    'downloaded'    => true,
                                    'icons'         => true,
                                    'description'   => false,
                                    'short_description' => false,
                                    'sections'      => false,
                                    'tested'        => false,
                                    'requires'      => false,
                                    'compatibility' => false,
                                    'downloadlink'  => false, 
                                    'homepage'      => false,
                                    'donate_link'   => false,
                                    'tags'          => false, ));
            
        $key = 'wp_plugin_ranking_' . $type . $page;
        $plugdt = get_transient( $key );
        if(empty($tmpdt[$type][$page]) || $plugdt === false){
            $api = plugins_api( 'query_plugins', $args );
            if ( is_wp_error( $api ) || empty($api->plugins)){
                sleep(10); //10sec 待って1回だけリトライ
                $api = plugins_api( 'query_plugins', $args );
                if ( is_wp_error( $api ) || empty($api->plugins)){
                      break;
                }
            }
            //最大実行時間オーバーで処理が終了される場合があるので中間データとしてとりあえず保存
            //時間オーバー時の残りデータは次に呼び出された時に取得する
            //保存データ構成が複雑で大きいと update_option が false となるのでインデックスとデータに分けて処理                
            set_transient( $key, $api->plugins, HOUR_IN_SECONDS );
            $day = new DateTime();
            $day->setTimeZone(new DateTimeZone('Asia/Tokyo'));
            $tmpdt[$type][$page] = $day->format("H:i:s");   //インデックス(取得済みマークセット)
            $res = update_option('wp_plugin_ranking_tmp', $tmpdt );
            //$chk = get_option('wp_plugin_ranking_tmp');
            $plugins[] = $api->plugins;
            sleep(1);
        }
        else {
            $plugins[] = $plugdt;
        }
        if($page >= $pagemax){
            break;
        }
        $page++;
    }
    return $plugins;
}

 

また、各プラグインのダウンロード数に関しては、

https://api.wordpress.org/stats/plugin/1.0/downloads.php?slug={slug}&limit={days}&callback={jsFunction} を用いて取得することが出来ます

 

データ収集の注意点

ローカル環境で NetBeans からデバッガを使いながら開発していた時は、簡単にデータ取得出来るようになったのですが、レンタルサーバー上で動作させるとデータが収集出来ませんでした (^_^;)

ここでハマってしまって、安定してデータ収集出来るまでにかなりかかってしまいました

データ収集のポイントを紹介します

この辺りを抑えておけば、データを収集して表示するようなアプリを作成する場合にもいろいろ応用できるようになると思います (^^)

wp_cron の活用

通常のブログ表示等に影響が出ないように処理を行うことが大切です

ブログの邪魔をせずに、裏で何事もなかったようにデータを収集してくれるのが理想です (^^)

wp_cron を使うことで、サイトへのアクセスをきっかけに裏で処理を行うことが出来ます

1回の cron 処理ではデータ取得が完了しない場合を想定して、データ取得が完了するまで、cron 動作をリトライするように作成します。

wp_cron の詳細は、wp_cron を使った外部データ取得の非同期化とそのデバッグ方法 を参照して下さい

最大実行時間 max_execution_time に注意

これがレンタルサーバー上で上手くデータ収集出来なかった一番の原因です (^_^;)

ローカル環境のデバッガ上では最大実行時間が無効となっているので、データが収集出来ていたのですが、レンタルサーバー上ではタイムオーバーで動作が途中で終了させられてしまいます

取得したいデータは、人気プラグインデータを500個,新規プラグインデータを500個です

今回は、1回毎に100データとして10回データを要求します。また人気プラグインの上位100個に関しては個別にダウンロード数を要求して取得していますので最終的に110回のリクエストを実行します

これだけの処理を行うには、通常のレンタルサーバーで設定されている最大実行時間では処理が終了しません

最大実行時間を必要十分な時間に延ばせればいいのですが、延ばせない場合もありますので、タイムアウトすることを前提として開発します

取得したデータは、どの時点で最大実行時間をオーバーしても良いようにその都度一時保存します

取得データの一時保存は、複数のデータを合わせて処理しようとすると、データ構造が複雑になりエラーが起きやすくなりますので、保存処理が重くならないよう通信毎に Transient API を使って別々のデータとして保存しておきます

データ収集状況の確認

ローカル環境と違いレンタルサーバー上での動作なので、データ収集がうまく動作しているのかがわかるようにログを生成して確認できる仕組みを作ります

今回は、WordPressの設定画面からデータ収集ログの確認と収集したデータの削除機能を設けました

どのあたりまで処理が進んだか確認できる簡単なもので十分です

 

データ分類

データが全て揃ったら、カテゴリー毎への分類等の処理を行います

プラグインデータには、内容や用途を識別する為のタグが付けられています

このタグは、プラグイン作者が任意に付けられるものなので、関係有りそうなタグを沢山付けまくっていることが多く、正直なところタグからはプラグインのカテゴリー分けを行うのは難しくなってしまいます

プラグインの特徴を簡潔に盛り込んでいる可能性が高いのがやはりプラグイン名です

従って、今回はプラグイン名に含まれているキーワードを使ってカテゴリー分けを行いました

例えば、プラグイン名に security,firewall,protect,antivirus,login,password 等のキーワードが含まれていたら「セキュリティ関連」に分類というような感じで処理しています

※プラグイン名からはカテゴリーに分類できないものや、複数のカテゴリーに属したり、そもそもプラグインの内容がまったく不明なものもあるので、間違って分類する場合も有ります (^_^;)

人気になるプラグインは概ねプラグイン名でどんなプラグインか想像できる素直な名前が多いようです (^^)

分類したらワンポイントとして FontAwesome のアイコンを表示しています

FontAwesome は初めてですが、下記記事を参考に簡単に使用することが出来ました

楽して便利!Webアイコンフォント『Font Awesome』の使い方と活用 Tips

 

データ表示

プログラムはデータの収集処理と収集したデータを加工して表示する処理にわかれています

データ収集は wp_cron で行っていますが、結果表示は固定ページの記事中に書かれているショートコードを用いて行っています

ショートコードは、記事中に実行するプログラム名とそのパラメータを記述出来るのでとても手軽で便利です

今回のような用途にピッタリです (^^)

ちなみに今回は表示内容ごとに5個のショートコードを作成して表示しています

wp_plugins_setfeatured お勧めプラグインの設定(slug のカンマ区切りで設定)
wp_plugins_insertdate プラグインデータの取得日時を表示
wp_plugins_newpickup 注目の新規プラグイン表示
wp_plugins_category カテゴリー別人気プラグインの表示
wp_plugins_popular 人気プラグインの表示(トップ100)

ショートコード実行時に収集データから表示するデータを取り出してHTML文を生成して、Transient API でキャッシュし、2回目以降はキャッシュしたHTMLを出力します

このプログラムで処理したプラグインの人気ランキングは、WordPress プラグインアンテナ から見ることが出来ます

2ページ構成で最初のページがカテゴリ別の人気プラグインで、次ページが7日間のダウンロード数が多い順の人気プラグイン100となっています

表示するデータは、プラグイン選択時の参考となるようにプラグインページや作者さんへのリンク、バージョン、更新日、ダウンロード数、評価値、プラグインアイコン(登録されている場合)を見やすく簡潔に表示しています

気になるプラグインがあれば、プラグイン名をクリックすれば、プラグインページから詳細情報を確認することが出来ますし、作者さんのリンクからは、作者さんの他のプラグイン等も見ることが出来ます

まとめるとWordPress上でデータ収集して何か表示するようなアプリを作成するポイントは

  1. データ収集は、wp_cron を使用する
  2. データ収集時の実行時間オーバーを想定しておく
  3. 結果表示は、ショートコードを使用する
  4. データ収集、結果表示ともに Transient API を用いて無駄を省く

です

最後に一言

プラグインランキングを見ると、既にある人気プラグインを超えるものを作るのは至難の業です (^_^;)

人気プラグインは作れなくても、世界に一つだけの自分用プラグインでも作ってみるとなかなか楽しいですよ

Webアプリを作成する時の参考に少しでもなれば幸いです (^^)

 


まとめ記事紹介

go-to-top