この章では、JSONシリアライズ形式を使用して単純なWebサービスからデータを転送する方法について説明します。このWebサービスは、PHPのGD拡張モジュールを使用してイメージを作成するクライアントからコールされます。
この章のトピックは、次のとおりです。
新規のPHPファイルac_get_json.php
を作成し、次を含めます。
<?php /** * ac_get_json.php: Service returning equipment counts in JSON * @package WebService */ require('ac_db.inc.php'); if (!isset($_POST['username'])) { header('Location: index.php'); exit; } $db = new \Oracle\Db("Equipment", $_POST['username']); $sql = "select equip_name, count(equip_name) as cn from equipment group by equip_name"; $res = $db->execFetchAll($sql, "Get Equipment Counts"); $mydata = array(); foreach ($res as $row) { $mydata[$row['EQUIP_NAME']] = (int) $row['CN']; } echo json_encode($mydata); ?>
このWebサービスに認証機能はありません。これはAnyCoアプリケーションから見て外部になります。必要になるのは、POST
データへのusername
の入力のみです。
このファイルはAnyCo Corpの備品割当を問い合せ、PHPのjson_encode()
を使用して、統計をJSON形式で返します。EQUIPMENT
表に現在格納されているデータに応じて、Webサービスから次のような出力が返されます。
{"cardboard box":1,"pen":4,"computer":2,"telephone":3,"paper":3,"car":1}
Webサービスをコールしグラフを作成する新規のPHPファイルac_graph_img.php
を作成します。初期のファイルには次が含まれています。
<?php /** * ac_graph_img.php: Create a JPEG image of the equipment allocation statistics * * Do not put any text or white space before the "<?php" tag because it will * be incorporated into the image stream and corrupt the picture. * * @package Graph */ define('WEB_SERVICE_URL', "http://localhost/ac_get_json.php"); session_start(); require('ac_equip.inc.php'); $sess = new \Equipment\Session; $sess->getSession(); if (!isset($sess->username) || empty($sess->username) || !$sess->isPrivilegedUser()) { header('Location: index.php'); exit; } $data = callservice($sess); do_graph("Equipment Count", 600, $data); // Functions ?>
使用しているシステムに合わせて、WebサービスのURLを変更します。
このファイルにcallservice()
関数を追加します。
/** * Call the service and return its results * * @param Session $sess * @return array Equipment name/count array */ function callservice($sess) { // Call the web "service" to get the Equipment statistics // Change the URL to match your system configuration $calldata = array('username' => $sess->username); $options = array( 'http' => array( 'method' => 'POST', 'header' => 'Content-type: application/x-www-form-urlencoded', 'content' => http_build_query($calldata) ) ); $ctx = stream_context_create($options); $result = file_get_contents(WEB_SERVICE_URL, false, $ctx); if (!$result) { $data = null; } else { $data = json_decode($result, true); // Sort an array by keys using an anonymous function uksort($data, function($a, $b) { if ($a == $b) return 0; else return ($a < $b) ? -1 : 1; }); } return($data); }
これはPHPのストリーム機能を使用して、URLをリクエストし統計を取得します。ストリーム・コンテキストには、サービスで必要になるpost変数としてusername
が含まれています。
JSON形式からデータがデコードされ、配列は名前順でソートされます。PHPのuksort()
関数への第2引数は、データ比較を行う匿名関数です。
ac_graph_img.phpを編集し、イメージを作成する関数を追加します。
/** * Draw a bar graph, with bars projecting horizontally * * @param string $title The Graph's title * @param type $width Desired image width in pixels * @param array $items Array of (caption, value) tuples */ function do_graph($title, $width, $items) { $border = 50; // border space around bars $caption_gap = 4; // space between bar and its caption $bar_width = 20; // width of each bar $bar_gap = 40; // space between each bar $title_font_id = 5; // font id for the main title $bar_caption_font_id = 5; // font id for each bar's title // Image height depends on the number of items $height = (2 * $border) + (count($items) * $bar_width) + ((count($items) - 1) * $bar_gap); // Find the horizontal distance unit for one item $unit = ($width - (2 * $border)) / max($items); // Create the image and add the title $im = ImageCreate($width, $height); if (!$im) { trigger_error("Cannot create image<br>\n", E_USER_ERROR); } $background_col = ImageColorAllocate($im, 255, 255, 255); // white $bar_col = ImageColorAllocate($im, 0, 64, 128); // blue $letter_col = ImageColorAllocate($im, 0, 0, 0); // black ImageFilledRectangle($im, 0, 0, $width, $height, $background_col); ImageString($im, $title_font_id, $border, 4, $title, $letter_col); // Draw each bar and add a caption $start_y = $border; foreach ($items as $caption => $value) { $end_x = $border + ($value * $unit); $end_y = $start_y + $bar_width; ImageFilledRectangle($im, $border, $start_y, $end_x, $end_y, $bar_col); ImageString($im, $bar_caption_font_id, $border, $start_y + $bar_width + $caption_gap, $caption, $letter_col); $start_y = $start_y + ($bar_width + $bar_gap); } // Output the complete image. // Any text, error message or even white space that appears before this // (including any white space before the "<?php" tag) will corrupt the // image data. Comment out the "header" line to debug any issues. header("Content-type: image/jpg"); ImageJpeg($im); ImageDestroy($im); }
この関数はPHPのGD拡張モジュールを使用してグラフを作成します。デフォルトのGDフォントは若干洗練性に欠けますが、新しいフォントの追加が可能です。出力はJPEGストリームであるため、WebページのHTMLコードにイメージ・ファイルを含めるかわりに、任意の場所でPHPファイルをコールできます。
AnyCoアプリケーションでは、新規ファイルac_graph_page.php
を作成してイメージを統合します。
<?php /** * ac_graph_page.php: Display a page containing the equipment graph * @package Graph */ session_start(); require('ac_equip.inc.php'); $sess = new \Equipment\Session; $sess->getSession(); if (!isset($sess->username) || empty($sess->username) || !$sess->isPrivilegedUser()) { header('Location: index.php'); exit; } $page = new \Equipment\Page; $page->printHeader("AnyCo Corp. Equipment Graph"); $page->printMenu($sess->username, $sess->isPrivilegedUser()); echo <<<EOF <div id='content'> <img src='ac_graph_img.php' alt='Graph of office equipment'> </div> EOF; $page->printFooter(); ?>
注意: 'EOF;'トークンは行の先頭に配置し、その後に空白が含まれないようにします。 |
イメージはHTMLの通常のimg
タグ内に配置されます。
ブラウザにAnyCoアプリケーションをロードし、Administrator
としてログインします。左側のナビゲーション・メニューから「Equipment Graph」リンクをクリックします。グラフが表示されます。
イメージが表示されない場合は、エラー・メッセージなどのテキストや<?php
タグの前の空白など、ac_graph_img.php
に問題があることが考えられます。このテキストがイメージ・ストリームに含められ、その結果画像が無効になります。この種の問題をデバッグするためには、ac_graph_img.php
で$session
チェックおよびheader()
コールをコメント・アウトすると役に立ちます。次に、イメージ・ストリームの生データを表示させるため、ブラウザで次のリンクをロードします。
http://localhost/ac_graph_img.php
JSON形式は、ブラウザとPHPサーバー間のデータ転送効率を上げる目的でよく利用されます。Webサービスac_get_json.php
は、使用可能なJSONグラフィック・ライブラリの多くで直接使用できます。