Comments
Description
Transcript
中谷 紘章
Ajax 機能・API を利用した グルメブログ 国際文化学部 1 国際文化学科 4 年 学籍番号 05g0716 中谷 紘章 目次 1. はじめに 2. システム制作目的・価値 3. 利用した技術について 3-1 3-1-1 Ajax の概要 3-1-2 Ajax のメリット・デメリット 3-2 Web API について 3-2-1 Web API とは 3-2-2 マッシュアップとは 3-3 4. Ajax について Smarty について 3-3-1 Smarty とは 3-3-2 Smarty の システムの概要と主な機能 4-1 ログイン機能 4-2 記事の編集や保存 4-2-1 プラグイン 4-2-2 記事作成の流れ 4-3 画像のアップロード 4-3-1 画像アップロードの処理 4-3-2 画像の操作 4-4 カテゴリーの操作 2 4-5 グルメブログの画面表示 4-6 API を利用した機能 4-7 店の検索と表示 4-7-1基本的な利用方法 4-7-2 4-8 Ajax を使った情報の表示 4-8-1 時間がかかる処理を Ajax で行う 4-8-2 グルメブログでの Ajax の処理 4-9 5. 検索の仕方 データベースの構成 開発環境 5-1 XAMPP とは 5-2 PHP 5-3 MySQL 5-4 Apache 6. 考察・今後の課題 7. 参考文献 3 1.はじめに Web2。0 の普及に伴い、Web サービスを提供する Web サイトが年々増えつつある。Web サービスとは WWW 関連の技術を使い、ソフトウェアの機能をネットワークを通じて利用 できるようにしたもの。企業間の商取引を担う大規模なものから、単一の機能を持ったコ ンポーネントまで、様々な規模・種類のものがある。 機能の記述や呼び出し手順などの標準化が進行中であり、コンポーネント化された複数 の Web サービス同士をつなぎ合わせてアプリケーションと構築するというスタイルが次世 代のソフトウェア環境の主流になると予測されている。そうした環境が普及すると、従来 の OS やミドルウェアは、Web サービスを開発・実行する環境としての役割を担うように なり、サービス(およびそれらを組み合わせたアプリケーション)を利用するエンドユーザは、 現在の Web ブラウザを拡張したようなクライアントソフトを通して、すべてのソフトウェ アを操作するようになると考えられている。 こうした環境の基盤となるようなソフトウェアやサービス、開発環境、仕様などが各社か ら提案されており、Microsoft 社の Microsoft 。NET や、IBM 社などが中心となって進め ている UDDI プロジェクトなどが有名である。 現在のところ、XML をベースにした標準や標準案が多く、中でも、ソフトウェアの機能 の遠隔呼び出しの手順を定めるプロトコルは、XML ベースの SOAP がデファクトスタンダ ード(事実上の標準)の地位を築いている。また、Web サービスの記述言語としては WSDL が標準として普及すると見込まれている。 Web サービスは広い概念で、適用範囲も広いが、現在の標準はどれも最も基礎的な基盤技 術に関するものばかりで、具体的に高度なアプリケーションを構築しようとすると独自仕 様に頼らざるを得ない。今後は基盤技術をベースに各業界や分野に応じた数々の標準仕様 が登場していくものと思われる。 簡単に言えば Web サイトが持つ機能を、Web を通じて一般のアプリケーションからつか えるように公開すること。Web サービスを利用した有名なものに Google マップや Amazon、 じゃらんなどがあげられる。 本システムはブログ機能により多くの人々に料理情報を提供する Web アプリケーション である。Google Maps やリクルート Web サービスの Web API キーを利用した機能を設け 4 店の情報を検索し地図を表示できるようにする。 また本システムでは Ajax を利用し、その有用性や将来性を論じ、これらの機能を利用し た本システムの利用価値について論じていきたい。 5 2.システム製作目的・価値 本システム「グルメブログ」の製作動機はいくつかある。まず一つ目はブログそのものの 人気が高まりつつあるということ。人気ブログともなれば一日一万件のアクセスを越すこ とも珍しくない。ということは多くのユーザーに利用してもらう可能性が増えるというこ とだ。このような人気・流行を取り入れていこうと考えた。 そして二つ目の動機としては人間の生活に欠かせない「食」について情報を発信していき たいと思った。近年、食の問題はかなり大きく取り扱われている。その中でおいしくかつ 安全に生活できる情報を発信していきたいと考えた。 そしてただのグルメブログというものではなくそこから料理レシピもみることができ、自 分自身で料理ができるようにしていきたかった。 (画面2-1 6 ユーザー側の Top ページ画面) 3.利用した技術について(Ajax・Web API キー) 先ほど述べたように本システムでは Ajax と Web API キーを利用している。ここではこれ らの特徴や概要、有用性について論じていきたい。 3-1 Ajax について 3-1-1 Ajax の概要 Web2。0 時代の Web アプリケーションでは Ajax を使う場面も多く登場します。「Ajax」 発祥の地は、コンサルティング会社を経営する Jesse James Garrett 氏が、2005 年 2 月 18 日に投稿した「Ajax: A New Approach to Web Applications」(Ajax Web アプリケーショ ン へ の 新 し い ア プ ロ ー チ ) と い う エ ン ト リ ー で す 。 Ajax は 略 語 で 、 正 式 名 称 は 「Asynchronous JavaScript + XML」となります。 Web ブラウザに実装されている JavaScript の HTTP 通信機能を使って、Web ページのリ ロードを伴わずにサーバと XML 形式のデータのやり取りを行なって処理を進めていく対 話型 Web アプリケーションの実装形態。 従来、Web ブラウザを使った Web アプリケーションでは、データをサーバに通知して処 理結果を得るにはページ全体をロードしなおさなければならず、ネイティブアプリケーシ ョンのような操作性を得ることは難しかった。Ajax では、指定した URL から XML ドキュ メントを読み込む機能を使い、ユーザの操作や画面描画などと並行してサーバと非同期に 通信を行なうことで、サーバの存在を感じさせないシームレスな Web アプリケーションを 実現することができる。 ちなみに、JavaScript の HTTP 通信機能自体は同期通信にも非同期通信にも対応してお り、受信するデータ形式も XML とプレーンテキストの両方を選べるため、プレーンテキス トを同期通信する従来型の Web アプリケーションをページ遷移を伴わずに実現するといっ た使い方もできる。 ●Ajax を使った Web サービスと使わないものとの違い 地図サイトを例に取ると、昔の地図サービスサイトは、目的地点に移動するときに、いち いち表示する地図をすべて作成し、表示をしなければならなかった。そのため、場所を移 動するたびに、ウィンドウをリロードし、表示に時間がかかった。しかし、Ajax を使った 7 地図サイトでは、カーソルで見たい場所をグリグリと移動できます。読み込みの時間も少 なく、直感的に操作ができて快適になる では、Ajax を使ったサービスとそうでないサービスはなぜこのような違いがでてくるのか。 Ajax を使っていない、いままでの地図サイトでは、見たい場所の地図の位置をクライアン トからサーバに送信する。サーバ側で画像を生成し、クライアント側にデータを送信する。 (図3-1 Ajax を使っていない地図サイトの動き) 8 一方、Ajax を使った地図サイトでは、Ajax がマウスの動きを検知し、現在表示されてい ない地図のデータ部分を計算し、足りない部分をサーバにリクエストする。サーバ側から は足りない地図データをクライアントに送信する。データは足りない部分を受け取り、補 正して表示する。 (図3-2 Ajax を使った地図サイトの動き) 初期の Ajax は、 「Google マップのようにグリグリと操作ができる」というイメージで広ま 9 った。この足りない部分だけのデータを送信して、現在あるデータをうまく使い、今のよ うな操作を可能にした。必要な部分だけを受信する方法は、この操作感だけでなく、サー バとのやりとりをするデータも必要最小限なため、サーバや回線に負担を掛けない。 3-1-2 Ajax のメリット・デメリット Ajax のメリット・デメリットは以下のように挙げられる。 ● メリット 1.クライアントは Web ブラウザだけでいい。プラグインなどは不要 2.ユーザーの操作に動的に反応する画面書き換え 3.サーバとの通信待ちがないスムーズな動作 Ajax を利用することで、クライアント/サーバ形式のアプリケーションが持つ高い柔軟性 と、Web アプリケーションが持つ運用コストの低さやメンテナンス性の高さを両立できる。 さらに付け加えるならば JavaScript は標準技術であり、特定ベンダの思惑に左右されにく い。これらが Ajax が注目されている大きな理由であり、これからの情報システムを構築す るテクノロジの条件を備えているといえる。 ● デメリット 1.サーバとブラウザの機能の切り分けの難しさ 2.JavaScript との交換性 3.セキュリティの問題 まず、開発者にとっては新しい考え方なので技術の理解が必要である。また、サーバとブ ラウザの双方にプログラムを記述するため、どうしても見通しの悪いプログラムになって しまう。さらに、高機能を求めて大量の JavaScript を 1 つのページに書き込むことによっ て最初のページ読み込みが遅くなる可能性がある。サーバとブラウザの機能の切り分けは 難しそうだ。 また、Ajax の中心的な役割を果たしている JavaScript には以前から互換性やセキュリテ ィの問題が指摘されている。JavaScript の互換性の問題のために、ウェブアプリケーショ ンが特定のブラウザでしか動作しない、ということはよくあることだ。 Ajax では JavaScript の占める割合が高まるため、より注意しながら開発する必要がある。 セキュリティには新しい問題がある。従来であればアドレスバーを見ればどこのサーバに 10 アクセスしているのかわかったが、Ajax ではバックグラウンドで通信しているサーバがど このサーバなのかわかりにくい。もしかすると悪意のあるサーバと交信するようプログラ ムされているかもしれない。この問題に対しては、(セキュリティ対策の基本だが)怪しいサ イトにはアクセスしない、重要な情報を書き込まない、という意識をユーザーが持つしか ない。 Ajax は新しい概念である。利点も欠点もあるが、応用方法はアイディア次第だ。成熟しき ってしまったかと思われたウェブアプリケーションにもまだまだ進歩の余地がありそうだ。 普通のアプリケーションと同等以上の操作感を持ったウェブアプリケーションの登場もそ う遠くはないだろう。 3-2 Web API について 3-2-1 Web API とは Web API とは、Web サイトなどの開発を効率的に行うための技術である。API は 「application programming interface」の略で、アプリケーションの開発者が、他のハー ドウエアやソフトウェアの提供している機能を利用するための手法である。例えば Windows などの OS は、アプリケーション向けに、ウインドウの描画などのよく使う機能 を API として提供している。 API を使えば、プログラムを開発する際の手間を省ける。開発者は OS などの提供者が定 めた手続きに従って、必要な機能の API を呼び出すようプログラミングすればよい。する と、自分で「ウインドウを描画する」などのコードを書かなくても、その機能を利用した プログラムを作成できる。 Web API は、Web サイトなどの開発のために、インターネット経由で利用できる API で ある。開発者にとっては、Web サイトなどの高機能なコンテンツを、より短期間・低コス トで開発できるという利点がある。 例えば多くのサイト運営者は、自分のサイトの機能や見栄えを良くしたいと考えるであろ う。しかし、個人や小さな企業では、開発できる機能に限界がある。Web API を利用すれ ば、 「開発者が自分一人では作れないデータベースや機能を利用した開発が可能となる」 (ヤ フー担当者) 。大規模な検索エンジン、地図のデータベース、言語の解析など、片手間では 開発できない機能を Web API を通じて取り入れられるわけだ。 11 Web API 以前にも、ネットワーク越しに他のソフトウエアの機能を使う方法は存在してい た。ただし、こうした技術は独自のプロトコルを使っていたため、Web アクセスで使う HTTP の通信しか許可しないファイアウオールを超えられず、インターネット経由で利用 するのが難しかった。 Web API では、API を公開する側と利用する側で命令やデータをやりとりする技術とし て、「SOAP」や「REST」と呼ばれる技術を使う。これらは、HTTP などのプロトコルを 使って、XML 形式のデータをやりとりするためのしくみである。こうしたインターネット の標準的な技術を使うため、開発や利用に特定の環境を要求しないという柔軟性が Web API の特徴の一つだ。 ● Web API の一覧 ・Google Web APIs ・Yahoo! Web サービス ・Amazon Web サービス ・はてな Web サービス ・ビッダーズ Web サービス ・お天気 Web サービス ・じゃらん Web サービス ・スマッチ Web サービス ・価格。com Web サービス ・カーセンサー・ラボ Web サービス ・お仕事検索 web サービス ・Flickr Services ・ホットペッパーWeb サービス ・Web ad Fortune 無料 API ・Wikipedia API ・YouTube API ・楽天ウェブサービス ・ケンコーコムウェブサービス ・HTML2PDF Web サービス API ・SAGOOL WEB API ・テクノラティブログ検索 API ・kizapi(きざっぴ) ・ぐるなび Web サービス ・リクルート WEB サービス ・@nifty Web Service (図3-3 Web API 一覧) Web API が提供する機能として数多いのが、企業の持つデータベースを公開するという ものである。例えば米 Google の「Google Maps API」では、同社の地図データベース「Google Maps」の情報を別の Web サイトに取り込んで表示したり、地図上に目印を付けたりする ことが可能だ。米 Amazon の「Amazon E-Commerce Service」ように、商品データを参照 できるデータベースもある。 12 データベースだけでなく、プログラムの機能を提供するタイプの Web API も提供されてい る。例えばヤフーの「日本語形態素解析 Web サービス」では、日本語の文章を区切ったり、 読み仮名を付けたりできる。 ●企業が無償で Web API を公開する理由 Web API の公開は 2002 年ごろ、Google や Amazon などの先進的なインターネット関連 企業によって始まった。今では多くの企業や個人が Web API を公開しており、しかもその 大半は無償で使うことが可能である。 なぜ企業は無償で Web API を公開するのであろうか。一つは、 「Web API を公開すること で、より優れたサービスが生まれる可能性が高いためである。Google の技術を使って Google 以外の人たちが考えてくれることで、Google だけでは思いつかなかったようなユニ ークなサービスが出てくる可能性がある」(Google 担当者)という狙いがあるようだ。 Web API を利用してもらうことで、間接的にせよ自社のサービスのユーザーが増えること も期待できる。複数の企業や個人が公開している Web API を組み合わせる開発手法を「マ ッシュアップ」と呼ぶ。Web API を公開する企業が増えれば、マッシュアップによってこ れまでなかった便利なサービスが次々と登場してくると期待できる。 3-2-2 マッシュアップとは マッシュアップとは、IT 用語としては、複数の異なる提供元の技術やコンテンツを複合さ せて新しいサービスを形作ることである。複数の API を組み合わせて形成された、あたか もひとつの Web サービスであるかのような機能が、マッシュアップと呼ばれている。 マッシュアップは、 「Web 2。0」の潮流とともに非常に盛んになった。その背景としては、 Amazon。com、Google、Flickr、YouTube といった、いわゆる Web 2。0 企業が、自社の Web サービスの機能を API として無償で提供する事例が増えたという点を挙げることがで きる。それに伴い、API を利用して複合的な機能を持った Web サービスを開発することが 可能となり、Web の可能性が広がった、というわけである。マッシュアップで構成された サービスは、腕試し的に作成されたものもあれば、商用のサービスとして本格的に運営さ れているものもある。 13 (図3-4 情報がばらばらだとユーザーを引き付けられない) (図3-5 そこで多数のサイトの情報をまとめ上げて提供しようというのがマッシュア ップである) マッシュアップとして生み出される Web サービスの内容は様々で、地図の表示と郵便番号 データを対応させるものから、あるキーワードについて議論しているブログとショッピン グサイトの関連製品を同時に表示させるものまで様々である。ユニークなものでは、自分 や他人がファーストキスをした記念の場所とエピソードを登録・閲覧することのできるサ 14 ービスや、地図情報と連動させてお店や観光地の口コミを投稿するサービスなどがある。 なお、マッシュアップ用の API として代表的なものとしては、Google Maps の地図情報な どを挙げることができる。 3-3 Smarty について PHP で web プログラミングを行う際、PHP のプログラムの中に HTML のコードを混在 させて記述する。そのため、ページのデザインを変更する際に、HTML だけでなく、PHP のコードを書き換えるなければならない場合があり、PHP のプログラムの保守性を低下さ せる原因となっている。Smarty を用いると、PHP のロジックと HTML のデザインの簡単 に分離することができる。 3-3-1 Smarty とは Smarty は、PHP プログラムのテンプレートエンジンである。Smarty によって、PHP プ ログラミングにおけるページのデザインと、ロジックのコーディングを分離することがで きる。 ●仕組み Smarty を用いるにあたって、まず、PHP のプログラムファイルと、ページデザインテン プレートファイルを用意する。テンプレートファイルには Fig。2 に示したように、 {$first_name}のようにして、PHP のプログラムで用いる変数を動的に受け取る箇所を指 定する。ブラウザから PHP のプログラムにアクセスすると、テンプレートエンジンが、テ ンプレートファイルの指定された箇所にデータを挿入し、ブラウザに表示する。このよう にすることで、ページのデザインを変更する際には、テンプレートファイルを、ロジック を変更する際には、プログラムを修整するだけでよいことがわかる。 3-3-2 Smarty の優位性 PHP で用いることができるテンプレートエンジンは、Smarty 以外にもいくつか存在する が、以下の点で Smarty は優れている。 ● 処理パフォーマンスが高速 Smarty は初回の実行時にテンプレートをテンプレートエンジンによってコンパイル処理 15 し、コンパイル後のコードを 1 次ディレクトリに保存する。これにより 2 回目以降の処理 では、通常の PHP スクリプトを実行するのと同等のパフォーマンスを実現できるほか、コ ンパイル処理は、テンプレートファイルが更新されたタイミングで自動的に実行されるた め、開発者がコンパイル作業を意識する必要がないという特徴がある。 ● 関数や修飾子、ライブラリが豊富 Smarty には、テンプレート上で、簡単なループ処理や、条件分岐などを実現する関数や、 出力するデータを修飾するための修飾子、また、テンプレートそのものを制御するための ライブラリが豊富に含まれている。これらを駆使することにより、柔軟なテンプレートを 構築できる。 ● 管理機能の充実 リソースの管理、設定ファイル、セキュリティレベルの制御、専用のででデバッキングコ ンソールなど、開発に役立つさまざまな機能が標準で提供されている。 16 4.システムの概要と主な機能 本システムであるグルメブログとは、Google map とリクルート Web サービスを組み合わ せるものである。リクルート Web サービスの1つにホットペッパーの情報を検索するサー ビスがあり、これを利用してさまざまな飲食店の情報をえることができる。 そして本システムは自分が行った店の情報をブログのように記事にするシステムであり、 記事を書く際にはリクルート Web サービスを使って店の情報を検索することができ、その 情報もブログに表示できるようにする。また検索した情報には店の場所も含まれるので、 それをもとにして Google map の地図も表示できるようにする。 (画面4-1 全体の構成図) 本システムには主に 8 つの機能がある。 1.管理ページのログイン機能 2.記事の編集や保存 3.画像のアップロード 4.カテゴリーの操作 5.グルメブログのページ表示 6.API を利用した機能 7.店の検索と表示 8.Ajax を使った情報の表示 17 4-1 ログイン機能 本システムでは管理ページはロ グインして利用する。 ① ユーザー名に「hiro」 ② パスワードに「hiro」 と入力しログイン (図 4-2 ログイン画面) --------------------------------------ログイン時のソースコードの一部-------------------------------------// ログイン処理 $options = array( 'users' => array($username => $password) ); $auth = new Auth('Array'、 $options、 'loginFunction'); $auth->setExpire(600); $auth->setIdle(600); if ($auth->checkAuth() && $_GET['mode'] == 'logout') { // ログアウト $auth->logout(); // 管理者モードをオフにする $_SESSION['admin_mode'] = 0; } $auth->start(); --------------------------------------ログイン時のソースコードの一部-------------------------------------- 18 ユーザー名もしくは パスワードが間違ってい たら右記のように表示さ れる。 (図4-3 ログインページ エラーメッセージ) ---------------------------------------エラー時のソースコード一部-----------------------------------// ログイン処理でエラーの場合と時間切れの場合 function loginFunction($user、 $status、 $auth) { global $smarty; switch ($status) { case AUTH_IDLED : case AUTH_EXPIRED : $smarty->assign('msg'、 '期限切れです。再度ログインしてください。'); break; case AUTH_WRONG_LOGIN : $smarty->assign('msg'、 'ユーザー名かパスワードが正しくありません。'); break; ---------------------------------------エラー時のソースコード一部------------------------------------ 19 4-2 記事の編集や保存 ブログシステムの中で最も重要な部分の一つであり、まずその処理に関するテンプレート から論じていく。 4-2-1 プラグイン 本システムでは、テンプレートを極力シンプルにするために Smarty を使用し、プラグイ ンをいくつか作る。 (画面 4-4 記事の作成画面) ●ブログ記事の一覧を出力する ブログでは多数の記事を扱うため、さまざまなかたちで記事を出力する機会がある。そこ で記事の出力を「entries」というプラグインで行うようにする。 --------------------------------------------------eintries 関数-----------------------------------------------{* 記事がない場合など 開始 *} {if $no_entry} <p>記事がありません</p> {/if} {if $db_error} <p>データベースからデータを読み込むのに失敗しました。</p> {/if} {* 記事がない場合など 終了 *} --------------------------------------------------eintries 関数------------------------------------------------ 20 ●多数の記事をページに分けて出力する 本システムでは多くの記事を管理することが出来るが、1 ページに多くの記事を表示する とページが縦に長くなり、また表示に時間がかかるようになる。そこで多数の記事がある 場合は一定条件ごとに区切って出力するようにし、そのために「entry_page_navi_setup」 というプラグインを作る。 ◆entry_page_navi_setup 関数の書き方 {entry_page_navi_setup per_page=1 ページの件数} 4-2-2 記事作成の流れ 画面① トップページ画面から記事の新規作成をクリック (画面4-5 トップページ) 画面② タイトル、本文、追記を入力 (画面4-6 記事作成画面) 21 画面③ 日付は自動的に入力されるが変えたい場合は入力しなおす (画面4-7 日付入力) 画面④:カテゴリーを作成しておくと、「カテゴリー」の欄でカテゴリーを選ぶことが可能 (画面4-8 カテゴリー分類) 画面⑤:ホットペッパーの情報を載せたい場合は店の ID で「検索」をクリック (画面4-9 検索) 画面⑥:本文、追記の欄の上にある鎖のアイコンをクリックすると、他のページのリンク を入力することが可能 (画面4-10 鎖アイコンクリック) 22 画面⑦:本文、追記の欄の上にある山のアイコンをクリックすると、画像のタグを入力す ることが可能 (画面4-11 山アイコンクリック) 画面⑧:本文、追記内の改行を br タグに変換したい場合は「改行を br タグに変換」のチ ェックをオンにする (画面4-12 チェックをオンにする) 画面⑨:記事を公開する場合は「公開状態」の「公開」、下書きにする場合は「下書き」を オンにする (画面4-13 をオンにする) 下書きか公開のチェック 23 画面⑩:保存ボタンをクリック (4-14 保存ボタン) ●既存の記事の編集 メニューの「記事の一覧」をクリックすると、これまで書いた記事のタイトルが一覧表示 される。編集したい記事のタイトルをクリックすると、記事作成時と同じ画面が表示され、 記事の内容を編集することができる。 4-3 画像のアップロード 本システムでは、画像をアップロードして記事に貼り付けることもできる。 4-3-1 画像アップロードの処理 メニューで「画像のアップロード」を選ぶと、画像をアップロードすることができる。ア ップロードの処理は以下の段階で行われる。 ① ファイルの指定 ② 日付やタイトルの入力 ③ 保存 アップロードされたファイルは、 「images」フォルダに保存されます。このフォルダにサブ フォルダをつくり、そこにアップロードすることもできる。 ●以下によって日付やタイトルを入力するページが出力されます。 ------------------------------日付やタイトルを入力するテンプレート----------------------------------{assign var="page_title" value="画像のアップロード"} {include file='header.tpl'} 24 <h2 class="page_title">画像のアップロード</h2> {if $image_exist} <p class="exist">同名のファイルが既にアップロードされています。<br />このままアップ ロードすると、既存のファイルに上書きされます。</p> {/if} <form method="post" action="{$self}?mode=upload_end"> <input type="hidden" name="filename" value="{$image_filename}" /> <input type="hidden" name="filepath" value="{$image_filepath}"" /> <table> <col width="150"> <col width="400"> <tr> <td>画像</td> {image_calc_size calc_width=400 calc_height=300} <td><img src="{$image_url}" width="{$image_calc_width}" height="{$image_calc_height}" alt="アップロードされた画像" /></td> </tr> <tr> <td>ファイル名</td> <td>{$image_filename}</td> </tr> (途中省略) </table> <p><input type="submit" name="submit" value="アップロード" /></p> </form> {include file='footer.tpl'} ------------------------------日付やタイトルを入力するテンプレート----------------------------------●またアップロードが成功したか失敗か確かめる機能や既存のファイルと同じファイルが 再度アップロードされた場合新しいファイルで置換する機能も備わっている。 ---------------------------アップロード失敗チェックのソースコード--------------------------------- 25 <?php require_once('make_path.php'); // アップロードに失敗していれば、ファイルを指定するページに戻る $tmp_name = $_FILES['upfile']['tmp_name']; if (!$tmp_name) { header("Location: $self?mode=upload_start&upload_error=1"); exit(); } ---------------------------アップロード失敗チェックのソースコード--------------------------------- ---------------------------アップロード済みのチェックのソースコード--------------------------------// 指定されたパスにすでに画像ファイルがある場合 $filename = $_FILES['upfile']['name']; $filepath = $_POST['filepath']; $upload_to = makePath('images/' . $filepath, $filename); if (file_exists($upload_to)) { // ファイルが存在することを変数に設定する $smarty->assign('image_exist', 1); // 画像のデータをデータベースから読み込む $sql = <<< HERE select * from ${pfx}image where filename = ? HERE; $type = array('text'); $data = array($filename); // アップロード先が指定されているときは、その条件を追加する if ($filepath) { $sql .= "and filepath = ?"; array_push($type, 'text'); array_push($data, $filepath); } 26 // アップロード先が指定されていなければ、 // 「filepath フィールドの値が null」という条件を追加する else { $sql .= "and filepath is null"; } // SQL を実行してファイルの情報を得る $sth = $mdb2->prepare($sql, $type); $res = $sth->execute($data); $data = $res->fetchRow(); ---------------------------アップロード済みのチェックのソースコード--------------------------------- ●アップロードされるファイルはまず仮ディレクトリに移動される。そして実際にファイ ルを保存する処理を行っていく。 ① 仮ディレクトリに移動される ② フォームで入力された情報を得る ③ その画像がすでにアップロードされているかどうかを確認し、アップロードされていれ ば、そのことを表すために変数に1を代入して既存の画像を削除する ④ 指定された本ディレクトリに一時ファイルを移動する -------------------画像を実際のファイルに保存するまでのソースコード-------------------------// ファイルの情報を得る $date = $_POST['date']; $title = $_POST['title']; $description = $_POST['description']; $filename = $_POST['filename']; $filepath = $_POST['filepath']; $filepath = preg_replace('/(.*)¥/$/', '¥1', $filepath); // 指定されたパスにすでにファイルがあるかどうかをチェックする $upload_to = makePath('images/' . $filepath, $filename); if (file_exists($upload_to)) { $is_exist = 1; unlink($upload_to); 27 } // 一時ファイルを本ファイルに移動する $tmp_file = 'images/tmp/' . $filename; if (!rename($tmp_file, $upload_to)) { $smarty->assign('page_title', 'エラー'); $smarty->assign('errmsg', '画像の移動に失敗しました。'); $smarty->display('error.tpl'); exit(); } -------------------画像を実際のファイルに保存するまでのソースコード-------------------------●次にデータベースに保存する処理を行う。 -------------------画像のファイル情報をデータベースに保存する-------------------------// 画像の情報を得る $fileinfo = getimagesize($upload_to); $width = $fileinfo[0]; $height = $fileinfo[1]; // データベースにファイルの情報を保存する if ($is_exist) { // 既存のファイルがある場合 $sql = <<< HERE update ${pfx}image set date = ?, title = ?, description = ?, width = ?, height = ? where filename = ? HERE; $type = array('timestamp', 'text', 'text', 'integer', 'integer', 'text'); 28 $data = array($date, $title, $description, $width, $height, $filename); if ($filepath) { $sql .= "and filepath = ?"; array_push($type, 'text'); array_push($data, $filepath); } else { $sql .= "and filepath is null"; } } else { // 新規ファイルの場合 $sql = <<< HERE insert into ${pfx}image ( date, title, description, filename, filepath, width, height ) values ( ?, ?, ?, ?, ?, ?, ? ) HERE; $type = array('timestamp', 'text', 'text', 'text', 'text', 'integer', 'integer'); $data = array($date, $title, $description, $filename, $filepath, $width, $height); } // SQL を実行する $sth = $mdb2->prepare($sql, $type, MDB2_PREPARE_MANIP); $res = $sth->execute($data); if (PEAR::isError($res)) { $smarty->assign('page_title', 'エラー'); $smarty->assign('errmsg', '画像をデータベースに保存するのに失敗しました。'); $smarty->display('error.tpl'); exit(); } // 画像一覧のページへ移動する header("Location: $self?mode=edit_image_start"); ?> 29 -------------------画像のファイル情報をデータベースに保存する-------------------------4-3-2 画像の操作 ① メニューの「画像のアップロード」をクリック ② アップロードする画像のファイル名を選び、「アップロード」ボタンをクリックする。 また、必要に応じてアップロード先のディレクトリも指定する。 ③ 画像の日付、タイトル、説明を入力して、 「アップロード」ボタンをクリックする。 アップロードが終わると、これまでにアップロードした画像が一覧表示されます。なお、 アップロード先のディレクトリを指定する場合は、あらかじめそのディレクトリをサーバ につくり、パーミッションを設定してファイルを保存できるようにしておく必要がありま す。 (画面4-16 画像のアップロード) (画面4-15 トップ画面) (画面4-17 アップロードされた画 像) 30 (画面4-18 タイト ル説明記入) (画面4-19 アップロード一覧) ●画像の情報の編集 メニューの「画像の情報の編集」をクリックすると、既存の画像が一覧表示されます。そ こから画像を選んで「画像の情報を編集」ボタンをクリックすると、画像の日付・タイト ル・説明を編集することができる。また「画像の削除」ボタンをクリックすると、その画 像を削除する。 31 (画面4-20 トップ画面) (画面4-21 編集ボタンクリック) (画面4-22 削除ボタンクリック) 4-4 カテゴリーの操作 カテゴリーを作成しておくと、記事を分類することができる。メニューの「カテゴリーの 新規作成」をクリックするとカテゴリーを作成するページが表示される。そこでカテゴリ ーの名前・概要・並び順を入力して「保存」ボタンをクリックすると、カテゴリーを保存 32 することができる。またメニューの「カテゴリーの一覧」をクリックすると、保存済みの カテゴリーが一覧表示される。そこでカテゴリーの名前をクリックすると、そのカテゴリ ーの名前・概要を編集でき、「削除」ボタンをクリックすると、そのカテゴリーが削除され る。 4-5 グルメブログの画面表示 まずはグルメブログのソースコードからみていく。 ------------------------------------グルメブログのソースコード-----------------------------------------<?php require_once('lib/set_path.php'); // セッションを開始する ini_set('session.use_only_cookies', 1); session_start(); // ライブラリの組み込み set_include_path('admin' . PATH_SEPARATOR . 'lib' . PATH_SEPARATOR . $pear_path . PATH_SEPARATOR . get_include_path()); require_once('Auth/Auth.php'); require_once('MDB2.php'); // Smarty オブジェクトの作成 require_once('initialize.php'); require_once(SMARTY_DIR . 'Smarty.class.php'); $smarty = new Smarty(); initialize(); $smarty->template_dir = './templates/blog'; $smarty->compile_dir = './templates_c/blog'; // データベースに接続 require_once('init_db.php'); 33 $mdb2 = initDB($dbuser, $dbpass, $dbhost, $database); if (PEAR::isError($mdb2)) { $smarty->assign('page_title', 'データベース接続エラー'); $smarty->assign('errmsg', 'データベースに接続することができませんでした。'); $smarty->display('error.tpl'); exit(); } $smarty->assign('mdb2', $mdb2); // 管理ページのファイル名 $self = 'index.php'; $smarty->assign('self', $self); // URL のパラメータを得る $category_id = intval($_GET['cat_id']); $year = intval($_GET['year']); $month = intval($_GET['month']); $entry_id = intval($_GET['id']); $is_image = intval($_GET['image']); $is_shop_detail = intval($_GET['shop_detail']); // 画像表示の場合 if ($is_image) { $smarty->assign('is_image', 1); $tmpl = 'image.tpl'; } // 店の詳細表示 elseif ($is_shop_detail) { $smarty->assign('is_shop_detail', 1); $smarty->assign('search_shop_id', $_GET['shop_id']); $smarty->caching = 2; $smarty->cache_dir = "./cache/blog"; $smarty->cache_lifetime = 86400; header('Content-Type: text/javascript; charset=UTF-8'); 34 $tmpl = 'shop_detail.tpl'; } // 記事表示の場合 else { // カテゴリーが指定されている場合 if ($category_id) { $smarty->assign('view_cat_id', $category_id); $smarty->assign('is_category', 1); $smarty->assign('url_query', "cat_id=$category_id"); } // 年月が指定されている場合 if ($year && $month) { $smarty->assign('view_year', $year); $smarty->assign('view_month', $month); $smarty->assign('is_monthly', 1); $smarty->assign('url_query', "year=$view_year&month=$view_month"); } // 記事の ID が指定されている場合 if ($entry_id) { $smarty->assign('view_entry_id', $entry_id); $smarty->assign('is_entry', 1); } // 条件が指定されていない場合 else { $smarty->assign('is_main', 1); } $tmpl = 'entry.tpl'; } // 現在の年を変数に設定 $smarty->assign('cur_year', date('Y')); // ページを表示する if ($is_shop_detail) { $smarty->display($tmpl, $_GET['shop_id']); } else { $smarty->display($tmpl); 35 } ?> ------------------------------------グルメブログのソースコード------------------------------------------ そして下記がトップページである。 ①記事が記載されてあ れば画面中央にブログ 記事が表示される。 ②右側にアップロード された画像が表示され る (画面4-23 ユーザートップ画面1) ③ 最新の記事が題名ご とで表示される ④ カテゴリーごとで表 示され、イタリアン をクリックすればイ タリアンのカテゴリ ーで表示される。 ⑤ 月ごとでブログの記 事がわけられる。 (画面4-24 ユーザートップ画面2) 36 4-6 API を利用した機能 本システムでは API を利用した機能が 2 つある。それは Google Map とリクルート Web サービスのホットペッパーである。これらでホットペッパーの情報を検索して表示させた り、Google Map からお店の地図を表示することが可能になる。 まずこれらの API を利用するにはいずれもユーザー登録して「API キー」と呼ばれるコー ドを取得する必要がある。その手順は下記の通りである。 ● リクルート Web サービスの API キーの取得手順 ① リクルート Web サービスのトップページに接続する。 ② ページ左上の新規登録ボタンをクリックする。 ③ ユーザー登録のページが表示される。 ④ 「上記の規約・個人情報取り扱いに同意する」のチェックをオンにし、自分のメールア ドレスを入力して送信する。 ⑤ 仮登録のメールが送られてくるので、その指示に従って本登録を行う。 (画面4‐25 記事とともにリクルート Web サービスから得た情報が表示される) 37 ● Google Map の API キー取得手順 ① Google Map の API キーに登録するページに接続する。 ② ページを一番したまでスクロールし「利用規約を読んだ上でこれに同意します」のチェ ックをオンにする。 ③ 「My web site URL」の欄に自分のサイトの URL を入力する。 ④ 「Generate API Key」のボタンをクリックする。 ⑤ ページが切り替わり API キーが表示される。 (画面4-26 4-7 Google Map の API キー取得) 店の検索と表示 4-7-1基本的な利用方法 グルメブログのシステムではホットペッパーの API を利用して飲食店のデータを検索する。 検索結果は XML 形式で返される。 -----------------------------------検索結果の XML の形式------------------------------------------<?xml version="1.0" encoding="UTF-8" ?> <results xmlns="http://webservice.recruit.co.jp/hotpepper/"> <api_virsion>API バージョン</api_virsion> <results_abailable>見つかった店の数</results_abailable> <results_returned>検索結果として返された店の数</results_returned> <results_start>先頭の店の番号</results_start> <shop> 38 <id></id> <name></name> ・ ・(店一件分の様々なデータ) ・ </shop> <shop> ・ ・(店一件分の様々なデータ) ・ </shop> 途中省略 ・ ・ ・ </results> -----------------------------------検索結果の XML の形式------------------------------------------みつかった個々の店の情報は<shop>と</shop>のタグで囲まれ出力される。また店の様々 な情報もそれぞれタグで囲まれて出力される。 4-7-2 検索の仕方 下記のような流れで検索する。 画面① 記事の新規作成の中にある検索ボタンをクリック (画面4-27 検索ボタンクリック) 画面② 店名がわかっていれば①に入力し住所がわかっていれば②に入力、キーワードで 検索したい場合は③に入力。 39 (4-28 検索画面1) 画面③ エリアごとで検索したい場合はエリアの項目を選択 (4-29 検索画面2) ④ ③と同様にジャンル・料理で検索したい場合は項目を選択 検索でのソースコードは以下の通りである。 40 -----------------------------------グルメサーチのソースコード--------------------------------------<?php require_once('HTTP/Client.php'); require_once('XML/Unserializer.php'); // キャッシュの設定 $smarty->caching = 2; $smarty->cache_dir = './cache/admin'; $smarty->cache_lifetime = 30; if (!$smarty->is_cached('search_shop.tpl')) { // HTTP_Client と XML_Unseriazlier のオブジェクトを初期化する $client =& new HTTP_Client(); $xml = new XML_Unserializer(); $xml->setOption('complexType', 'array'); $recruit = $smarty->get_template_vars('recruit'); $types = array('large_area', 'genre', 'food'); foreach ($types as $type) { // リクルート Web サービスにアクセスする $data = array(); $query = "http://webservice.recruit.co.jp/hotpepper/${type}/v1/"; $query .= "?key=${recruit}"; $client->get($query); $resp =& $client->currentResponse(); if ($resp['code'] != 200) { $smarty->assign('page_title', 'エラー'); $smarty->assign('errmsg', 'リクルート Web サービスに接続することができ ませんでした。'); $smarty->display('error.tpl'); exit(); } // XML を連想配列に変換する $xml->setOption('forceEnum', array($type)); $result = $xml->unserialize($resp['body'], FALSE); $xmldata = $xml->getUnserializedData(); 41 // フォームの select に出力するデータを生成する $select = array('0' => '↓選択してください'); foreach ($xmldata[$type] as $data) { $select[$data['code']] = $data['name']; } $smarty->assign($type, $select); } } // 検索フォームを表示する $smarty->display('search_shop.tpl'); ?> -----------------------------------グルメサーチのソースコード--------------------------------------4-8 Ajax を使った情報の表示 4-8-1 時間がかかる処理を Ajax で行う 本システムでは記事を書くときに、記事で紹介する店の ID を登録することができる。そ して、その ID をもとにグルメサーチ API で店の情報を得て、ここの記事のページに情報を 表示させることができる。 記事のページを出力する処理は下記のような手順で行うことが考えられる。ただグルメサ ーチ API を実行して情報が返ってくるまでには、通信や検索の時間がかかる。そおためこ の手順では、ページがブラウザに表示されるまでに若干タイムラグが生じる。 ◆Web ブラウザ ◆Web サーバ(グルメブログ) 記事のページにアクセス データベースから 記事のデータを読み込む グルメサーチ API で 店のデータを読み込む ページを受信して データとテンプレートを元 表示する にしてページを出力する (図4-30 全ての処理が終わってからページを出力する) 42 このように、外部のサーバと通信してデータをえて、それを Web ページに表示させる場合 は、通信や検索によるタイムラグがおこりやすくなる。特に夜間など、外部のサーバへの アクセスが集中する時間帯は検索処理に時間がかかり、ページがなかなか表示されないこ とが多々起こる。下記のような手順で記事部分と店の情報の部分とを分けて表示する方法 が考えられる。 ◆Web ブラウザ ◆Web サーバ(グルメブログ) 記事のページにアクセス データベースから 記事のデータを読み込む ページの記事部分を データとテンプレート 受信して表示する をもとにしてページの 記事部分を出力する Ajax で Web サーバ グルメサーチ API で アクセス 店のデータを読み込む 店の情報部分を データとテンプレート 受信して表示する をもとにしてページの 店の情報の部分を出力する (図4-32 店の情報を Ajax で表示する) これなら、まず記事の部分が一通り表示され、その後に店の情報が表示されるので、待た されたという印象を与えにくくなる。 4-8-2 グルメブログでの Ajax の処理 Ajax では、サーバと通信した結果としてテキストデータ(HTML や XML など)を受信 することができる。本システムでは「JSON」という形式のテキストデータを受信する。 JSON とは「JavaScript Object Notation」の略で、PHP の連想配列とよく似たもの。 ま ず ブ ロ グ 表 示 ス ク リ プ ト に 処 理 ( index.php ) を 追 加 し 、 URL に 「?shop_detail=1&shop_id=店の ID」が付加されていた場合に店の詳細情報を出力する処 理をいれる。 43 ---------------------------------------index.php の変更------------------------------------- ---------------------------------------index.php の変更------------------------------------(1)URL のチェック・・・① この文で URL に「?shop_detail=1」が付加されているかを調べ、それを変数$is_shop_detail に代入する。そして、その条件がみたされていれば②が実行され出力される。 (2)キャッシュ設定・・・②-A っこの処理ではグルメサーチ API にアクセスして情報を得るが、それには若干時間がかか る。そこでページをキャッシュして、グルメサーチ API へのアクセスは、前回から 24 時間 以上経過するまで行わないようにする。 (3)HTTP ヘッダーの送信・・・②-B Header 関数を使って「Content-Type」の HTTP ヘッダーを送信し、送信内容が JavaScript のデータであることを Web ブラウザに送信する。同時に、文字コードが UTF-8 であるこ とも送信する。 (4)店の ID ごとにキャッシュする 44 さらにページをキャッシュするために、display メソッドを呼び出す箇所も書き換える。 ID に応じた店の情報を出力する。そのため、ID ごとにキャッシュを行う必要がある。この ように URL のおパラメータなどによって、同じテンプレートでも違うキャッシュを使う音 が必要になる場合があり、そのときは display メソッドの 2 つ目のパラメータとして、ここ のページを識別するために値を渡す。 店ごとのページを出力する場合は店によって ID が異なるので、それを使って各ページを識 別することができる。そこで display メソッドの 2 つ目の因数として、店の ID を渡す。 (③) 記事ごとにページアクセスされたときは、Ajax を使って店の情報を表示する処理を行う。 ------------------------------entry.tpl 内の Ajax の処理を行う部分-------------------------------------{if $is_entry && $entry_shop_id} <div id="shop_detail">通信中です... <img src="ajax-loader.gif" alt="通信中" /></div> <script type="text/javascript"> {literal} //<![CDATA[ window.onload = function() { // Ajax で「index.php?shop_detail=1&shop_od=店の ID」にアクセスする new Ajax.Request('{/literal}{$self}{literal}?shop_detail=1&shop_id={/literal}{$entry_shop_id}{ literal}', { method : 'get', onSuccess : showShopDetail, onFailure : failure }); } // アクセスに成功したときの処理 function showShopDetail(resp) { // 読み込んだ JSON を JavaScript のオブジェクトに変換する var rData = eval('(' + resp.responseText + ')'); if (rData.error) { // 検索に失敗した場合 $('shop_detail').innerHTML = '<p>店の検索に失敗しました。</p>'; } else { 45 // 店の詳細を表示する $('shop_detail').innerHTML = rData.description; // Google Maps を表示する infoHtml = '<p><a href="' + rData.shopUrl + '">' + rData.shopName + '</a><br />' + rData.shopAddress + '</p>'; showGMap('gmap', rData.lat, rData.lng, 150, 150, infoHtml); } } function failure(resp) { $('shop_detail').innerHTML = '<p>サーバーとの通信に失敗しました。</p>'; } // {/literal} </script> {/if} ------------------------------entry.tpl 内の Ajax の処理を行う部分-------------------------------------- 4-9 データベースの構成 本システムでは、投稿した記事や画像の情報を保存するためや、記事をカテゴリーに分類 できるようにするためにカテゴリーの情報も保存できるようにデータベースを使う。また 個々の記事に店の ID を保存する機能もあるのでそのためのデータベースも必要である。記 事・画像・カテゴリーの 3 つのテーブルを使用する。 ● 記事テーブルの構造 記事のテーブルには、記事の各項目を保存するためのフィールドを作る。また個々の記事 を特定できるように連番のフィールドも作る。 記事の日付は、記事を時間順に並べ替えたりする際に必要な情報なので、NULL を受けつ けないようにする必要がある。一方、タイトル・本文・追記は空欄にすることもあるので NULL を受け付けないようにする。 46 (表4-32 記事のテーブル) ● 画像テーブルの構造 画像のテーブルでは個々の画像のタイトル・日付・概要・ファイル名・アップロード先デ ィレクトリ・幅・高さを保存するので、テーブル構造は下記のようになる。ここでは日付 とファイル名には NULL を受け付けないようにする。また、ID のフィールドは個々の画像 を識別するために使うので自動的に連番が振られるようにして、主キーも設定する。 (表4-33 画像のテーブルの構造) ● カテゴリーテーブルの構造 カテゴリーテーブルでは、ID・名前・概要・並び順の 4 つの情報を保存する。カテゴリー 名は必ず指定すべきなものなので、NULL を受け付けないようにする。また ID のフィール ドは個々のカテゴリーを識別するために使うので自動的に連番が振られるようにし、主キ ーも設定する。 47 (表4-34 カテゴリーのテーブル構造) 48 5.開発環境 本システムでは XAMPP 開発環境を整えるソフトウェアーを使用している。 5-1 XAMPP とは PHP やMySQLを動作させて Web アプリケーションを作る場合は、Web サーバソフト の Apache など、PHP や MySQL 以外に用意すべきものがある。それらをすべてインスト ールして動作するように設定を行うのは、手間のかかる作業だ。 そのような煩雑な作業を簡便化してくれるのが「XAMPP」で、Apache/PHP/MySQL な どの開発環境をまとめてインストールできるソフトウェアーである。XAMPP は非営利組織 の Apache Friends が開発したもので、Windows 版としては「XAMPP for Windows」が提 供されている。これを自分の Windows パソコンにインストールすれば、ローカルで PHP やMySQLを使った開発を行うことが出来る。 (画面5-1 5-2 XAMPP のコントロールパネル) PHP 動的に Web ページを生成する Web サーバの拡張機能の一つ。また、そこで使われるスク リプト言語。レイアウトの「雛形」となる HTML ファイル内に、処理内容を記述したスク 49 リプトを埋め込み、処理結果に応じて動的に文書を生成し、送出することができる。動的 に生成されるページの作成に向いている。また、XML のサポートや各種データベースとの 連携に優れている点などから近年普及しつつある。プログラムの表記法は C 言語、Java、 Perl の各言語から転用したものがベースとなっているが、PHP 独自のものもある。言語仕 様やプログラムはオープンソースソフトウェアとして無償で入手することができる。 5-3 MySQL TCX DataKonsultAB 社などが開発している、オープンソースのリレーショナルデータベ ース管理システム(RDBMS)。マルチユーザ、マルチスレッドで動作し、高速性と堅牢性に 定評がある。オープンソースなので基本的には無償で利用することができ、国内では有償 でサポートを提供する企業もある。 5-4 Apache Apache はフリーソフトウェアとして無償で公開され、世界中のボランティアのプログラ マたちの手によって長年に渡って開発が続けられている。もともと NCSA httpd の細かい バグを修正したり新しい機能を追加するためのパッチ(patch)集として公開されていたが、 途中から単体の Web サーバソフトとして公開された。 50 6.考察・今後の課題 今回のこの製作によってプログラミングをする技術・知識が高まった。しかしそれだけで は足りないということも感じた。それはクリエイティブな発想も必要だということだ。何 か新しいシステムはないのかということを考えたり、どのようにしたら多くの人に使いや すいようにできるのか考えることも重要なことだということを学んだ。 今後の課題としてはグルメブログを書いたとこから料理レシピを検索できるシステムを 作っていきたかった。しかし完成させることはできなかったので、このシステムを導入す ることを目指していく。 またブログ機能ではコメントを入力できないので、コメントを入力することができればよ り使いやすいものにもなると思うので、これも同時に導入していくことを目指す。 最後に 2 年間という短い時間でしたが、プログラミングについて何もわからなかった私を 手厚くご指導してくださった山本先生には誠に感謝しております。そして 2 年間支えてく れたゼミの仲間にも大変お世話になりました。ありがとうございました。 51 7.参考文献 ●書籍 ◇「改訂新版 基礎 PHP」 WINGS プロジェクト (著), 山田 祥寛 (著) インプレス社 ◇「作って覚える PHP+MySQL アプリケーション」 藤本 壱 (著) ソシム社 ●インターネット ◇IT 用語辞典 e-Words http://e-words.jp/ ◇初心者用 PHP 入門 http://www.standpower.com/ 52