• []
  • []
  •  
  • del.icio.us 
  •  
  • Yahoo!֥åޡϿ 

symfonyでセッションを使う

PHP 求人 募集 Symfony CakePHP Smarty Ruby on Rails

symfony セッションの利用 概要

symfonyにはデフォルトでセッションをサポートしている。
デフォルトではPHPのセッションをそのまま利用しているが、
MySQLやPostgreSQLなどのデータベースを利用したセッションも可能だ。

今回はDBを利用したセッションは使わず。
PHPのセッションを利用したものを使う。

symfony セッションの利用 通常

セッションを利用すると言っても特別何もすることはない。
ただ単純にデータをセッションに格納すれば良いだけ。

{
  public function executeFirstPage()
  {
    $nickname = $this->getRequestParameter('nickname');
 
    // Store data in the user session
    $this->getUser()->setAttribute('nickname', $nickname);
  }
 
  public function executeSecondPage()
  {
    // Retrieve data from the user session with a default value
    $nickname = $this->getUser()->getAttribute('nickname', 'Anonymous Coward');
  }
}

symfony セッションを使って二重投稿を防止する

セッションの使い方の中にもう一つ重要なものがある。
それは二重投稿防止
入力ページ、または確認ページに一時的に発行したキーを表示しておき、
投稿を処理する段階でそのキーが一致しているかを確認し、
確認が終わった段階でそのキーを削除する。
これによりリロードなどにより多重ポストを排除することが出来る。

この機能で強化されたものがCaptcha。
一時的に発行したキー表示に解析しにくい画像を使うことによって
システムによる投稿を防止することが出来る。

captchaについては追々触れるとして、
今回は二重投稿を防止してみよう。

表示用のアクションとビューに以下のような記述を加える。
アクションaction.class.php

public function executeIndex()
{
  ・・・
  $this->setFlash('mymodule_index', md5(uniqid(time())) );
  ・・・
}

ビューindexSuccess.php

<div>
<?php use_helper('Validation') ?>
  <?= form_tag('mymodule/do') ?>
・・・
  <?= input_hidden_tag('uniqid', $sf_flash->get('mymodule_index')) ?>
・・・
  </form>
</div>

そして投稿処理用のアクションとに以下のような記述を加える。

public function executeDo()
{
  ・・・
 if( $this->getFlash('mymodule_index') !== $this->getRequestParameter("uniqid") ){
  $this->logMessage("二重投稿です");
  $this->forward404();
 }
 else{
  // 投稿格納処理
 } 
  ・・・
}

symfony セッションの利用 ハマリどころ

symfony テスト環境のセッション

テスト環境(SF_ENVIRONMENT=testまたはproject_test.php利用)の時、
通常のsfSessionStorageではなく、
テスト専用のセッションストレージsfSessionTestStorageというのが使われる。
このsfSessionTestStorageというのはどうやらまともにセッションの役割を果たさないようだ。
(なぜこうしているのかは不明。セッション名を変えるだけではダメなのだろうか。。。)

これを外すにはfactories.ymlの設定を変更する必要がある。 factories.yml

test:
    class: sfSessionStorage
    param:
      session_name: SYMFONYSESSID

symfony セッションデータの欠損

セッションの利用はsymfonyに限らず、
PHPで利用する上ではナーバスにならざるを得ない。
例えば、MySQLでのセーブハンドラを自前で実装したとして、
unknownエラーと戦うことになったり、
memcachedで実装したとして、
session_destory時の挙動と戦うことになったりする。

symfonyでもそれは起こるようだ。
symfonyでナーバスにならなければならない点はこれ。
shutdown_register_functionによる実装
デストラクタみたいなもの。
各クラスにはshutdownというメソッドが用意されていて、
shutdown_register_functionで割り当てている。 一見効率の良い実装法のようだが、
PHPは得てして一見良さそうなものはだいだい変な動作をする。

sfUser上のshutdownも挙動が怪しく、
たまに、データが保存されないことが発生する。 残念ながら、いつどのように起こるのか調査しきれていない。
なので如何に回避するかを考えておく必要がある。
実際は、発生してからの対処となるわけだが。

回避方法は$_SESSIONやsfStorageクラスを直に利用するか、
あるいはshutdownメソッドを明示的に利用する。
setAttributeを使用したアクションの一番最後に

 $this->getUser()->shutdown();

と記述をしインスタンスに載っている(つまりメモリ上)に載っかっているデータを明示的にストレージ(ファイル、またはDB)に格納させる。


framework/symfony/session.txt · 最終更新: 2007/06/28 01:27 by dozo