こんにちは。ライターの亀田です。実用的なWebアプリを作る際には、データ通信はとても重要な課題です。
Webアプリでのデータ通信に良く使われるデータ形式として、JSONとXMLがあります。これらはとても扱いやすく、大変便利なフォーマットです。
CakePHPにでは、これらのデータフォーマットを簡単に扱える方法が存在してます。今回は、このデータフォーマットのうち、特にJSONを扱う方法について説明します。
- JSONとは
- JsonViewとXmlViewの使い方
- JSONPレスポンスの使い方
JSONとは
JSONとはJavaScript Object Notationの略で、テキストベースのデータフォーマットの一種です。名前の由来の通りJavaScriptのオブジェクト表記構文のサブセットとして扱われています。
一方、XMLは、ExtensibleMarkupLanguageの略であり、インターネット上で様々なデータを扱うテキストベースのデータフォーマットの一種です。基になったのがHTML形式であり、HTML同様<>で挟まれたタグではさまれたものです。
見た目がHTMLと似ていますが、HTMLを抽象化して作られたのがこのフォーマットなのです。
実はこの2つ、形式は違うのですが、ほぼ同じものを扱うことができるのです。ですから、状況に応じて使い分ければいいわけです。
JSONの特徴をあげるのなら、XMLと比べてもよりシンプルであり、 各種言語との親和性も高く使い勝手も良いという点が挙げられます。そもそも、JavaScriptプログラムでのデータ通信を目的としているので、Webアプリケーションと大変相性が良いのです。
なお、PHPにはJSONを利用するAPIが用意されています。興味のある方は、以下を参考にしてみてください。
JsonViewとXmlViewの使い方
では、一体JSONはどのような場面で使われるのでしょうか?
一般に、JSONは、様々な種類のデータを外部ファイルとして扱うことを目的としています。したがって、ここでは、何らかのデータをJSONデータとして出力する簡単なサンプルを紹介することにします。
まず、特定のURLを指定すればJSONデータを取得できるようにします。そのために、route.phpを、以下のように変更します。なお、みやすさのためにコメントアウト部分は削除してあります。
config/route.php
<?php use CakeHttpMiddlewareCsrfProtectionMiddleware; use CakeRoutingRouteBuilder; use CakeRoutingRouter; use CakeRoutingRouteDashedRoute; Router::defaultRouteClass(DashedRoute::class); #以下の1行を追加 Router::extensions(['json', 'xml']); Router::scope('/', function (RouteBuilder $routes) { $routes->registerMiddleware('csrf', new CsrfProtectionMiddleware([ 'httpOnly' => true ])); $routes->applyMiddleware('csrf'); $routes->connect('/', ['controller' => 'Pages', 'action' => 'display', 'home']); $routes->connect('/pages/*', ['controller' => 'Pages', 'action' => 'display']); $routes->fallbacks(DashedRoute::class); });
Router::defaultRouteClassは、デフォルトのRouteを指定するときに使用します。
また、Router::extensionsは、ファイル拡張子のルーティングを行います。この場合、jsonとxmlが指定されているので、JSONとXMLの拡張子が両方使えることを意味します。
次はコントローラを作ってみましょう。
src/controller/ApiController.php
<?php namespace AppController; use CakeCoreConfigure; use CakeNetworkExceptionNotFoundException; use CakeViewExceptionMissingTemplateException; class ApiController extends AppController { public function test(){ $sample_list = [ [ "list" => "ListA", "content" => "ContentA" ], [ "list" => "ListB", "content" => "ContentB" ], [ "list" => "ListC", "content" => "ContentC" ] ]; $this->set([ 'sample_list' => $sample_list, '_serialize' => ['sample_list'] ]); } }
たったこれだけの設定で、$sample_listというデータを、JSONおよび、XMLデータとしてとして出力することができます。
実際にアクセスをしてみてみることにしましょう。XAMPPなどのローカルな環境で開発を行っている場合は、以下のようにURL指定してください。
http://localhost/[プロジェクト名]/api/test.json
以下のように、ブラウザ上でjsonのデータを得ることができました。
ちなみに、URL末尾の「.json」を、「.xml」にしてみてください。
http://localhost/[プロジェクト名]/api/test.xml
同じデータがXMLで出力されるのがわかります。このように、CakePHPでは簡単にデータをJSONおよびXML形式で出力することが出来るのです。
CakePHPでは、.jsonと.xmlのいずれかの拡張子のサポートを有効にすることで、 自動的に新しいビュークラスを使用することが出来るようになります。 JSONのクラスはJsonView、XMLのクラスはXmlViewと言います。
これらのデータビューは_serializeキーを使用することにより簡単に生成されるのです。
JSONPレスポンスの使い方
JSONPとは何か
次に、JSONPレスポンスという方法を用い、作成したデータを受信する仕組みについて解説しましょう。
JSONPとは、Javascriptで非同期でデータを取得する手段の一つで、JavaScriptのscriptタグを使用してデータを取得する仕組みのことです。HTMLのscriptタグ、JavaScript(関数)、JSONを組み合わせて実現されます。
非同期通信というとAjaxがポピュラーですが、クロスドメイン制約と言いう制約があり万能ではありません。クロスドメインとは、異なるドメインを持つウェブサーバー間のアクセスのことを言います。
クロスドメイン制約とは、これを許可しないことであり、ajaxでは異なるドメイン間の通信が原則禁止されています。
それに対し、JSONPはクロスドメイン制約が無いため、ドメインが異なるサーバー間の通信に便利です。ですので、どのような方法で非同期通信をするのかによって手段を使い分ける必要があるのです。
なお、Ajaxについては、以下を参考にしてみてください。
JSONPを実際に使ってみる
では、実際にJSONPの仕組みを用い、前述のサンプルで出力されたjsonファイルを受け取ってその内容を出力してみることにしましょう。まずはApiController.phpを以下のように書き換えます。
<?php namespace AppController; use CakeCoreConfigure; use CakeNetworkExceptionNotFoundException; use CakeViewExceptionMissingTemplateException; class ApiController extends AppController { public function test(){ #以下の1行を追加 $this->response->header("Access-Control-Allow-Origin: *"); $sample_list = [ [ "list" => "ListA", "content" => "ContentA" ], [ "list" => "ListB", "content" => "ContentB" ], [ "list" => "ListC", "content" => "ContentC" ] ]; $this->set([ 'sample_list' => $sample_list, '_serialize' => ['sample_list'], #以下の1行を追加 '_jsonp' => true ]); } }
次のサンプルは、jQueryのgetJSON関数を用いてでjsonファイルを読み出し、HTMLを出力するものです。
sample.html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>jQuery TIPS</title> <script src="http://code.jquery.com/jquery-1.11.3.min.js"></script> </head> <body> <dl id="wrap"> <script type="text/javascript"> $(function(){ $.getJSON("http://localhost/json/api/test.json", function(data){ for(var i in data.sample_list){ var h = '<dt>' + data.sample_list[i].list + '</dt>' + '<dd>' + data.sample_list[i].content + '</dd>'; $("dl#wrap").append(h); } }) }); </script> </dl> </body> </html>
実際に使うときは、データの取得先urlであるhttp://localhost/json/api/test.jsonの部分を、任意の環境に合わせて書き換えてください。このページをWebサーバーの適切な場所に配置してアクセスすると、以下のように結果が出力されます。
これで、CakePHP3で出力されたJSONを読み出し、出力できたことを確認できました。CakePHPでJSONを用いて通信をする際には、データベースなどをからめていくと、更に実用的な処理をすることが可能になります。
このように、CakePHPでJSONを出力する仕組みとJSONP/Ajaxなどを連携すると、簡単に通信が実現するのです。
まとめ
ここでは、CakePHP3でJSONを扱うために、
- JSONとは
- JsonViewとXmlViewの使い方
- JSONPレスポンスの使い方
などについて解説しました。これにより、CakePHP3のJSONViewとJSONPを組み合わせれば、簡単にクロスドメインの非同期通信ができることがわかりました。もしも、JSONで何らかの通信の処理をしたいときは、この記事を参考にしてみてください。