MicrosoftProjectでスケジュールを作成する。タスクの作成や休日の設定方法。

スケジュール

システム開発において、まずPM(プロジェクトマネージャ)が作成するのがスケジュールかと思います。
「誰が」「いつまでに」「何を」を明確にしてスケジューリングします。


この際、スケジュールを作成するツールが必要になるのですが、筆者は「MicrosoftProject」がおすすめです。
ずっと使っていて慣れているという理由もあるのですが、とても高機能なので、スケジュール管理でやりたい事はほぼ全てできます。


今回は、「MicrosoftProject」でのスケジュールの作成方法について最低限覚えておくべきことを紹介します。
とても高機能なので、全ての機能を使うのは大変です。
というよりも、全ての機能を使わなくても実際のプロジェクトで耐えられるレベルのスケジュールは作成できます。
最低限、“これさえ覚えていれば大丈夫”という使い方を説明していきます。


環境


  • MicrosoftProject2007

プロジェクト全般の設定


タスクを作成していく前に、まずはプロジェクト全般の設定をおこないます。
プロジェクト全般の設定をきちんとおこなっていないと、以降のタスク作成に影響が出てしまいますので、まずはこの設定をきちんとおこなっていきましょう。


開始日の設定


プロジェクトの開始日を設定することができます。
ここの日付は様々な箇所で参照されますが、ここで設定する日付がタスクのデフォルト日付になります。


「プロジェクト」→「プロジェクト情報」から、『開始日』をプロジェクトの開始日とします。

MicrosoftProjectで開始日の設定

休日の設定


休日の設定も可能です。
デフォルトの休日設定では、通常の土日は休日に設定されていますが、祝祭日は休日に設定されていないので、自分で設定する必要があります。
また、人によっては個別の休日(有給を使って夏休み、とか)がありますが、こういった全体ではない人毎の休日設定も可能です。


「ツール」→「稼働時間の変更」から、休日の設定をおこなうことができます。


全体の休日を設定する場合は、カレンダーの部分で「標準(プロジェクト カレンダー)」を設定して休日の設定をおこないます。

MicrosoftProjectで休日の設定

人によって個別の休日を設定する場合は、「カレンダー」で休日を設定したい要員を選択して休日の設定をおこないます。
こうすることで、選択した要員(リソース)に対してだけ適用される休日を設定できます。

MicrosoftProjectで休日の設定

タスクの作成


タスクを作成して、実際に各メンバに作業を割り振りします。


タスクを新規登録


タスク名の部分をダブルクリックすると、タスクの新規登録ウィンドウがひらくので、タスク名を入力してタスクを新規登録します。
タスクの新規登録ウィンドウで、期間・担当者の入力も可能です。

MicrosoftProjectでタスクの作成

子タスクを作成(レベル上げ・レベル下げ)


実際のプロジェクトでは、タスクは親子関係であることがほとんどです。
例えば、各画面のコーディングは『製造』というタスクの子タスクですし、各画面の試験は『試験』というタスクの子タスクです。
こういった、タスクの親子関係は、タスクの「レベル上げ・レベル下げ」で設定することができます。


以下例では、画面A・B・Cのコーディングと試験スケジュールを、親子関係を表現する形でスケジューリングしています。

MicrosoftProjectでタスクのレベル上げ・下げ

↓↓↓

MicrosoftProjectでタスクのレベル上げ・下げ

先行タスクを設定


「先行タスク」という形で、タスクの前後関係を設定することができます。
“このタスクが終わったらこのタスク”っていう設定が可能です。
「先行タスク」という名の通り、タスクの前のタスクを設定していきます。

MicrosoftProjectで先行タスクの設定

進捗の入力


スケジュールを作成した後に実際の作業を進めていくことになるのですが、各タスクの進捗を入力する必要があります。
この進捗管理もMicrosoftProjectで可能です。


この進捗の入力は「達成率」というフィールドで管理可能ですが、デフォルトではこの列は非表示となっています。
まずはこの列を表示する必要があります。


任意の列を選択して左クリックし、「列の挿入」を選択します。
そこで「達成率」を選択すれば、達成率フィールドが一覧に表示されるようになります。

MicrosoftProjectで進捗率の表示
MicrosoftProjectで進捗率の設定

この達成率フィールドにパーセンテージを入力するこで、各タスクの進捗を管理することができます。


印刷する


「MicrosoftProject」でスケジュールを作成しても、作成したスケジュールは「MicrosoftProject」がインストールされていないと参照できません。
Viewerで参照もできますが、一番手っ取り早い方法はPDFにして印刷する方法です。
そうすれば、皆が参照できます。


しかしそうした場合、デフォルトの設定だと1P目にしかタスク名が表示されず、とても見辛いです。


1P目

MicrosoftProjectで印刷

2P目

MicrosoftProjectで印刷

上記を解消するために、全てのページに左のタスク名等を表示することができます。
「ファイル」→「ページ設定」から、左からN列目までをすべてのページに印刷する、についてチェックをおこない、全ての印刷ページに印刷する列数を定義することができます。


MicrosoftProjectで印刷ページの設定

2P目

MicrosoftProjectで印刷

まとめ


MicrosoftProjectは非常に強力なスケジュール作成ツールで、とても高機能です。
しかし、今回紹介した機能さえ覚えていれば、プロジェクトを進めていく中で最低限必要な情報は定義・管理していくことができます。


上手にツールを使い、円滑なプロジェクト運営をしていきましょう!



サジェストAPIを使って、各サービスのサジェストワードを取得する

JavaScript

Googleを始めとした検索システムにおいて、検索ワードのテキストボックスにキーワードを入力すると候補文字列が表示されます。
これを「サジェスト」と呼び、日本語訳では「予測変換」になります。


このサジェスト文字列は、各サービスからAPIで提供されており、個別で実行可能になります。


今回は、各サービス毎のサジェストAPIの実行方法と、取得結果について紹介していきます。


環境情報


PHPでAPIを実行して、取得結果の表示をおこないます。


  • PHP 5.5.35

APIのURL


各APIのURLは以下になります。
取得形式はXMLだったらJSONだったりするのですが、できるだけ様々なパターンを試してみたいので、両方のパターンを実施してみます。


サービス 取得形式 URL
Google XML http://www.google.com/complete/search?hl=en&output=toolbar&q=keyword
Yahoo XML http://ff.search.yahoo.com/gossip?output=xml&command=keyword
Bing JSON https://api.bing.com/osjson.aspx?market=ja-JP&query=keyword
Youtube JSON http://clients1.google.com/complete/search?hl=en&ds=yt&client=firefox&q=keyword
Amazon JSON http://completion.amazon.co.jp/search/complete?search-alias=aps&mkt=6&q=keyword
wikipedia JSON https://ja.wikipedia.org/w/api.php?action=opensearch&format=json&search=keyword

※「keyword」が、予測変換したい文字列になります。


各APIのパラメータ詳細については、各サービスの正式ドキュメントを参照ください。


実行プログラムと実行結果


実行プログラムと実行結果を紹介していきます。
サービスによっては、APIの返り値には予測変換以外の属性情報が格納されている様なのですが、今回はあくまで予測変換文字列のみを抽出します。


なので、各プログラムで予測変換文字列以外は除外しています。


Google


一番メジャーな(気がする)Googleのサンプルコードです。
XMLで結果を取得して表示するプログラムになります。

try {
    $searchWord = "wordPress";
    $url = "http://www.google.com/complete/search?hl=en&output=toolbar&q=" . $searchWord;
    $result = simplexml_load_file($url);
    if (!isset($result)) {
        echo "not result.";
        exit;
    }
    foreach ($result->CompleteSuggestion as $item) {
        echo "suggestWord=" . 
            $item->suggestion->attributes()->data . "
"; } } catch (Exception $e) { echo "message=" . $e->getMessage() . "
"; exit; }

実行結果

suggestWord=wordpress
suggestWord=wordpress login
suggestWord=wordpress download
suggestWord=wordpress themes
suggestWord=wordpress tutorial
suggestWord=wordpress plugin
suggestWord=wordpress hosting
suggestWord=wordpress php
suggestWord=wordpress api
suggestWord=wordpress free

Yahoo


YahooもGoogleと同じようにXMLでの結果取得が可能です。
XMLの構造がYahooとは異なるので、微妙にコーディングが異なります。

try {
    $searchWord = "wordPress";
    $url = "http://ff.search.yahoo.com/gossip?output=xml&command=" . $searchWord;
    $result = simplexml_load_file($url);
    if (!isset($result)) {
        echo "not result.";
        exit;
    }
    foreach ($result as $item) {
        echo "suggestWord=" . 
            $item->attributes()->k . "
"; } } catch (Exception $e) { echo "message=" . $e->getMessage() . "
"; exit; }

実行結果

suggestWord=wordpress.com
suggestWord=wordpress login
suggestWord=wordpress.org
suggestWord=wordpress.com login
suggestWord=wordpress download
suggestWord=wordpress themes
suggestWord=www.wordpress.com login
suggestWord=wordpress login wp-admin
suggestWord=wordpress.org download
suggestWord=wordpress templates

Bing


BingからJSON形式で取得します。
XMLとはプログラムは異なりますが、基本的な構造は変わりません。


また、取得結果の配列は2段階になっているので、結果の配列構造も意識したプログラムとなります。

try {
    $searchWord = "wordPress";
    $url = "https://api.bing.com/osjson.aspx?market=ja-JP&query=" . $searchWord;
    $result = file_get_contents($url);
    if (!isset($result)) {
        echo "not result.";
        exit;
    }
    $result = json_decode($result, true);
    for ($lc = 0; $lc < count($result); $lc++) {
        if (is_array($result[$lc])) {
            $searchWord = $result[$lc];
            for ($slc = 0; 
                $slc < count($searchWord); $slc++) {
                echo "suggestWord=" . 
                    $searchWord[$slc] . "
"; } } } } catch (Exception $e) { echo "message=" . $e->getMessage() . "
"; exit; }

実行結果

suggestWord=wordpress
suggestWord=wordpress ログイン
suggestWord=wordpress 使い方
suggestWord=wordpressとは
suggestWord=wordpress インストール
suggestWord=wordpress テーマ
suggestWord=wordpress ログインできない
suggestWord=wordpress テンプレート
suggestWord=wordpress log in

Youtube


YoutubeはBingと同じプログラムで結果を取得できます。
APIのURLが違うだけです。


結果は以下になります。


実行結果

suggestWord=wordpress
suggestWord=wordpress tutorial
suggestWord=wordpress 使い方
suggestWord=wordpress website
suggestWord=wordpress blog
suggestWord=wordpress theme
suggestWord=wordpress speed optimization
suggestWord=wordpress plugins
suggestWord=wordpress マナブ
suggestWord=wordpress php

Amazon


Amazonは、BingとYoutubeと基本的に同様なのですが、結果配列の3階層目にも情報が格納されているようです。
サジェストワードは2階層目なので、3階層目を除外する制御を入れています。

try {
    $searchWord = "wordPress";
    $url = "http://completion.amazon.co.jp/search/complete?search-alias=aps&mkt=6&q=" . $searchWord;
    $result = file_get_contents($url);
    if (!isset($result)) {
        echo "not result.";
        exit;
    }
    $result = json_decode($result, true);
    for ($lc = 0; $lc < count($result); $lc++) {
        if (is_array($result[$lc])) {
            $searchWord = $result[$lc];
            for ($slc = 0; 
                $slc < count($searchWord); $slc++) {
                if (is_array($searchWord[$slc])) {
                    continue;
                }
                echo "suggestWord=" . 
                    $searchWord[$slc] . "
"; } } } } catch (Exception $e) { echo "message=" . $e->getMessage() . "
"; exit; }

実行結果

suggestWord=wordpressの教科書
suggestWord=wordpress
suggestWord=wordpress 本
suggestWord=wordpress php
suggestWord=wordpress ブログ
suggestWord=wordpress カスタマイズ
suggestWord=wordpressデザインレシピ集
suggestWord=wordpress 仕事の現場でサッと使える デザイン教科書
suggestWord=wordpress デザイン
suggestWord=wordpress レッスンブック

wikipedia


wikipediaは、他サービスとちょっと異なります。
実行プログラムは他のJSON形式と同一なのですが、結果にURLが格納されています。

※親切ですね


以下のサンプルプログラムでは、他結果との違いが分かりやすいように、キーワードを「wordPress」ではなく「japan」(結果がたくさん返ってくる)にしています。
また、空欄の結果文字列は除外しています。

try {
    $searchWord = "japan";
    $url = "https://ja.wikipedia.org/w/api.php?action=opensearch&format=json&search=" . $searchWord;
    $result = file_get_contents($url);
    if (!isset($result)) {
        echo "not result.";
        exit;
    }
    $result = json_decode($result, true);
    for ($lc = 0; $lc < count($result); $lc++) {
        if (is_array($result[$lc])) {
            $searchWord = $result[$lc];
            for ($slc = 0; 
                $slc < count($searchWord); $slc++) {
                if (is_array($searchWord[$slc])) {
                    continue;
                }
                if (strlen($searchWord[$slc]) == 0) {
                    continue;
                }
                echo "suggestWord=" . 
                    $searchWord[$slc] . "
"; } } } } catch (Exception $e) { echo "message=" . $e->getMessage() . "
"; exit; }

実行結果

suggestWord=Japan
suggestWord=JAPAN COUNTDOWN
suggestWord=JAPAN FM LEAGUE
suggestWord=Japan Expo
suggestWord=JAPAN (アルバム)
suggestWord=JAPANサッカーカレッジ
suggestWord=JAPAN JAM
suggestWord=JAPANNEXT
suggestWord=JAPANARIZM
suggestWord=Japan Skeptics
suggestWord=https://ja.wikipedia.org/wiki/Japan
suggestWord=https://ja.wikipedia.org/wiki/JAPAN_COUNTDOWN
suggestWord=https://ja.wikipedia.org/wiki/JAPAN_FM_LEAGUE
suggestWord=https://ja.wikipedia.org/wiki/Japan_Expo
suggestWord=https://ja.wikipedia.org/wiki/JAPAN_(%E3%82%A2%E3%83%AB%E3%83%90%E3%83%A0)
suggestWord=https://ja.wikipedia.org/wiki/JAPAN%E3%82%B5%E3%83%83%E3%82%AB%E3%83%BC%E3%82%AB%E3%83%AC%E3%83%83%E3%82%B8
suggestWord=https://ja.wikipedia.org/wiki/JAPAN_JAM
suggestWord=https://ja.wikipedia.org/wiki/JAPANNEXT
suggestWord=https://ja.wikipedia.org/wiki/JAPANARIZM
suggestWord=https://ja.wikipedia.org/wiki/Japan_Skeptics


WordPressプラグインの開発で発生し易いエラーと対処方法

WordPress

WordPressプラグインを開発していく中で、何かしらエラーが発生して悩んでしまう場合があるかと思います。
特にWordPressプラグインの開発を始めたばかりの人の場合、ハマって場合もあります。


そんな人むけに、WordPressプラグインの開発を始めたばかりの人がハマりやすいエラーについて、原因と対処方法を説明します。


環境情報


  • WordPress 5.4.1

文字化け


一番最初に陥り易いエラーです。


WordPressのダッシュボードで、開発しているプラグインの説明分が文字化けしてしまう場合があります。


WordPressプラグインの有効化の時に文字化け

文字化けしてしまう原因は文字コードです。
WordPressの文字コードは「UTF-8」なのですが、開発しているプラグインのPHPファイルが他の文字コードになっている事が原因です。


PHPファイルの文字コードを「UTF-8」に変更して保存すれば、文字化けは解消されます。


WordPressプラグインの有効化の時に文字化けの解消

プラグインの有効化中に”N”文字の予期しない出力が生成されました


プラグインの有効化をおこなうタイミングで発生するエラーになります。
これは、PHPプログラムの先頭、もしくは、末尾に、余計な改行や空白が存在する場合に発生します。


WordPressプラグインの余分な改行

PHPプログラムの先頭や末尾には、余分な改行や空白は不要になります。
以下のように、末尾位置と改行位置は一致する必要があります。


WordPressプラグインの先頭
WordPressプラグインの末尾

重大なエラーを引き起こしたため、プラグインを有効化できませんでした


プラグインの有効化をおこなったタイミングでPHPファイルに文法エラーが存在すると、有効化に失敗します。


WordPressプラグインの有効化時syntaxエラー

通常のPHPエラーがダッシュボードに表示されているだけなので、エラー内容を確認した上で対処すればよいです。


上記サンプルのエラーでは、「;」(セミコロン)の記載をおこなっていないので、PHPのパースに失敗しています。
通常のPHPと同様に、エラー発生箇所に対して「;」を記載して、再度有効化すれば問題ありません。


Apacheでクライアント認証をおこない、Javaで証明書情報を取得

apache

Apacheを使ったWEBアプリケーションでSSL通信をおこなうためには、Apacheが認識するサーバのフォルダ上に証明書を格納し、Apacheの設定ファイルに証明書の情報を定義する必要があります。

かつ、より安全なSSL通信をおこなう方法は、クライアント認証をおこなう方法になります。

許可した端末のブラウザにクライアント証明書をインストールし、そのクライアント証明書がインストールされている端末についてのみSSL通信を許可します。


今回は、クライアント証明書を使ってSSL通信をおこなうための設定方法と、クライアント証明書から情報を抜き出すJavaプログラムについて説明します。


環境情報


  • HTTPサーバ:Apahce2.2.15
  • 言語:Java1.7.79

SSL認証の概要


クライアント証明書を用いたSSL通信は、通常のSSL通信と少し異なります。

SSL通信をおこなう端末のブラウザにクライアント証明書をインストールしておき、通信においてブラウザのクライアント証明書と、サーバ側のルート証明書とで証明書のマッチング認証をおこない、同証明書であればSSL通信を許可します。



上記のクライアント証明書を用いたSSL通信をおこなうためには、ブラウザへのクライアント証明書のインストールと、Apacheへの証明書設定の2つが必要になります。


Apacheへの証明書設定(サーバ側)


サーバ側の証明書設定は、通常、証明書発行局が作成した証明書をサーバ上に指定フォルダに格納し、Apacheの設定ファイルに証明書のパスを設定します。
OpenSSLを使って独自で証明書を作成した場合でも設定方法は同様です。


設定するファイルは「ssl.conf」になります。
設定箇所は以下の4つです。


SSLCertificateFile サーバ証明書の格納パス
SSLCertificateKeyFile 秘密鍵の格納パス
SSLCertificateChainFile サーバー証明書の中間証明書格納パス
SSLCACertificateFile クライアント証明書のルート証明書格納パス

# サーバー証明書
SSLCertificateFile /etc/httpd/cert/server.crt

# 秘密鍵
SSLCertificateKeyFile /etc/httpd/cert/secret.key

# サーバー証明書における中間証明書
SSLCertificateChainFile /etc/httpd/cert/publicKey.cer

# クライアント証明書におけるルート証明書
SSLCACertificateFile /etc/httpd/cert/root.pem

設定する証明書によっては、証明書の形式も意識する必要があります。
例えば、クライアント証明書におけるルート証明書(SSLCACertificateFile)は、テキスト形式でなくてはなりません。

Apacheのバージョンによるかもしれないのですが、少なくとも「Apahce2.2.15」ではバイナリ形式のルート証明書は認識できません。


Apacheのエラーログに、以下のログが出力されてApacheの起動に失敗します。


[Thu Mon DD HH:MI:SS YYYY] [info] SSL Library Error: 336105671error:140890C7:SSL routines:SSL3_GET_CLIENT_CERTIFICATE:peer did not  return a certificate No CAs known to server for verification? 

証明書発行局からテキスト形式の証明書を発行してもらうことが一番よいのですが、OpenSSLコマンドを用いてバイナリからテキスト形式への変更も可能です。


openssl x509 -inform der -in root.cer -outform pem -out root.pem 

ブラウザへの証明書インストール(クライアント側)


ブラウザにインストールするクライアント証明書も、サーバ証明書と同様に証明書発行局が作成した証明書をインストールします。

こちらも基本的には、ウィザードに沿ってブラウザに証明書をインストールしていきます。


証明書ファイル(.der、など)をクリックすると、以下のようなインストールウィザードがひらきます。

表示内容を確認し、OKボタンを押下します。



保管場所を選択します。

通常であれば「現在のユーザ」でよいです。

選択したら次へボタンを押下します。



証明書ストアを設定します。

何かしらの理由がなければ、自動ストアを選択して、次へボタンを押下します。


以下のウィンドウが表示されれば、無事にクライアント証明書のインストール完了です。



インストールが完了したら、ブラウザの設定ウィンドウをひらいてインストール結果を確認します。

Edge(Chromium版)での確認方法は、設定ウィンドウをひらき、「プライバシーとサービス」→「証明書の管理」で証明書情報を確認できます。



「個人」タブにインストールした証明書が表示されていれば、正常にクライアント証明書が認識されているという事になります。


証明書から情報を取得


クライアント証明書を使ったSSL通信において、WEBアプリケーション側でクライアント証明書を情報を取得する事も可能です。
具体的には、JavaプログラムでHTTPリクエストから抽出します。


以下のプログラムでは、java.security.cert.X509Certificateを使って、HttpServletRequestから識別情報を取得しています。


private void getCert(HttpServletRequest request) {

    // -- クライアント証明書情報の取得 --//
    java.security.cert.X509Certificate[] certs = 
        (java.security.cert.X509Certificate[]) request.getAttribute(
        "javax.servlet.request.X509Certificate");

    // クライアント証明書からクライアント証明書識別子を取得
    Principal principal = certs[0].getSubjectX500Principal();

    // クライアント証明書識別子を取得
    X509Name name = new X509Name(principal.getName());
    Vector<?> cert = 
        name.getValues(X509ObjectIdentifiers.commonName);
    if (cert.size() == 1) {
        String code = cert.get(0);
    }

上記のプログラムで、クライアント証明書に格納されている「commonName」を取得することができます。


上記プログラムの用途としては、インストールされているクライアント証明書に格納されている情報(commonName)毎にアプリケーションの制御を変える場合です。
クライアント証明書Aをインストールしているブラウザからログインしたユーザと、クライアント証明書Bをインストールしているブラウザからログインしたユーザとで、上記で取得した情報をもとに制御の切替が可能となります。



WordPressプラグインの開発。コントローラを使って設定を保存する方法

WordPress

WordPressプラグインを開発する際、設定画面でさまざまコントローラを使う場面がでてきます。
テキストボックス・セレクトボックス・ラジオボタン、いろいろあります。


今回は、各コントローラを設定画面で使う場面を想定した際の実装方法について紹介します。


環境情報


  • WordPress 5.1.6

基本的なプログラム


WordPressプラグインを開発する場合、基本的なお作法があります。
今回の各コントローラを扱うプラグインプログラムについても、この部分は変わりません。


<?php
/*
  Plugin Name: ControlSample
  Plugin URI:https://sakusaku-techs.com/
  Description: 設定ウィンドウでのコントロールサンプル
  Version: 1.0.0
  Author: SakuSaku
  Author URI: https://sakusaku-techs.com/
  License: GPLv2
 */


/**
1:初期アクションの定義
*/
add_action('init', 'ControlSample::init');

class ControlSample {

    /**
    2:プラグイン定数の定義
    */
    const PLUGIN_ID         = 'control-sample';
    const SAMPLE_ACTION     = self::PLUGIN_ID . '-nonce-action';
    const SAMPLE_NAME       = self::PLUGIN_ID . '-nonce-key';
    const SAMPLE_DB_PREFIX  = self::PLUGIN_ID . '_';
    const SAMPLE_MENU_SLUG  = self::PLUGIN_ID . '-config';
    const COMPLETE_CONFIG  = 'update-date-complete';

    /**
    初期化処理
    */
    static function init() {
        return new self();
    }

    /**
    コンストラクタ
    */
    function __construct() {
        /**
        3:アクションの定義
        */
        if (is_admin() && is_user_logged_in()) {
            add_action('admin_menu', 
                [$this, 'set_controlSample_menu']);
            add_action('admin_menu', 
                [$this, 'set_controlSample_sub_menu']);
            add_action('admin_init', 
                [$this, 'save_config']);
        }
    }

    /**
    コントロールサンプルのメニュー追加
    */
    function set_controlSample_menu() {
        /**
        4:メニューの追加
        */
        add_menu_page(
            'コントロールサンプル',
            'コントロールサンプル',
            'manage_options', 
            'sample-index-slag',
            [$this, 'show_about_plugin'],
            'dashicons-format-gallery', 
            99
        );
    }

    /**
    コントロールサンプルのサブメニュー追加
    */
    function set_controlSample_sub_menu() {
        /**
        5:サブメニューの追加
        */
        add_submenu_page(
            'sample-index-slag', 
            '設定',
            '設定',
            'manage_options',
            'custom-index-banner-config',
            [$this, 'show_config_form']);
    }

    /**
    設定画面の項目データベースに保存する
    */
    function save_config() {
        if (isset($_POST[self::SAMPLE_NAME]) && 
            $_POST[self::SAMPLE_NAME]) {
            if (check_admin_referer(
                self::SAMPLE_ACTION, self::SAMPLE_NAME)) {
            /**
            6:データベースへの保存
            */
            }
        }
    }

    /**
    設定ウィンドウの表示
    */
    function show_config_form() {
        /**
        7:データベースからのデータ取得と画面表示
        */
    }
}
?>

1~5のプログラムは、WordPressプラグイン開発においては基本的な部分です。
各コントローラの表示と保存をおこなうために、6と7にプログラムとHTMLの記載をおこないます。


各コントローラのサンプルプログラム


WordPressプラグインの開発において、設定画面を設ける場合が多いかと思います。
その場合、何かしらの設定値を画面に入力して、WordPressのDBに保存する必要があります。


想定されるコントローラとして、以下のコントローラについてサンプルプログラムを紹介します。


  • テキストボックス
  • テキストエリア
  • セレクトボックス(プルダウン)
  • ラジオボタン
  • カラーピッカー

テキストボックス


テキストボックスは、全てのコントローラに対するプログラムの基本です。


保存メソッドである「save_config()」においてテキストボックスの内容をWordPressのDBに保存しています。
WordPressのDBに保存する際にキー値が必要となりますが、先頭にプレフィックスとして「self::SAMPLE_DB_PREFIX」を付加しているのがポイントです。
このプレフィックスの値が、本プラグインの値となります。


実際に「show_config_form()」において、このプレフィックスを使用してWordPressのDBから値を取得しています。



/**
設定画面の項目データベースに保存する
*/
function save_config() {
    if (isset($_POST[self::SAMPLE_NAME]) && 
        $_POST[self::SAMPLE_NAME]) {
        if (check_admin_referer(
            self::SAMPLE_ACTION, self::SAMPLE_NAME)) {
            update_option(self::SAMPLE_DB_PREFIX . 
                "_textbox", $_POST['prefix']);
            $completed_text = "設定の保存が完了しました。";
            set_transient(
                self::COMPLETE_CONFIG, $completed_text, 5);
            wp_safe_redirect(
                menu_page_url(self::SAMPLE_MENU_SLUG), false);
        }
    }
}

/**
設定ウィンドウの表示
*/
function show_config_form() {
    $textbox = 
        get_option(self::SAMPLE_DB_PREFIX . "_textbox");
?>
<div class="wrap">
  <h1>カスタムバナーの設定</h1>
  <form action="" method='post' id="my-submenu-form">
      <?php wp_nonce_field(
        self::SAMPLE_ACTION, self::SAMPLE_NAME) ?>
      
        <label for="prefix">テキストボックス:</label>
        <input type="text" name="prefix" value="<?= $textbox ?>"/>
      
      
        <input type='submit' value='保存' class='button button-primary button-large'>
      
  </form>
</div>
<?php
}

テキストエリア


テキストエリアは、テキストボックスとほぼ同等となります。

保存メソッドである「save_config()」にテキストエリアの値を保存し、表示メソッドである「show_config_form()」にテキストエリアの値の取得とHTMLへの表示をおこなっています。



/**
設定画面の項目データベースに保存する
*/
function save_config() {
    if (isset($_POST[self::SAMPLE_NAME]) && 
        $_POST[self::SAMPLE_NAME]) {
        if (check_admin_referer(
            self::SAMPLE_ACTION, self::SAMPLE_NAME)) {
            update_option(self::SAMPLE_DB_PREFIX . 
                "_textarea", $_POST['prefix_area']);
            $completed_text = "設定の保存が完了しました。";
            set_transient(
                self::COMPLETE_CONFIG, $completed_text, 5);
            wp_safe_redirect(
                menu_page_url(self::SAMPLE_MENU_SLUG), false);
        }
    }
}

/**
設定ウィンドウの表示
*/
function show_config_form() {
    $textbox = get_option(self::SAMPLE_DB_PREFIX . "_textbox");
?>
<div class="wrap">
  <h1>カスタムバナーの設定</h1>
  <form action="" method='post' id="my-submenu-form">
      <?php wp_nonce_field(
          self::SAMPLE_ACTION, self::SAMPLE_NAME) ?>
      
        <label for="prefix">テキストエリア:</label>
        <textarea rows="10" cols="60" name="prefix_area">
            <?= $textArea ?>
        </textarea>
      
      
<input type='submit' value='保存' class='button button-primary button-large'>
  </form>
</div>
<?php
}

セレクトボックス(プルダウン)


セレクトボックス(プルダウンメニュー)も、テキストボックスとテキストエリアとほぼ同一なのですが、HTMLの構成が異なりますので、おのずとプログラムも変わってきます。
セレクトボックスで選択された値についてのみ、WordPressのDBに保存をおこない、HTMLに反映をおこなっています。



/**
設定画面の項目データベースに保存する
*/
function save_config() {
    if (isset($_POST[self::SAMPLE_NAME]) && 
        $_POST[self::SAMPLE_NAME]) {
        if (check_admin_referer(
            self::SAMPLE_ACTION, self::SAMPLE_NAME)) {
            update_option(self::SAMPLE_DB_PREFIX . 
                "selectbox", $_POST['siteoption_select1']);
            $completed_text = "設定の保存が完了しました。";
            set_transient(
                self::COMPLETE_CONFIG, $completed_text, 5);
            wp_safe_redirect(
                menu_page_url(self::SAMPLE_MENU_SLUG), false);
        }
    }
}

/**
設定ウィンドウの表示
*/
function show_config_form() {
    $textbox = get_option(
        self::SAMPLE_DB_PREFIX . "_textbox");
?>
<div class="wrap">
  <h1>カスタムバナーの設定</h1>
  <form action="" method='post' id="my-submenu-form">
      <?php wp_nonce_field(
          self::SAMPLE_ACTION, self::SAMPLE_NAME) ?>
      
        <label for="prefix">セレクトボックス:</label>
          <select name="siteoption_select1" id="siteoption_select1">
              <option value="0" <?php selected(0, 
                get_option(self::SAMPLE_DB_PREFIX . "selectbox"));
              ?> >
                値0:デフォルト
              </option>
              <option value="1" <?php selected(1, 
                get_option(self::SAMPLE_DB_PREFIX . "selectbox"));
              ?> >
                値1
                </option>
              <option value="2" <?php selected(2, 
                get_option(self::SAMPLE_DB_PREFIX . "selectbox"));
              ?> >
                値2
                </option>
              <option value="3" <?php selected(3, 
                get_option(self::SAMPLE_DB_PREFIX . "selectbox" ));
              ?> >
                値3
                </option>
          </select>
      
      
<input type='submit' value='保存' class='button button-primary button-large'>
  </form>
</div>
<?php
}

ラジオボタン


ラジオボタンは、セレクトボックスとほぼ同等となります。


保存メソッドである「save_config()」にラジオボタンで選択されたの値を保存し、表示メソッドである「show_config_form()」において選択内容の反映をおこなっています。



/**
設定画面の項目データベースに保存する
*/
function save_config() {
    if (isset($_POST[self::SAMPLE_NAME]) && 
        $_POST[self::SAMPLE_NAME]) {
        if (check_admin_referer(
            self::SAMPLE_ACTION, self::SAMPLE_NAME)) {
            update_option(self::SAMPLE_DB_PREFIX . 
                "option", $_POST['siteoption_radio1']);
            $completed_text = "設定の保存が完了しました。";
            set_transient(
                self::COMPLETE_CONFIG, $completed_text, 5);
            wp_safe_redirect(
                menu_page_url(self::SAMPLE_MENU_SLUG), false);
        }
    }
}

/**
設定ウィンドウの表示
*/
function show_config_form() {
    $textbox = get_option(
        self::SAMPLE_DB_PREFIX . "_textbox");
?>
<div class="wrap">
  <h1>カスタムバナーの設定</h1>
  <form action="" method='post' id="my-submenu-form">
      <?php wp_nonce_field(
        self::SAMPLE_ACTION, self::SAMPLE_NAME) ?>
      
        <label for="prefix">ラジオボタン:</label>
          <label>
            <input name="siteoption_radio1" type="radio" value="0" 
                <?php checked(0, get_option(
                    self::SAMPLE_DB_PREFIX . "option")); ?> />
                    値1</label>
          <label>
            <input name="siteoption_radio1" type="radio" value="1" 
                <?php checked(1, get_option(
                    self::SAMPLE_DB_PREFIX . "option")); ?> />
                    値2</label>
          <label>
            <input name="siteoption_radio1" type="radio" value="2" 
                <?php checked(2, get_option(
                    self::SAMPLE_DB_PREFIX . "option")); ?> />
                    値3</label>
          <label>
            <input name="siteoption_radio1" type="radio" value="3" 
                <?php checked(3, get_option(
                    self::SAMPLE_DB_PREFIX . "option")); ?> />
                    値4</label>
      
      
<input type='submit' value='保存' class='button button-primary button-large'>
  </form>
</div>
<?php
    }

カラーピッカー


カラーピッカーは、他コントローラとちょっと異なります。
色選択ウィンドウを表示する必要があるので、クライアント側の作りこみが必要があります。


色選択ウィンドウは、JQueryUIの「wpColorPicker」を使用します。
「wpColorPicker」を制御するJavaScriptを準備して、サーバ上のプラグインフォルダに保存しておきます。


plguinfolder --- control-sample.php
             |
             --- js
                 |
                 --- date.js

PHPでは、プラグインフォルダに保存しておいたJavaScriptを読み込むプログラムを実装しておきます。



JavaScript

(function( $ ) {
    var options = {
        defaultColor: false,
        change: function(event, ui){},
        clear: function() {},
        hide: true,
        palettes: true
    };
    $('.color-picker').wpColorPicker(options);
})( jQuery );

PHP

add_action( 'wp_enqueue_scripts', 'load_javascript_func' );

class ControlSample {

/**
設定画面の項目データベースに保存する
*/
function save_config() {
    if (isset($_POST[self::SAMPLE_NAME]) && 
        $_POST[self::SAMPLE_NAME]) {
        if (check_admin_referer(
            self::SAMPLE_ACTION, self::SAMPLE_NAME)) {
            update_option(
                self::SAMPLE_DB_PREFIX . "_color", $_POST['color']);
            $completed_text = "設定の保存が完了しました。";
            set_transient(
                self::COMPLETE_CONFIG, $completed_text, 5);
            wp_safe_redirect(
                menu_page_url(self::SAMPLE_MENU_SLUG), false);
        }
    }
}

/**
JavaScriptの読み込み
*/
function load_javascript_func() {
     wp_enqueue_script( "jQuery", includes_url().'/js/date.js' );
}

/**
設定ウィンドウの表示
*/
function show_config_form() {
?>
<div class="wrap">
  <h1>カスタムバナーの設定</h1>
  <form action="" method='post' id="my-submenu-form">
      <?php wp_nonce_field(
          self::SAMPLE_ACTION, self::SAMPLE_NAME) ?>
      
          <label for="prefix">カラーピッカー:</label>
          <input type="text" name="color" 
            class="color-picker" value="<?= $color ?>" >
      
      
        <input type='submit' value='保存' class='button button-primary button-large'>
      
  </form>
</div>
<?php
    }
}
?>

カラーピッカーに関わらず、JavaScriptでクライアント側の制御をおこないたい場合は、上記の方法で機能を実現することが通常の方法になります。