Jul 05, 2015
FuelPHP 勉強会 大須 vol. 1
水野 史土[email protected]
FuelPHP とは
● 軽量&シンプルなフレームワーク○ ファイル 756(5.1 MB)、含ドキュメント○ cf. CakePHP2.1.3 ファイル 1,356(8.8 MB)
● 最初から PHP5.3 前提● ルールが緩い● オープンソース
○ https://github.com/fuel○ 多くのユーザーがコミットしている
フォルダ構成
fuel 本体
app corepackages
public 公開部分
fuel/app フォルダ
コントローラ、モデルはclasses 配下
ビューは app/views を使う
作ってみたサイト
● FuelPHP クラス名検索○ http://fuel.php-web.net/○ FuelPHP のクラス名から、ソースコード閲覧○ PHP のリフレクション機能を活用○ Model は未使用
● 使用したソースコード○ https://github.com/twitter/bootstrap○ https://github.com/jquery○ https://github.com/pornel/PHPTAL○ https://github.com/kenjis/sample-contact-form/
http://fuel.php-web.net/ の構造
コントローラ
ビューPHPTAL
リフレクション(通常のアプリのモデル部分)
コントローラ
● fuel/app/classes/controller に置く
fuel/app/classes/controller/methodlist.php
class Controller_Methodlist extends Controller{
public function action_index(){…
コントローラのクラス
● Controller_(ファイル名) というクラス名○ (ファイル名) の先頭は大文字
● Controller を継承する
コントローラのメソッド名
● action_hoge メソッド○ URL/クラス名/hoge でアクセス可能○ URL/クラス名/ => action_index
● action_ をつけないメソッド○ ブラウザからは(たぶん)呼び出しできない
fuel.php-web.net では、
フォームを作るメソッド _form() $this->_form() で呼び出している
特殊なメソッド名
● before() ○ 他のメソッドの呼び出し前に実行
● after($response)○ 他のメソッドの呼び出し後に実行
fuel.php-web.net では未使用
URL とコントローラの対応
URL/methodlist/index↓
methodlist.php の action_index()
URL/methodlist/list/Arr↓
methodlist.php の action_list('Arr')
ルーティング
● fuel/app/config/routes.php で設定
_root_ トップページへアクセスした時
( http://fuel.php-web.net/ )
_404_ 見つからない時
(キャッチオール的に使える)
(404 レスポンス を指定する必要あり)
fuel/app/config/routes.php
return array('_root_' => 'methodlist/index', '_404_' => 'methodlist/404',
);
fuel.php-web.net にアクセス
↓fuel.php-web.net/index.php/methodlist/index
$view = View::forge('methodlist/index');
素のビューを使う場合は、View::forge(フォルダ/ファイル名)で指定する
ビューのファイルを指定する
$view = View::forge('methodlist/index');$view->set('title', 'クラス名検索');
$view->set(変数名, 値)
ビューに渡すデータ設定 方法1
$view = View::forge('methodlist/index');$view->title = 'クラス名検索';
$view->変数名 = 値
ビューに渡すデータ設定 方法2
$data['title'] = 'クラス名検索';return View::forge('methodlist/index',$data);
連想配列に格納 → View::forge に引数で渡す
ビューに渡すデータ設定 方法3
標準以外のビューを使う
TwigMustacheMarkdownDwooJadeHamlSmartyPhptal
app/config/config.php
'always_load' => array('packages' => array(
'parser', // ここを追加する
), ...
);
app/vendor にライブラリを設置する
ライブラリをダウンロードするapp/vendor 以下に置く
app/vendor/PHPTAL/PHPTAL.php
Mustache と markdown はデフォルトで入っている
PHPTAL のライセンス
FuelPHP : MIT
PHPTAL : LGPL
ライブラリは MIT とは限らない
PHPTAL を使う
● コントローラView::forge
↓View_Phptal::forge
config で設定できる?
PHPTAL を使う
● FuelPHP で使う場合○ 拡張子 .phptal (*)○ 明示的に指定すれば .html でも可
● ファイルは app/views フォルダに置く
* FuelPHP 以外では .html のこともある
PHPTAL の特徴 1
● テンプレートファイル(HTML) の属性に記述する
<h1 tal:content="title">title here</h1>↓
<h1>FuelPHPクラス名検索</h1>
● テンプレートをブラウザで表示して確認可能
app/views/methodlist/template.phptal
<body onload="prettyPrint()"><div class="container">
<div class="hero-unit"><h1 id="applypos" tal:content="title" >title here</h1></div><div class="alert alert-error" tal:condition="exists:
error_message" tal:content="error_message" >error message sample</div>
<p tal:replace="structure html_form" >Form</p><div class="row" metal:define-slot="content" >
contents here</div>
<footer><p class="pull-right"><a href="http://fuel.php-web.net/"
>http://fuel.php-web.net/</a> is programmed by <a href="http://php-web.net/">PHPでWEB作成</a></p>
<p><a href="http://fuelphp.com">FuelPHP</a> is released
under the MIT license.<br /></p>
</footer></div>
</body></html>
PHPTAL の特徴 2
● ビュー変数の出力をデフォルトエスケープ○ FuelPHP もデフォルトエスケープする
● FuelPHP のエスケープを無効にする方法'auto_filter_output' => false,
● HTML 属性をクォートしないとエラー○ エラー例: <div class=menu>メニュー</div>
PHPTAL の特徴 3
● 継承できる (ただし、ややこしい)
● 親 template.phptal
<html metal:define-macro="template"><div metal:define-slot="content">
● 子 index.phptal
<html metal:use-macro="template.phptal/template"><div metal:fill-slot="content">
PHPTAL のデメリット
● パフォーマンス○ smarty より遅いらしい http://d.hatena.ne.
jp/tanakahisateru/20100906/1283766620
● テンプレート HTML が厳密○ 例えば、</p> 無しだとエラー
● 日本語の情報が少ない
CSRF とは
● Cross Site Request Forgery
● 取り消しできない重要な処理を実行させる○ by 「安全な Web アプリケーションの作り方」 (徳丸浩)
● 被害者自身の操作で意図しないHTTPリクエストを送信させる攻撃○ by 「PHP逆引き516の大全」(大家正登, 鮫島康浩, 谷
中志織, 茂木健一)
CSRF 対策
● 重要な処理の直前の画面でトークン発行○ $form->add(Config::get('security.
csrf_token_key'),'token',array('type'=>'hidden','value'=>Security::fetch_token())) ;
○ $form->add_csrf(); (Form のみ?)
● 重要な処理実行時にチェック○ クッキー(*)の値と照合する○ Security::check_token()
* FuelPHP では(デフォルトでは)クッキーを使用
トークンを発行する箇所
入力画面 実行
トークン発行 チェック
トークンを発行する箇所
入力画面 実行
トークン発行 チェック
罠ページ 正規のトークンが無いので処理を実行しない
トークンを発行する箇所
入力画面 実行
チェック
確認画面
確認画面がある場合はどうなるか?
トークンを発行する箇所
入力画面 実行
チェック
確認画面
トークン発行
確認画面がある場合重要な処理実行の直前 = 確認画面
XSS とは
● クロスサイトスクリプティング
● 外部からの入力などに応じて表示が変化する箇所があり、この部分のHTML生成の実装に問題がある○ by 「安全な Web アプリケーションの作り方」 (徳丸浩)
● 2つ以上のサイトをまたがって、脆弱なサイトに悪意のあるスクリプトを混入させる○ by 「PHP逆引き516の大全」(大家正登, 鮫島康浩, 谷
中志織, 茂木健一)
XSS 対策
● 出力 HTML をエスケープする○ FuelPHP/PHPTAL はデフォルトエスケープ
■ エスケープ漏れが生じにくい
● HTML 属性値をクォートする○ PHPTAL は、クォート無しをハネる
■ ミスによる脆弱性が防げる
バリデーション
● 入力値の間違いを早期に発見して再入力を促すことにより、ユーザビリティを向上する○ by 「安全な Web アプリケーションの作り方」 (徳丸浩)
● 間違った処理を継続することによるデータの不整合などを防ぎ、システムの信頼性を向上させる○ by 「安全な Web アプリケーションの作り方」 (徳丸浩)
バリデーション
● add_rule で追加していく$form->add('classname','クラス名')
->add_rule('trim')->add_rule('valid_string',array
('alpha','dashes'))->add_rule('required')->add_rule('max_length',30);
php の関数(trim 等)も使用できる
valid_string はややこしい&ハマりやすい
バリデーション
$val = $form->validation();if ($val->run()){
検証を通過した場合
}else{
検証に失敗した場合
}
reflection
● クラスや関数等の情報を表示する○ メソッド、プロパティの情報取得○ コメントの取得○ クラス/関数が定義されているファイル名、行数の取得○ protected/private メソッド実行
● PHP の機能○ ReflectionClass が用意されている○ FuelPHP 以外でも利用可能
Reflection クラスのメソッド
getFileName()getStartLine()getEndLine()getMethods()
詳細は PHP マニュアル参照http://www.php.net/manual/ja/book.reflection.php
クラスのソースコードの表示
getFileName() でファイル名を取得
そのファイルを読み込むgetStartLine(), getEndLine() で範囲をチェック
getMethods() でメソッド一覧を取得
ユニットテスト
● 個々のメソッドのテスト○ メソッドの返り値のチェック等
● テストケースを残す○ 繰り返し実行可能
ユニットテスト
● FuelPHP では、PHPUnit を利用する
● oil から実行可能○ php oil test ○ php oil test --group=App○ php oil test --group=Core
FuelPHP をインストールしたルートで実行する
ユニットテストを書く
● app/tests フォルダに置く
● @group App アノテーションを書く
/** * * @group App */class Test_SourceView extends \TestCase
assertEquals で値が等しいかチェック
function test_sourceview(){
$classname = 'Date';$expected = 'クラス名:'.$classname;$data = Controller_Methodlist::_sourceview($classname);$title = $data->title;$this->assertEquals($expected,$title);
}
例外のテスト(アノテーションをつける)
/** * @expectedException InvalidArgumentException **/function test_sourceview_argument_null_raises_exception(){
$data = Controller_Methodlist::_sourceview('');}
ユニットテスト
● カバレッジ(*)も確認できる○ php oil test --group=App --coverage-html ./report/○ xdebug の設定が必要
* コードのうち、どれくらいがテストされているか
= テストされている部分/コード全体
テスト通過 : 緑、 未テスト : 橙
● 開催日時・頻度○ 平日夜で良いか?○ 定期開催するか?頻度は?
● 考えているネタ○ 効率的なWebアプリケーションの作り方
○ Novius OS http://www.novius-os.org/
今後の予定