SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

symfony入門

symfony入門(3):掲示板アプリケーション作成でsymfonyを理解しよう(後篇)

symfonyによる実践的なPHPアプリケーション開発


  • X ポスト
  • このエントリーをはてなブックマークに追加

掲示板投稿内容をチェックする:入力値検証

 ここまでで一通りの機能を備えた掲示板らしくなりましたが、あらゆる入力を許している状態です。しかしセキュリティのためにも、入力された値の検証は欠かせません。symfonyでは入力値検証のための設定もYAMLファイルで行うようになっています。

YAMLファイルによる入力値条件の設定:「validate/~.yml」

 特定のアクションにおける入力値検証設定は、モジュールフォルダ内の「validate/<アクション名>.yml」ファイルを作成することによって行われます。今回は入力された値が実際にデータベースに書き込まれるupdateアクションにおいて入力値検証を行うことになります。

update.ymlの作成

 validateフォルダ内に以下の内容の「update.yml」ファイルを作成します。下記のように、まず検証を行う入力方法(post、get、またはその両方)を指定し、次に各フィールドについて検証条件を設定します。

update.yml
# post, get双方の入力に対応する
methods: [post, get]

# 各フィールドの入力値条件を以下に記述する
fields:

  # フィールド名
  title:       

    # 必須項目であることを示す
    required:  

      # 入力されていない場合表示するメッセージ
      msg:   タイトルを入力してください。 

    # 使用するバリデーター。sfStringValidatorは文字列用
    sfStringValidator:  

      # 許容最小文字数。指定しなければ1文字
      min:        
 
      # 最小文字数より少ない場合表示するメッセージ
      min_error:  

      # 許容最大文字数。指定しなければバリデーター上無制限
      max:  50    

      # 最大文字数を超えた場合表示するメッセージ
      max_error:  タイトル文字数が多すぎます(50文字以内)。

  author:
    required:
      msg:   お名前を入力してください。
    sfStringValidator:
      min:
      min_error:
      max:        30
      max_error:  お名前の文字数が多すぎます(30文字以内)。
  mail:

    # emailアドレス用バリデーター
    sfEmailValidator: 

      # 適正なemailアドレスが表示されない場合表示するメッセージ
      email_error:  "適切なメールアドレスを入力してください
(例: name@domain.com)。" 
  url:

    # 正規表現用バリデーター
    sfRegexValidator: 

      # パターンマッチした場合には入力値は適正であるという指定
      match:  Yes 

      # 適性でない場合表示するメッセージ
      match_error:  "適切なホームページアドレスを入力してください
(例: http://example.com)。" 

      #マッチさせる正規表現
      pattern:      /^https?:\/\/\w+/i 
  body:
    required:
      msg:   本文を入力してください。
  passwd:
    required:
      msg:   削除用パスワードを入力してください。
    sfStringValidator:
      min:        5
      min_error:  削除用パスワードの文字数が少なすぎます。5文字~15
文字で入力してください。
      max:        15
      max_error:  削除用パスワードの文字数が多すぎます。5文字~15文
字で入力してください。

 各フィールド内に記述されているバリデーターは例えば以下のものが利用できますが、カスタマイズする(カスタムバリデーター)ことも可能です。カスタムバリデーターについては、次回以降で扱う予定です。

バリデーター
バリデーター内容パラメータパラメータの意味
sfStringValidator文字列を検証するmin:最小文字数
min_error:最小文字数より少ない時のエラーメッセージ
max:最大文字数
max_error:最大文字数より少ない時のエラーメッセージ
sfEmailValidatorEmailアドレスの妥当性を検証するemail_error:Emailアドレスが適切でないときのエラーメッセージ
sfRegexValidator正規表現を指定し検証を行うmatch:マッチした場合に適正と判断するならYes、不適正と判断するならNo
match_error:不適正な場合のエラーメッセージ
pattern:マッチさせる正規表現
sfCompareValidator2つの入力が同一かを検証する(パスワードを2カ所入力させ双方が一致するかなど)check:,比較対照となるフィールド
compare_error:同一でない場合のエラーメッセージ

handleErrorUpdate関数作成(actions.class.php内追記)

 もしここに記された入力条件に合わない入力があった場合、アクションクラス内のhandleError<アクション名>関数が呼び出されます。

actions.class.php(追記分:handleErrorUpdate)
public function handleErrorUpdate()
{
  $this->forward('bbsdata', 'create');
}

 この場合、再度入力してもらうべく、createアクションへフォワードしています。

テンプレートの修正

 入力値が適正でない場合は上記handleError関数でcreateアクションへ差し戻されますが、デフォルトではエラーとなった場合にそれがどのようなエラーなのか表示されず、またそれまで入力したフォームの内容は白紙に戻されてしまいます。symfonyには「/validate/~.yml」で設定したエラー内容を表示する関数が用意されているので、入力画面上にそれを表示するようにします。また、それまで入力された内容も保持されるよう、テンプレート「editSuccess.php」を書き換えます。

editSuccess.php
<?php
// auto-generated by sfPropelCrud
// date: 2006/12/07 00:14:58
?>
<?php use_helper('Object') ?>

// 入力値検証の結果が適性だったかどうか
<?php if ($sf_request->hasErrors()): ?>
  <p>投稿されたいずれかの項目が適切ではありません。
  下記のエラー内容を訂正し再投稿してください。
  </p>
  <ul>

  //生じたエラーを表示
  <?php foreach($sf_request->getErrors() as $error): ?>
    <li><?php echo $error ?></li>
  <?php endforeach ?>
  </ul>
  <br />
  <br />
<?php endif ?>

<?php echo form_tag('bbsdata/update') ?>

<?php echo object_input_hidden_tag($bbsdata, 'getId') ?>

<table>
  <tbody>

  <tr>
    <th>タイトル:</th>
    <td>
    <?php if ($sf_params->get('oya_title')): ?>
      <?php echo input_tag('title', 
                           'Re: '.$sf_params->get('oya_title'), 
                           array ('size' => 30,)) ?>

    //$sf_paramsでそれまで入力されていた内容を表示
    <?php else: ?>
      <?php echo input_tag('title', 
                           $sf_params->get('title'), 
                           array ('size' => 30,)) ?>
    <?php endif; ?>
    </td>
  </tr>
 :
 :
  <tr>
    <th>削除用パスワード:</th>
    <td>
      <?php echo input_tag('passwd', 
                           $sf_params->get('passwd'), 
                           array ('size' => 20,)) ?>
    </td>
  </tr>
  </tbody>
</table>
 :
 :

 $sf_requestショートカットで前回送られたリクエストについてのエラー情報を取得し、入力されていた内容の表示には$sf_paramsショートカットを用いています。今回用いた$sf_request$sf_paramsショートカットの関数は次のとおりです。

$sf_request/$sf_paramsショートカットで使用した関数
関数内容
$sf_request->hasErrors()エラーが生じれば真
$sf_request->getErrors()生じたすべてのエラー内容を配列で返す
$sf_params->get('<name>')'name'で送られてきたデータを返す

 実際には、次のようなエラー表示になります。

入力フォームで表示されるエラーメッセージ
入力フォームで表示されるエラーメッセージ

symfonyのセキュリティについて

 ここまでで、入力値検証を行うようになりました。しかしまだ、HTMLタグなどの入力に対しては無防備です。ですが、これに対し入力値を一つ一つ、htmlspecialcharsなどでエスケープする必要はありません(初回はビュー出力ではないため行いましたが)。「view.yml」内に以下を追記する事で、エスケープ処理は自動的に行われます。

view.yml(追記分)
escaping:
  strategy: both
  method: ESC_ENTITIES

 strategyの部分はエスケープ処理の対象を指定します。「both$sf_dataコンテナとローカルスコープ変数に適用)」「bc$sf_dataコンテナのみに適用)」「on(変数は$sf_dataコンテナからしか得られなくなる)」「off(エスケープ処理を行わない)」から選びます。

 methodの部分はエスケープ処理の方法を指定します。「ESC_RAW(エスケープ処理を行わない)」「ESC_ENTITIES(phpのhtmlentities関数を用いる)」「ESC_JS(HTMLとして使用されるであろうJavaScript文字列に埋め込まれる文字列をエスケープする)」「ESC_JS_NO_ENTITIES(JavaScript文字列に埋め込まれる文字列をエスケープするが、エンティティーは付加しない)」が選べます。

$sf_dataコンテナ
 $sf_dataコンテナとは、テンプレート内で変数を表示するためのコンテナです。例えば「$x」を表示する際に、
echo $sf_data['x']
echo $sf_data->get['x']
 といったやり方が可能で、ビューにおける変数のより安全なアクセスと取り回しを実現します。また一方でエスケープ処理されたら困る場合などに、
echo $sf_data->getRaw['x']
 とすることで何ら処理を行わずに表示することも可能です。例えば「layout.php」ではコンテンツ表示の際、
<?php echo $sf_data->getRaw('sf_content') ?>
 として、個々のビューで使われるタグをそのまま表示しています。

不要な要素の削除

 ここまで、入力値検証を含め基本機能を一通り実装してきましたが、今まで残しておいたshowアクション関連や書き込み以外の編集機能、レコードを直接削除するdeleteアクションは不要なので、ここで削除します。

ID表示部分のリンクをはずす

 scaffolding機能で自動生成したlistビューではID表示部分にshowアクションへのリンクが張られていましたが、これをはずします。

listSuccess.php(抜粋)
<td><?php echo $bbsdata->getId() ?></td>
 :
 :
<td><?php echo $reply->getId() ?></td>

editSuccess.php不要部分消去

 新規投稿や返信機能に使用する「editSuccess.php」ですが、既存レコードの編集には使用しない(つまり、Objectヘルパーも使用しない)ので、関連項目を削除します。

editSuccess.php(削除部分)
<?php use_helper('Object') ?>
<?php echo object_input_hidden_tag($bbsdata, 'getId') ?>
 :
 :
<?php if ($bbsdata->getId()): ?>
   <?php echo link_to('delete', 
                           'bbsdata/delete?id='.$bbsdata->getId(), 
                           'post=true&confirm=Are you sure?') ?>
   <?php echo link_to('cancel', 
                           'bbsdata/show?id='.$bbsdata->getId()) ?>
<?php else: ?>

  //この行のみ残す
   <?php echo link_to('cancel', 'bbsdata/list') ?>
<?php endif; ?>

投稿後リストへ直接接続(executeUpdate)

 scaffolding機能でのUpdateアクションはshowアクションにリダイレクトされますが、これをlistアクションへのリダイレクトに書き換えます。

変更前(actions.class.php executeUpdate内抜粋)
return $this->redirect('bbsdata/show?id='.$bbsdata->getId());
変更後(actions.class.php executeUpdate内抜粋)
return $this->redirect('bbsdata/list');

他、不要なアクション/ビューの削除

 仕上げに、showアクション/ビューとdeleteアクションを削除します。

  • 「executeShow()」削除
  • 「showSuccess.php」削除
  • 「executeDelete()」削除

次のページ
管理者用画面を用意する:ログイン画面とアドミンジェネレーター

修正履歴

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
symfony入門連載記事一覧

もっと読む

この記事の著者

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

WINGSプロジェクト 川北 季(カワキタ ミノル)

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト) Facebook

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/911 2007/03/09 10:08

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング