忍者ブログ

uthorofotus iruc

プログラムを組むために考えたり憶えたりした、いろいろなことを記録していきます。タイトルの読みは「ウソロフォトス イルーク」

[22]  [21]  [20]  [19]  [18]  [17]  [16]  [15]  [14]  [13]  [12

[PR]

×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

askeet day eight:AJAX interactions の解説

askeetチュートリアルの8日目『AJAXインタラクション』です。AJAXを付けることにより、よりWeb2.0らしいアプリケーションとなります。

8日目の日本語版はまだ無いようです。有志の翻訳状況はこちらです。本家英語版はこちらです。

■これまでのsymfony(Previously on symfony)
askeetのログインと質問に興味を示す(お気に入り)の機能にAJAXを付けます。

※質問に興味を示す(declare interest)ですが、言葉が長くて文章にすると読みづらいので、これからは原語を直訳した『興味宣言』を使います。

■レイアウトにインジケータを付ける(Add an indicator in the layout)
AJAXがサーバと通信している間、AJAX自体はそのことをユーザに通知する仕組みを持っていません。そのため、AJAXが通信しているという表示を開発者が用意する必要があります。全ページにAJAX用のインジケータを付けます。

まず、レイアウトテンプレートにインジケータの場所を指定します。divタグにstyle="display: none"が付いているところがポイントです。cssを見ると分かりますが、このdivの場所にインジケータ用gif画像が表示されます。普段はこれを隠しておき、AJAXが通信する時だけこの非表示指定を解除します。こうすることにより、ユーザにAJAXが通信状態にあることが分かるようになります。

cd web/images/
wget http://svn.askeet.com/tags/release_day_8/web/images/indicator.gif
cd ../../

■興味宣言にAJAXを付ける(Add an AJAX interaction to declare interest)
AJAXを実装するためには3つの作業があります。1つ目は呼び出し(Caller)で、ユーザがAJAXアクションを開始するためのボタンやリンクのことです。2つ目はサーバ処理、そして3つ目はAJAXの処理結果をユーザに見せるためのスペースです。

▽呼び出し(Caller)
4日目に興味を持った人数の部分をパーシャルで別部品(_interested_user.php)にしておいたのは、ここにAJAXを追加する予定があったからでした。新たにUserヘルパーを作成して、AJAXを呼び出すリンクを生成するヘルパー関数を定義します。興味宣言はログイン済みユーザしか実行出来ませんので、ユーザセッションのisAuthenticated関数を使ってログイン状態を確認しています。user/interestedがAJAXがアクセスするサーバ側の処理アクションです。

link_to_remoteヘルパー関数は、AJAX呼び出しの機能にあたります。実行するAJAXアクション先(link_toなどの設定と同じ形式です)、実行結果の反映先(どのidのhtmlタグへ)指定を引数に入れます。loadingとcompleteはprototypeのイベントハンドラの指定です。ここれでは、AJAX実行中(loading)には先ほど設置したインジケータを表示させています。AJAX処理が完了(complete)したらインジケータを隠し、指定したidのタグにハイライト効果をつけます。

AJAXを実行する際、AJAX効果の対象にはユニークなidを付ける必要があります。興味のdivタグに質問id使ってユニークなidを設定しておきます。

symfonyでAJAXを使う場合、prototype.jsなどのJavaScriptはすべて /sf/にあります。設定してない場合は1日目に戻って/sf/にアクセスできるようにしておきます。

▽結果スペース(Result zone)
link_to_remoteのupdate引数で指定したidのhtmlタグにAJAX処理結果が表示されます。さっきの定義では、結果を表示する"block_[質問id]"とハイライト処理される"mark_[質問id]"を指定されていましたので、_interested_user.phpと_list.phpにdivタグを使って定義しておきます。

▽サーバ処理(Server action)
AJAXで呼び出されるアクションuser/interestedを作ります。AJAXとは言っても、httpプロトコル上では普通にアクセスするのと同じですので、Userモジュールのactions.class.phpにexecuteInterestedメソッドを追加します。4日目にUserモデルのsaveメソッドで質問モデルのinterested_usersも更新するようになっています。

executeInterestedのテンプレートinterestedSuccess.phpが、結果データとしてAJAXに渡されます。その際、interested_blockのデータだけあればよく、レイアウト(httpヘッダやサイドバーなど)は不要です。modules/user/config/view.ymlで、レイアウトは使わないように設定をします。

▽最終テスト(Final test)
link_to_user_interestedヘルパー関数のおかげで、すでに興味宣言をした質問は"interested!"となって、宣言できないようになっています。

もし、以下のようなエラーが出たのならBaseInterestPeer.phpのretrieveByPkを確認してください。retrieveByPkの引数が間違っているというエラーです。正しい引数定義は retrieveByPK( $question_id, $user_id, $con = null) なのですが、retrieveByPK($pk, $con = null)となっている場合はスキーマの設定が上手く行っていません。

PHP Fatal error:  Call to a member function prepareStatement() on a non-object in /usr/share/php/symfony/vendor/propel/util/BasePeer.php on line 446

 ※以前に掲載したschema.ymlは、Interestのプライマリキーの指定が上手くできていませんでした。そのため、InterestPeer::retrieveByPkが上手く生成できず、link_to_user_interestedでエラーが発生してしまいます。Relevancyについても同じことをしていましたので、そちらも修正します。以下のようにschema.ymlを修正してください。

  ask_interest:
    _attributes:  { phpName: Interest }
    question_id:  { type: integer, primaryKey: true, foreignTable: ask_question, foreignReference: id }
    user_id:      { type: integer, primaryKey: true, foreignTable: ask_user, foreignReference: id }
    created_at:
  ask_relevancy:
    _attributes:  { phpName: Relevancy }
    answer_id:    { type: integer, primaryKey: true, foreignTable: ask_answer, foreignReference: id }
    user_id:      { type: integer, primaryKey: true, foreignTable: ask_user, foreignReference: id }
    score:        integer
    created_at:

primaryKeyの指定を追加したのですが、そうするとデータ型や外部キー設定を自動で補完してくれなくなりました。そこで、foreignTableとforeignReferenceも追加しました。

■組み込みログインフォームの追加(Add an inline 'sign-in' form)
ログインしていないユーザが興味宣言をしようとした際、今までの仕様だとログインフォームページに行ってしまいます。そうすると、どの質問に興味宣言をするのかが分からなくなってしまいます。そこで、ログインフォームをページ移動をせずに表示させます。

▽レイアウトへ隠しログインフォームの追加(Add a hidden login form to the layout)
<div id="content">の前にログインフォームを入れます。user/loginのフォームと違うところは、hiddenには今アクセスしているページのURLが入ることです。これは、ログインが成功したら同じページ表示を維持するために必要になります。

▽非ログインユーザのために興味宣言リンクにフォーム表示機能を付ける(Have the form appear when a non-authenticated user clicks an interested link)
UserHelper.phpで定義したlink_to_user_interestedヘルパー関数を修正します。今までは非ログインユーザはlink_toのリンクでしたが、link_to_functionというAJAXを実行するヘルパー関数に変更します。AJAXを実行すると、先ほどレイアウトに付けたid=loginのdivが持続時間0.5秒のビジュアル効果blind_downされつつ表示します。

▽ユーザのログイン(Login the user)
ログインフォームはAJAXでレイアウトにあるものを表示するようになりましたが、user/loginアクションは特に変更はしません。

非ログイン時に興味宣言のリンクinterested?を選択した場合、まずレイアウトに隠されたログインフォームが表示(コンテンツ部分がスライドをしながら)されます。そのログインフォームからログインができれば、user/loginアクションはリファラが持っている興味宣言のリンク先へリダイレクトします。そのまま興味宣言のアクションが実行されます。ユーザからみると以下のようにスムーズな流れになります。

  1. 興味宣言のリンクをクリック
  2. ログインフォームが出てくる
  3. ログインフォームに情報を入力して送信
  4. 興味宣言の実行結果がでてくる

■また明日(See you Tomorrow)
9日目に行く前に、課題が出されています。各回答に対して、良い(up)と悪い(down)の評価を投票するAJAX機能を付けるという物です。user/loginと同じ仕組みで作成します。
これから数日間のチュートリアルはAJAXの機能を追加していきます。

課題については、長くなりそうなので別記事で解説します。

PR

この記事にコメントする

お名前
タイトル
文字色
メールアドレス
URL
コメント
パスワード   Vodafone絵文字 i-mode絵文字 Ezweb絵文字

この記事へのトラックバック

この記事にトラックバックする:

askeet day eight:AJAX interactions の課題 HOME askeet day seven:model and view manipulation の解説

プロフィール

HN:
flyfront
性別:
非公開
自己紹介:
PHPプログラマ。東京でsymfonyな仕事してます。

HNはflyfrontですが、
仕事関係ではr_koike名義を使ってる場合もあります。

Wassr

カレンダー

05 2017/06 07
S M T W T F S
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30

最新コメント

[01/02 通りすがり]
[10/18 flyfront]

バーコード

アクセス解析

忍者ブログ [PR]
Template by repe