このページの本文へ

AngularJSとREST APIでWordPressのSPA化を先取りしてみた!

2016年08月10日 04時00分更新

文●Almir Bijedic

  • この記事をはてなブックマークに追加
本文印刷
WordPressが整備を進めているREST APIなら、WordPressで本格的なSPA(シングルページアプリケーション)が作れる? REST APIとAngularJSを使って、WordPressの記事をすぐに編集できる投稿アプリを作ってみました。

本記事はJay ShieldsSimon Codringtonが査読を担当しています。最高のコンテンツに仕上げるために尽力してくれたSitePointの査読担当者のみなさんに感謝します。

AutomatticとWordPressコミュニティがWordPress REST APIプラグインをWordPressの内部へ組み込む方向で動いています。つまり、プラグインを使わなくてもAPIが利用できるようになります。これからどんどんWordPressとフロントエンドのJavaScriptフレームワークとの統合を目にするようになるでしょう。

WordPress REST APIプラグインがWordPress内部に組み込まれると、アプリケーションをこれまでよりもすばやく開発できるようになります。JavaScriptでいちから実装しなければならなかったいくつかの基本的な機能が、最初から実装された状態で提供されることになるからです。WordPressのユーザー管理や、WooCommerceの製品管理や静的ページなど、挙げだしたらキリがありません! また、カスタマイズしたエンドポイントをAPIに追加できます。

APIを使う1つの方法として、フロントエンドのJSフレームワークをWordPressのテーマの一部として含める方法があります。しかし、この方法は不便です。というのは、非標準のディレクトリ構造を扱う必要があり、一般的なフレームワーク、WordPressテーマのどちらとして使うにせよベストプラクティスとは言えないからです。

もっと良い方法はREST APIを使ってWordPressデータを公開し、完全に構造的に分離された2つのアプリを作ることです。しかし、両方の良いところを使用するために、「セッション共有」によって2つのアプリは接続しています。

記事では「セッション共有」の方法を解説します。セッション共有ではWordPressをユーザー管理とログインに使用し、クライアントサイドは許可されたユーザーが簡単にSPA(シングルページアプリケーション)のような投稿編集機能を利用できるAngularアプリを使用します。

GitHubでWordPressの子テーマやAngularクライアントのコードを見つけられます。

要件

記事を読むにあたって、以下について多少なりとも習熟している必要があります。

また、以下のものを使います。

  • Vagrant (仮想マシン2台。1台はWP用、もう1台はgruntサーバー上でのAngularアプリ実行用)
  • Yeoman (Angularアプリの補助用)
  • Grunt

上の3つは開発ツールとして利用しますが、ローカルなWordPress Webサイトの実行はほかの方法でもかまいませんし、補助ツールは必須ではありません。

WordPress REST API

目標となるアーキテクチャを作成するには、WordPress REST APIプラグインをインストールする必要があります。WordPress REST APIプラグインはまだベータ版なので、利用するには注意点があります。こちらを参照してください。

公式には開発中のバージョン2は使わないほうが良く、最新の安定版であるバージョン1が推奨されています。とはいえ、プラグインが安定して動作するバージョンがリリースされることはなく、ベータ版から正式版ができた場合、正式版はWordPress内部に組み込まれた状態でリリースされるという噂があります。それでも、この記事ではバージョン2を使用します。

認証

REST APIのセキュリティーを確保するために利用できる認証方法はいくつかありますが(詳しくはこちらを参照してください)、さまざまな認証方法の賛否を簡単に説明します。

基本認証

もっとも基本的な認証方法は、すべてのリクエストとヘッダーにユーザー名とパスワードを送信します。送信にはSSLを使う必要があります。そうしないと、ユーザー名とパスワードが知られてしまい攻撃される可能性があるからです。また、クライアントIDとクライアント・シークレットをクライアントに送ります。

クッキー認証

標準のWordPressに組み込まれているログインシステムで認証できます。この認証方法の難しいところは、CSRFの問題を避けるためには、システムをWordPressの内部で利用する必要があることです。外部やほかのアプリからAPIにアクセスする必要があるため、この方法はお勧めできません。

OAuth認証

記事ではOAuthを実装する非標準的な方法を紹介します。ユーザーは明確なアプリケーション認証はできませんが、代わりにWordPressログイン機能にシームレスに接続し、ユーザー用のAngularアプリを認証し、アクセストークンを取得します。そしてAPIリクエストの認証のためにJSアプリに情報を転送します。

OAuth認証でもSSLが必要なことは重要ですので、再度、書いておきます。記事は紹介なのでSSLの複雑さには触れませんが、コード自体はSSLを使っても使わなくても違いはありません。

OAuth認証は基本的認証よりも優先して利用すべきです。ブラウザーにユーザーのユーザー名やパスワードを保存したり、クライアントIDやクライアント・シークレットをユーザーに提供しなくてもよいからです。OAuth認証はプラグインがあってはじめて有効なので、WordPress OAuthサーバーを利用します。

トークンを共有

WPにログインしてトークンを作成したら、なんらかの方法でトークンをJSアプリと共有する必要があります。共有するための方法はたくさんあり、どの方法を使うかはニーズや個人の好み次第です。記事では2つの方法を取り上げますが、どちらもブラウザーのバージョンによる制約を受ける可能性を、あらかじめ知っておいたほうがよいでしょう。

ワイルドカードドメインCookieの設定

1つ目の方法は、両方のアプリが同一のサブドメイン上にあることが条件になり、ワイルドカードCookieを設定してからAngular側のクッキーを利用します。ワイルドカードCookieを使う場合、同一のサブドメインを持つようにローカルホストファイルに注意しておくことが重要です。

私はVagrantとVagrantホストマネジャーを使用して、WordPress仮想マシンのホスト名をsitepoint.localに、Vagrant仮想マシンのホスト名をapp.sitepoint.localに設定しました。自動的にホストファイルが以下のように編集されます。

192.168.33.16  app.sitepoint.local  # VAGRANT: 297067a67f66f631aa1962e3b49ab73c (default) / cc52bb5a-3972-4b55-8e0c-0c805b9c6f1c
192.168.33.15  sitepoint.local  # VAGRANT: 6a5b8c757547fe9f0a32a0c747a91a79 (default) / b08c3e7d-cba8-4130-a11b-b26494574280

記事では上記の方法を使いますが、複雑だと感じたらiframeを使う方法を考えるとよいでしょう。

iframeを介してlocalStorageに投稿

iframeを使う方法はクッキーを使いたくない人や同一のサブドメイン上にWordPressとAngularアプリを持っていない人にお勧めです。SPAからWordPressへiframeを引き出し、メッセージをiframeに投稿します。iframeの中ではユーザーがあとで使えるようにアクセストークンを取得し、JSアプリのlocalStorageに保存するためのメッセージが来るのを待っています。ブラウザーの互換性に関してはこちらを参照してください。

サーバー

最初に、アクセストークンを生成するコードを含むログイン画面用のテンプレートを作成します。次に、クッキー(または選択した方法によってはiframe)を利用するためにログイン/ログアウト機能に接続します。

サーバー仮想マシンを作成

さあ、作業を始めましょう! 最初にScotchbox VagrantfileをまねてWordPressプロジェクトから始めます。

任意の端末のアプリを開きプロジェクトを保存しておくフォルダーに進みます。私の場合、/boxesです。そして、Scotchboxレポをまねて先へ進みます。

cd /boxes
git clone https://github.com/scotch-io/scotch-box.git sitepoint-wp-rest-api
cd sitepoint-wp-rest-api

# remove .git folder in order not to get confused if you later initialise your own repository
rm -rf .git

# Initialise a vagrant machine
vagrant up

ここで好みのIDEまたはテキストエディターがあるsitepoint-wp-rest-apiフォルダーを開いてもよいでしょう。Vagrantfileを編集する必要がありますから。

Vagrantfileをまねて作った場合、初期設定では以下のように表示されます。

# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|

    config.vm.box = "scotch/box"
    config.vm.network "private_network", ip: "192.168.33.10"
    config.vm.hostname = "scotchbox"
    config.vm.synced_folder ".", "/var/www", :mount_options => ["dmode=777", "fmode=666"]

    # Optional NFS. Make sure to remove other synced_folder line too
    #config.vm.synced_folder ".", "/var/www", :nfs => { :mount_options => ["dmode=777","fmode=666"] }

end

ここでは2つのことに注意します。

  1. IPの変更
  2. ホスト名の変更

192.168.33.10で動作するネットワークデバイスまたは別の仮想マシンをすでに持っている場合、必ず変更してください。プライベートアドレススペースの範囲内であればどのIPアドレスを選択してもOKです。

サブドメインクッキーを使う方法を利用したいと考えているなら、ホスト名をFQDNに変更するのも重要です。

オプション:仮想マシンのRAM/CPUも増やせます。RAM/CPUの機能は第2の仮想マシンでも役立ちます。たとえば、bash npm installを実行する必要がある場合などに役立ちます。仮想マシンの性能をあげておけば、より短時間で実行できます。性能をあげる方法はコードスニペットの最後にあるコメント欄を確認してください。512MB RAM、1CPU(Vagrantのデフォルト値)でシステムがいかに動作するかを確認するのも参考になるかもしれません。開発目的のためには速くなって欲しいものです。そのあと、WordPress Webサイトのスピードのテスト/最適化をすれば再度調整できます。

Vagrantfileは最終的には以下のようになります。

# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|

    config.vm.box = "scotch/box"
    config.vm.network "private_network", ip: "172.31.255.254"
    config.vm.hostname = "sitepoint-wp-rest-api.test"
    config.vm.synced_folder ".", "/var/www", :mount_options => ["dmode=777", "fmode=666"]

    # Optional NFS. Make sure to remove other synced_folder line too
    #config.vm.synced_folder ".", "/var/www", :nfs => { :mount_options => ["dmode=777","fmode=666"] }

    # Optional performance tweaking
    #config.vm.provider "virtualbox" do |v|
    #   v.memory = 2048
    #   v.cpus = 2
    #end
end

仮想マシンを起動する前にもう1つだけ作業が必要です。vagrant-hostupdaterプラグインのインストールです。このプラグインはvagrant upを実行した場合にVagrantfile内で付与されるIPおよびホスト名を使ってローカルホストを更新します。すぐにこの作業の意味が分かると思います。

# Install Vagrant host udpater plugin
vagrant plugin install vagrant-hostsupdater

ここでコンピュータを再起動します。

vagrant up

sudoパスワードを求められるかもしれません。vagrant-hostupdater/etc/hostsを編集するからです。このプロセスには管理権限が必要になります。

scotch/box画像をローカルネットワークにすでにあるかどうか次第ですが、1分(または2、3分)程度時間がかかります。画像がない場合、scotch/box画像をダウンロードする必要があります。

「http://172.31.255.254/」にアクセスすると、Scotchbox情報ページが表示されます(実際に表示されるのはまねて作成したScotchboxレポジトリのパブリックフォルダーにあるindex.phpです)。

hostupdaterプラグインの作業結果は同一ページ内になりますが、「http://sitepoint-wp-rest-api.test/」にアクセスすれば表示されます。Sitepoint-wp-rest-api.testはローカルホストファイルを介して172.31.255.254になります。ここからFQDNを使ってREST APIにアクセスします。

WordPressのインストール

サーバーが動作したので、WordPressをインストールします。ローカルユーザーフォルダーに移動してWordPressをダウンロードします。WordPressを解凍して構成ファイルを作成し、RAWファイルをsitepoint-wp-rest-api内部のバブリックフォルダーにコピーします。

cd ~
curl -OL http://wordpress.org/latest.tar.gz
tar xzvf latest.tar.gz
cd ~/wordpress
cp wp-config-sample.php wp-config.php

# Do not forget to change /boxes to the actual folder onb *your* system
sudo rsync -avP ~/wordpress/ /boxes/sitepoint-wp-rest-api/public

IDEに戻り、wp-config.phpを開きます。ここに示されたようにDB認証情報を入力します。さらに、構成ファイルにWP_HOMEWP_SITEURL変数を追加するとよいでしょう。この変数はデータベースの値を上書きし、コンピュータ環境/ホスト間でのバージョン付与や変更が簡単になります。

// wp-config.php

/** The name of the database for WordPress */
define('DB_NAME', 'scotchbox');

/** MySQL database username */
define('DB_USER', 'root');

/** MySQL database password */
define('DB_PASSWORD', 'root');

/** This is new, WP SiteURL and Home globals override */
define('WP_SITEURL', 'http://sitepoint-wp-rest-api.test/');
define('WP_HOME', WP_SITEURL);

これらの値を変更し、ファイルを保存します。

再度、「http://sitepoint-wp-rest-api.test/」にアクセスします。今度は図のようなWordPressインストールウィザードが表示されます。

WordPress install - step 2

「次へ」を数回クリックします。最終的にtwentysixteen(2016)テーマを実行するディフォルトのWordPress Webサイトが表示されます。

REST APIプラグインのインストール

WordPress REST APIプラグインページに進み、プラグインをダウンロードします。ダウンロードしたファイルを解凍し、wp-content/plugins/にコピーします。「http://sitepoint-wp-rest-api.test/wp-admin」にアクセスし、左のメニューのプラグインをクリックします。WordPress REST APIが表示されますのでアクティベートします。このAPIに設定は不要です。これで完了です!

「http://sitepoint-wp-rest-api.test/wp-json/wp/v2/posts」にアクセスすると、すべての投稿を含むJSON配列を取得できます。

[
   {
      "id":1,
      "date":"2016-05-09T17:49:50",
      "date_gmt":"2016-05-09T17:49:50",
      "guid":{
         "rendered":"http:\/\/sitepoint-wp-rest-api.test\/?p=1"
      },
      "modified":"2016-05-09T17:49:50",
      "modified_gmt":"2016-05-09T17:49:50",
      "slug":"hello-world",
      "type":"post",
      "link":"http:\/\/sitepoint-wp-rest-api.test\/2016\/05\/09\/hello-world\/",
      "title":{
         "rendered":"Hello world!"
      },
      "content":{
         "rendered":"<p>Welcome to WordPress. This is your first post. Edit or delete it, then start writing!<\/p>\n"
      },
      "excerpt":{
         "rendered":"<p>Welcome to WordPress. This is your first post. Edit or delete it, then start writing!<\/p>\n"
      },
      "author":1,
      "featured_media":0,
      "comment_status":"open",
      "ping_status":"open",
      "sticky":false,
      "format":"standard",
      "categories":[
         1
      ],
      "tags":[

      ],
      "_links":{
         "self":[
            {
               "href":"http:\/\/sitepoint-wp-rest-api.test\/wp-json\/wp\/v2\/posts\/1"
            }
         ],
         "collection":[
            {
               "href":"http:\/\/sitepoint-wp-rest-api.test\/wp-json\/wp\/v2\/posts"
            }
         ],
         "about":[
            {
               "href":"http:\/\/sitepoint-wp-rest-api.test\/wp-json\/wp\/v2\/types\/post"
            }
         ],
         "author":[
            {
               "embeddable":true,
               "href":"http:\/\/sitepoint-wp-rest-api.test\/wp-json\/wp\/v2\/users\/1"
            }
         ],
         "replies":[
            {
               "embeddable":true,
               "href":"http:\/\/sitepoint-wp-rest-api.test\/wp-json\/wp\/v2\/comments?post=1"
            }
         ],
         "version-history":[
            {
               "href":"http:\/\/sitepoint-wp-rest-api.test\/wp-json\/wp\/v2\/posts\/1\/revisions"
            }
         ],
         "wp:attachment":[
            {
               "href":"http:\/\/sitepoint-wp-rest-api.test\/wp-json\/wp\/v2\/media?parent=1"
            }
         ],
         "wp:term":[
            {
               "taxonomy":"category",
               "embeddable":true,
               "href":"http:\/\/sitepoint-wp-rest-api.test\/wp-json\/wp\/v2\/categories?post=1"
            },
            {
               "taxonomy":"post_tag",
               "embeddable":true,
               "href":"http:\/\/sitepoint-wp-rest-api.test\/wp-json\/wp\/v2\/tags?post=1"
            }
         ],
         "curies":[
            {
               "name":"wp",
               "href":"https:\/\/api.w.org\/{rel}",
               "templated":true
            }
         ]
      }
   }
]

ほかの方法もあります。全体の一覧を見るにはAPIドキュメントを参照してください。

APIは公開されている情報のみ表示します。個人的な投稿を追加して、APIから再度すべての投稿のリクエストを試みてください。個人的な投稿は表示されないはずです。

このような場合にWordPress OAuthプラグインが役立ちます。ユーザーのユーザー名やパスワードをクライアントの側に置いておきたくはないが、リクエストがあるたびに認証情報を送信したくもないとも考えます。そのため、Angular側でデフォルトのWordPressログインクッキーを使えません。

OAuthサーバープラグインをインストール

WP Oauth Server pluginプラグインのページにアクセスし、プラグインをダウンロードして展開、展開したフォルダーをwp-content/plugins/にコピーします。再度、「http://sitepoint-wp-rest-api/wp-admin/」にアクセスし、左側のメニューPluginsをクリックしてOAuth Serverプラグインをアクティベートします。

OAuthを使った認証方法は複数あります。認証コード付与タイプを使えばクライアントアプリはユーザー名とパスワードをクライアントIDやクライアント・シークレットと共に認証サーバーに投稿でき、あとですべてのAPIリクエストの認証コードとして使われるアクセストークンを再度入手できます。

子テーマを作成

WordPressテンプレートをログインページへ実装する前に、元のテーマファイルと混ざってしまわないように子テーマを作成する必要があります。wp-content/themesの下に新規のフォルダーを作成し、twentysixteen-childという名前を付けます。新しく作成したtwentysixteen-childフォルダーにfunctions.phpとstyle.cssの2つのファイルを作成します。

functions.phpに以下のコードを追加します。

<?php
// wp-content/themes/twentysixteen-child/functions.php

add_action( 'wp_enqueue_scripts', 'theme_enqueue_styles' );
function theme_enqueue_styles() {
    wp_enqueue_style( 'parent-style', get_template_directory_uri() . '/style.css' );
    wp_enqueue_style( 'child-style',
        get_stylesheet_directory_uri() . '/style.css',
        array('parent-style')
    );
}

スタイルの上書きを簡単にするため、twentysixteenとい名付けたテーマの元のCSSの後にカスタマイズしたstyle.cssに項目を追加します。

style.cssには以下のコードを追加します。

/*
 Theme Name:     twentysixteen Child Theme
 Author:         Almir Bijedic
 Author URI:     http://almirbijedic.rocks
 Template:       twentysixteen
 Version:        1.0.0
*/

/* Add Custom CSS after this line */

WordPressダッシュボードから、実際に子テーマをアクティベートするのをお忘れなく。左側のメニューからThemesをクリックします。twentysixteenの子テーマを見つけたらクリックしてアクティベートします。

子テーマの用意できたので、さらに新しいファイルを追加します。login.phpをtwentysixteen-childに作成し、次のコードを追加します。

<?php
// wp-content/themes/twentysixteen-child/login.php

/*
Template Name: Login Page
*/

$client_id = '';
$client_secret = '';

WordPressダッシュボードからAuth Serverメニューに進むとクライアントIDとクライアント・シークレットを取得できます。左側のメニューでClientsタブをクリックし、アプリケーションを追加します。

WP OAuth Server - Client ID and Secret generation 1

「Angular App」と名前を付けて、リダイレクトを相対URL/ログインに設定します。

WP OAuth Server - Client ID and Secret generation 2

作成したアプリケーションはSPAのクライアントの役割を果たします。すべてのユーザーのログインは同一のクライアントを介します。

WP OAuth Server - Client ID and Secret generation 3

では、クライアントIDとクライアント・シークレットをテンプレートにペーストします。

<?php
// wp-content/themes/twentysixteen-child/login.php

/*
Template Name: Login Page
*/

$client_id = 'CWwPjFsaCaXaT8qRl2UIwc9AI8Ex4i';
$client_secret = 'vHe1wyHYIk9Gv3OVU9YPSu124KbJif';

次の段階ではユーザーをOAuth認証ページにリダイレクトします。特別なリダイレクトを使って順番にユーザーを通常のwp-login.phpにリダイレクトします。クエリ文字列の特別なリダイレクトは、OAuthプラグインがユーザーの入力した認証情報を取得し、access_tokenを作成するために必要です。

以下のコードをクライアント・シークレットの下に追加します。

$url = site_url() . '?oauth=authorize&response_type=code&client_id=' . $client_id;

// Redirect to OAuth login page
header('Location: ' . $url);
die();

ぜひ一度自分で試してみてください。WordPress WebサイトのローカルURLは「http://sitepoint-wp-rest-api.test」です。「http://sitepoint-wp-rest-api.test/?oauth=authorize&response_type=code&client_id=CWwPjFsaCaXaT8qRl2UIwc9AI8Ex4i」にアクセスしてください。クライアントIDを自分用に変更するのをお忘れなく。

ユーザー名とパスワードを送信したら、/login?code=”code-here”にリダイレクトされます。すると、404ページが表示されます。これは「http://sitepoint-wp-rest-api.test/login」のURL上の実際のページにテンプレートを設定していないからです。クエリ文字列のコードは次のOAuthの認証段階で使われるコードです。

アクセストークンを取得するためにクライアントIDとクライアント・シークレットと共にクエリ文字列のコードを送信する必要があります。テンプレートに戻り、POSTコールをOAuthサーバーに追加します。

<?php
// wp-content/themes/twentysixteen-child/login.php

/*
Template Name: Login Page
*/

$client_id = 'CWwPjFsaCaXaT8qRl2UIwc9AI8Ex4i';
$client_secret = 'vHe1wyHYIk9Gv3OVU9YPSu124KbJif';

$code = false;
if(isset($_GET['code'])) {
    $code = $_GET['code'];
}

// If there is no code present, first get the code by redirecting to login page
if(!$code) {

    $url = site_url() . '?oauth=authorize&response_type=code&client_id=' . $client_id;
    header('Location: ' . $url);
    die();

} else {

    // Encode the client ID and secret with base64 in 
    // order to add it to the Authorization header
    $auth = base64_encode($client_id.':'.$client_secret);
    try {

        // Making the Call to get the access token
        $args = [
            'headers' => [
                'Authorization' => 'Basic ' . $auth
            ],
            'body' => [
                'grant_type'    => 'authorization_code',
                'code'          => $code
            ],
    ];

        // Send the actual HTTP POST with the built-in WordPress HTTP library.
        $json = wp_remote_post( site_url() . '?oauth=token', $args );

        if(is_array($json) && isset($json['body'])) {

            $json = json_decode($json['body']);

            // Retrieve the access token from the response
            $auth_token = $json->access_token;
            $user_id = get_current_user_id();


            // Set the cookie
            setcookie('wordpress_access_token', $auth_token, time() + 3600, '/', preg_replace('#^https?://#', '', rtrim(site_url(),'/')), 0);

            // Save the cookie to user meta
            // Can be useful for debugging or if needed to refresh the cookie
            update_user_meta($user_id, 'wordpress_access_token', $auth_token);
        } else {
            print_r($json);
            die();
        }

        // All set, redirect to the home page
        header('Location: ' . site_url());
    } catch (Exception $e) {
        var_dump($e);
    }
}

これでテンプレートは準備完了です。Login Pageに設定されたテンプレートを使って新規のWordPressページを作成します。左側のメニューからPagesをクリックしてAdd Newを選択、好きな名前を付けます。重要なのが、ページ作成画面の右側のメニューからテンプレートをLogin Templateに設定することです。

Create login page

固定リンクをprettyに設定するのをお忘れなく。というのは、OAuthクライアントのリダイレクトURLを/loginに設定するからです。この設定をするには、再度管理ダッシュボードに進み、左側のメニューからSettings、Permalinksの順に選択します。通常の設定では、Post名を選択し、保存をクリックします。

これで「http://sitepoint-wp-rest-api.test/login」にアクセスできます。、一度試しに使ってみてください! ログインしたら、開発者用ツールを開き、ResourcesからCookiesへ進み、wordpress_access_tokenが見られるか確認してください。

Check wordpress_access_token cookie

Vagrantを持っていない仮想マシンを使っている場合、仮想マシンがsitepoint-wp-rest-apiドメインを読み込めない可能性があります。このドメインがローカルホストファイルのみに設定されているからです。エラーが起こった場合、仮想マシンにSSHで接続し、site-point-wp-rest-api.testドメインを追加してローカルホストに接続します。

127.0.0.1 sitepoint-wp-rest-api.test

実際に仮想マシンがsitepoint-wp-rest-apiドメインを読み込めない場合、エラーを引き起こす可能性のある具他的なコードは以下です。

$json = wp_remote_post( site_url() . '?oauth=token', $args );

site_url()は、http://sitepoint-wp-rest-api.test(私の場合)に設定されており、仮想マシンは読み取る方法が分かりません。

WordPress APIからリクエストを送る前にもう1つ作業をします。ダッシュボード画面の左上に現在のユーザーのaccess_tokenを表示するために、ユーザーに設定したメタフィールドを使用します(「hello dolly」プラグインなどはまさにその例です!)。

WordPressテーマの子テーマに進み、functions.phpに以下のコードを追加します。

// wp-content/themes/twentysixteen-child/functions.php

// Only for admin
if (current_user_can('manage_options')) {
    add_action('admin_notices', 'display_user_token');
}
function display_user_token() {
    $user_id = get_current_user_id();
    $auth_token = get_user_meta( $user_id, 'wordpress_access_token', true);
    echo $auth_token;
}

では、WPダッシュボードにログインし、トークンをコピーします。次に隠れウィンドウを開きます。この手順は重要です。なぜなら、認証のための通常のWordPressクッキーとOAuthアクセストークンの両方を使ってもAPIを待ち行列に追加できないため、両方が存在するとエラーが返ってくるからです。そして「http://sitepoint-wp-rest-api.test/wp-json/wp/v2/users/1/?context=edit」にアクセスしてください。

以下のようなコードが返ってくるはずです。

{
    "code":"rest_not_logged_in",
    "message":"You are not currently logged in.",
    "data": {"status" : 401}
}

次に「http://sitepoint-wp-rest-api.test/wp-json/wp/v2/users/1/?context=edit&access_token=ACCESS_TOKEN」にアクセスします。

できました!

すべて問題なく動作するかダブルチェックするために以下のcURLコールも試せます。第1コールがエラーメッセージを返し、もう一方がWordPressから「Hello World!」の投稿を消去します。

# this one returns an error
curl -X DELETE http://sitepoint-wp-rest-api.test/wp-json/wp/v2/posts/1/

# this one should really delete the post -
# you can verify it in the WP dashboard
curl -X DELETE http://sitepoint-wp-rest-api.test/wp-json/wp/v2/posts/1/?access_token=<access-token>

コンテキストが正しい値になることが重要です。その値によって異なるフィールドが返されるからです。詳しくはWP REST APIドキュメントをご覧ください。また、ユーザーがリダイレクトなしの通常のwp-login.phpを使っているかを確認する必要があります。まだアクセストークンを取得するためのページにリダイレクトされているかもしれないからです。

ユーザーがログインし、/loginページにアクセスすると、作成したOAuthのテンプレートのコードが実行され、ユーザーは新規のaccess_tokenを入手します。

以下のコードをfunctions.phpに追加します。

// wp-content/themes/twentysixteen-child/functions.php

add_filter( 'login_redirect', 'ab_login_redirect', 10, 3 );
function ab_login_redirect( $redirect_to, $request, $user ) {
    return site_url() . '/login';
}

ユーザーがWordPressからログアウトしたらクッキーが消去されているかも確認する必要があります。

// wp-content/themes/twentysixteen-child/functions.php

add_action ( 'login_form_logout' , 'ab_cookie_remove_logout' );
function ab_cookie_remove_logout() {
    setcookie('wordpress_access_token', "expired", time() - 3600, '/', preg_replace('#^https?://#', '', rtrim(site_url(),'/')), 0);
    wp_logout();
}

子テーマの最終的なfunctions.phpファイルは以下のようになります。

<?php
// wp-content/themes/twentysixteen-child/functions.php

add_action( 'wp_enqueue_scripts', 'theme_enqueue_styles' );

function theme_enqueue_styles() {
    wp_enqueue_style( 'parent-style', get_template_directory_uri() . '/style.css' );
    wp_enqueue_style( 'child-style',
        get_stylesheet_directory_uri() . '/style.css',
        array('parent-style')
    );
}

if (current_user_can('manage_options')) {
    add_action('admin_notices', 'display_user_token');
}
function display_user_token() {
    $user_id = get_current_user_id();
    $auth_token = get_user_meta( $user_id, 'wordpress_access_token', true);
    echo $auth_token;
}

add_filter( 'login_redirect', 'ab_login_redirect', 10, 3 );
function ab_login_redirect( $redirect_to, $request, $user ) {
    return site_url() . '/login';
}

add_action ( 'login_form_logout' , 'ab_cookie_remove_logout' );
function ab_cookie_remove_logout() {
    setcookie('wordpress_access_token', "expired", time() - 3600, '/', preg_replace('#^https?://#', '', rtrim(site_url(),'/')), 0);
    wp_logout();
}

これでAPIサーバーの準備完了です。次はAngularアプリを見ていきます。(明日に続く)

(原文:Single Page Apps Using AngularJS and the WordPress REST API

[翻訳:中村文也]
[編集:Livit

Web Professionalトップへ

WebProfessional 新着記事