管理人
(0 件のコメント, 28 件の投稿)
このユーザーは共有されたプロフィール情報を持っていません
管理人 による投稿
CSS tips float の罠?
0おはようございます。将来の夢はイタクァに宇宙旅行に連れて行ってもらうことなゆうきんです。
ちょっと FuelPHP のサンプルページを凝って作ってみようとしたら、悩んだことがあったのでメモ。
float: left のように要素の回りこみを指定していると、それより下に書いた要素が、回りこみを指定した要素の表示位置と重なってしまうという現象。
これ、地味に困りました。
例えば、 css が
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
#div1 { width: 120px; height: 200px; background-color: blue; float: left; } #div2 { width: 60px; height: 200px; background-color: red; float: left; } #div3 { width: 300px; height: 50px; background-color: green; } |
これで、 view が
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> {Asset::css('testcss.css')} <title>css のテスト</title> </head> <body> <div id="div1"></div> <div id="div2"></div> <div id="div3"></div> </body> </html> |
の場合、私は
こうなって欲しかったのですが、実際は
こうなります・・・。
緑の部分が、青と赤の下に行ってしまうんです、
仕様を考えれば当然のことなんですが、これでは困るんですよね。
というわけで、以下の様に直して下さい。
そうすれば、想定した通りの配置になります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
div:after { content: ""; display: block; clear: both; } #div1 { width: 120px; height: 200px; background-color: blue; float: left; } #div2 { width: 60px; height: 200px; background-color: red; float: left; } #div3 { width: 300px; height: 50px; background-color: green; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> {Asset::css('testcss.css')} <title>css のテスト</title> </head> <body> <div> <div id="div1"></div> <div id="div2"></div> </div> <div id="div3"></div> </body> </html> |
これでOKです。
擬似要素である :after で「何もない」要素を表示しています。
content に指定したものが表示されるんですが、 “” という空の文字列を指定することによって、何もない要素としてます。
display はその要素をどう表示するかの指定で、今回はインラインでは困るのでブロックを指定してます。
clear は回り込みの解除するかどうかの指定です。 both で全ての回りこみを解除しています。
これで、 div の後に回りこみを無視する空の要素を表示することによって、次に表示する要素を、既に表示している要素の下に表示させることができるのです。
しかし、先ほどのビューの場合、赤 div の回り込みが残っているため、直後に表示する要素は、緑と同じ運命を辿ります。
そこで、回り込みのない div で青と赤をくくることにより、解決を図っているのです。
今回は、div 全てに :after を指定しましたが、今回の場合は、くくった div にのみ指定するのが正しいのかもしれません。
通常の div を表示する場合でも特に害がない(?)ので、私は div 全ての指定していますけどね。
では、おやすみなさい。
CSS tips FuelPHPのTemplateで使えそうなもの
0おはようございます。実家の犬に会いたくて禁断症状が出てきたゆうきんです。
チュートリアルでCSSの説明をする気はないと言ったな?…あれは嘘だ。
ちょくちょく自分でも忘れるのでメモがてら、私がTemplateコントローラで使っているCSSを書きます。
まず。これが私のTemplateです。
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 |
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> {Asset::css('template.css')} <title>{$title}</title> </head> <body> <!-- ヘッダ --> <div id="header"> {$header} </div> <!-- コンテンツ 上から「メニュー」「メイン」--> <div id="content"> <div id="menu">{$menu}</div> <div id="main">{$main}</div> </div> <!-- フッタ --> <div id="footer"> {$footer} </div> </body> </html> |
これを使うことを前提に書きます。
div を左右に並べる
#menu と #main を左右に並べてみます。
1 2 3 4 5 6 |
#menu { float: left; } #main { float: left; } |
float: left とは「要素を左に回りこませる」という意味です。
これで、左右に並べて表示できます。
しかし、画面を小さくしすぎると、配置が変わってしまうので注意です。
div を常に画面中央に表示
1 2 3 4 |
#content { margin:0px auto; width: 1200px; } |
これで、ウィンドウのサイズを変えても #content が画面の中心に表示されるようになります。
さらに、widthを指定しているので、ウィンドウサイズを小さくしても #menu と #main の配置が変わることがなくなります。
とりあえず、こんなところでしょうか。
本当はもっとごちゃごちゃ書いてあるんですか。装飾なので気にしないで下さい。
この記事はもしかしたら、随時更新していくかも知れないです。
では、おやすみなさい。
チュートリアル 画像認証
0次 未定
おはようございます。給料日前はいつもぎりぎり生活のゆうきんです。
captcha(キャプチャ) というものはご存知でしょうか。
よくユーザ登録などの際に、画像中の文字を入力して下さい とか言ってくるあれです。
主にスクリプトやBOT対策のために使用されます。
だって、機械がルーチンワークで登録繰り返したらあっという間にDBいっぱいになっちゃうじゃないですか。
そこで、画像認証は必要なものなのです。
FuelPHP で使える画像認証用のライブラリが公開されているので、簡単に実装できます。やったね!
導入
https://github.com/carlcraig/fuel-captcha から zip ファイルを落としてきて解凍して下さい。
解凍して出来たフォルダを captcha にリネームして、 fuel/package/ に突っ込んで下さい。
これで終わりです。
config.php の編集
app/config/config.php に以下の項目を追加して下さい。
1 2 3 |
'packages' => array( 'captcha', ), |
既に packages がある場合は、 captcha を追加するだけでいいです。
captcha の config を編集
ここからsimplecaptcha を使うか、recaptcha を使うかで書き方が違います。
simplecaptcha を使う場合は以下のようにします。
1 2 3 4 5 6 7 8 9 10 |
/** Default Driver * * (string) * * The name of the default driver to load * * The default driver will be called when you forge without giving the driver * e.g. Captcha::forge(); */ 'driver_default' => 'simplecaptcha', |
逆に recaptcha を使いたい場合は、 simplecaptcha と書かれている部分を recaptcha にして下さい。
この設定は、デフォルトでどっちを使うかの設定なので、特にやる必要はないですが、多く使う方を指定しておくと楽になります。
simplecaptcha を使用する
controller フォルダに simplecaptcha.php という名のファイルを作り以下の通りにして下さい。
1 2 3 4 5 6 7 8 9 |
<?php class Controller_Simplecaptcha extends Controller_Rest { public function get_image() { return Captcha::forge('simplecaptcha')->image(); } } |
captcha 用の画像を生成して、返す関数を用意しています。
なお、forge に ‘simplecaptcha’ を渡していますが、何も書かなければデフォルトの方が渡されるようになっています。
が、このファイルでは絶対に省略しないで下さい。
ファイルを作ったら、 fuel/package/captcha/config/simplecaptcha.php を以下の様に編集して下さい。
1 2 3 4 5 6 7 8 |
/** Captcha Route * * (string) * * The route to the captcha image * e.g. \Uri::create('captcha/index') */ 'captcha_route' => \Uri::create('simplecaptcha/image'), |
特にいじってなければ58行目にあると思います。
これは、captcha 用の画像はどれを使うのかという指定をしています。
この場合は先程の get_image 関数を指定いるわけです。
肝心の使い方は以下のようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Captchaテスト</title> </head> <body> {Form::open('captchatest/confirm')} {Captcha::forge('simplecaptcha')->html()} </p> {Form::submit('submit','送信')} </p> {Form::close()} </body> </html> |
これがビューです。名前は captchatest.smarty としてます。
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 |
<?php class Controller_Captchatest extends Controller { /** * アクションインデックス */ public function action_index() { return View_Smarty::forge('captchatest'); } /** * 認証に成功したか確認 */ public function action_confirm() { if( Captcha::forge('simplecaptcha')->check() ) { return '認証に成功'; } else { return View_Smarty::forge('captchatest'); } } } |
で、これがコントローラです。captchatest.php としてます。
Captcha::forge(‘simplecaptcha’)->html() で入力フォーム付きの HMLT を生成してくれます。
んでもって Captcha::forege(‘simplecaptcha’)->check() で入力した文字列が正しいかチェックをかけてます。
recaptcha を使う
私はこちらを使うのをオススメします。セキュリティの問題で・・・。
recaptcha とはgoogleさんが提供している captcha です。
まず、http://www.google.com/recaptcha にアクセスし、USE reCAPTCHA YOUR SITE をクリックして下さい。
そしたら SIGN UP をクリック、出てきた画面で recaptcha を使用したい画面のURLを入力しって、Create Key ボタンを押して下さい。
※Enable this key on all domains (global key) にチェックを付けるかドウかはTipsをよく読んでください。
ボタンを押したあとに出てきた画面で、 Public Key と Private Key をメモしておきましょう。
fuel/package/captcha/config/recaptcha.php に同じ項目があるので、メモした内容をペーストして下さい。
で、肝心の使い方なんですが、ビューとコントローラーは simplecapthca とまったく同じです。
forge 関数に渡す文字列を simplecaptcha から recaptcha に変えるだけです。
もし、デフォルトを simplecatpcha にしてて、 forge 関数ではなくも渡してないなら。デフォルトを recaptcha に変えるだけで終わりです。
以上で、画像認証についての説明を終わります。
では、おやすみなさい。・
チュートリアル セッション
0前 チュートリアル 複数のアプリケーションをフォルダごとにわける
おはようございます。何も買わないのに通販番組を見るのが好きなゆうきんです。
・・・セッション・・・。この単語を聞いただけで拒否反応が出るあなた。
そんなあなたに朗報です。
FuelPHP なら、なんと!簡単にセッション管理できるんです! オーディエンス<ナンダッテー!
セッション開始
1 |
Session::create(); |
これでセッションを開始できます。
古いセッションがある場合は破棄します。
セッションに値をセット
1 2 3 4 5 |
Session::set( 'userdata', array( 'id' => 'yukin', 'name' => 'ゆうきん', 'age' => '24', 'sex' => 'male' ) ); |
多分見ただけでわかりますよね。
第1引数でセッション名、第2引数で値を渡してあげるだけです。
サンプルのように連想配列も渡すことができます。
セッションから値の取得
1 |
Session::get('userdata'); |
これで、値の取得ができます。
格納したときと同じ型で返ってくるので、この場合は連想配列です。
セッションから値の削除
1 |
Session::delete('userdata'); |
セッションから値を破棄するだけです。
セッション自体が破棄されるわけではありません。
セッションの破棄
1 |
Session::destroy(); |
これで、セッションを破棄します。
セッションにセットした値も全て破棄されます。
セッションにフラッシュ変数をセット
1 |
Session::set_flash('flash', 'mabusii'); |
構成によってページのリクエストや変数の取得が行われたら、値が破棄される変数をセットします。
使い方は普通に値をセットするときと同じです。
セッションからフラッシュ変数を取得
1 |
Session::get_flash('flash'); |
フラッシュ変数を取得すると、フラッシュ変数が削除されます。
フラッシュ変数の寿命を延ばす
1 |
Session::keep_flash('flash'); |
次の消されるタイミングまで、寿命を延ばすことができます。
セッションからフラッシュ変数を削除
1 |
Session::delete_flash('flash'); |
削除したい場合これで。
基本的には、これだけでセッション管理できます。
他にも数個、関数があるのですが、使い方がわからないため説明できません。ごめんなさい。
でも、上記の関数だけで良いと思います。
以上でセッションの説明を終わります。
ちなみに、デフォルトではセッションはクッキーに保存されますが、ファイルやDBに保存することも可能らしいです。
今のところ必要性を感じないので、使うときが来たら説明します。
では、おやすみなさい。
FuelPHP tips Fuelのセキュリティ機能2
0・出力フィルタ
・URIフィルタ
・SQL文の自動エスケープ
・入力フィルタ
・XSSフィルタ
・バリデーション(検証)
・CSRF保護
はい、Fuelのセキュリティ機能1で説明できなかった残り4つ行きます。
微妙に順番が変わってるのは気にしない。
1. 入力フィルタ
入力フィルタとは、スーパーグローバル変数の内
$_POST
$_GET
$_COOKIE
この3つを処理する機能です。
フォームからの入力やクッキーの値などに独自のフィルタをかける事が可能です。
デフォルトではなにも設定されておらず全く機能しません。
1 2 3 4 5 6 |
/** * Security settings */ 'security' => array( 'input_filter' => array(), ) |
ほら、coreの方のconfig見ても何もないでしょ?array()の中が空でしょ?
この中には自分で作った関数を入れる事ができます。(使う時はcoreじゃなくappの方を編集しましょう。)
例えば、出力フィルタやURIフィルタで使用されている「htmlentities」を指定できたりします。(公式ドキュメント引用)
このブログの住人が参考にしている書籍では文字エンコーディングのフィルタを用意していましたね。
指定の仕方は例えば次のようになります。
1 2 3 4 5 6 |
/** * Security settings */ 'security' => array( 'input_filter' => array('Ore::rule'), ) |
Oreクラスのruleメソッドを指定してます。
でもって次がそのクラスです。配置は app/class/ore.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<?php class Ore { public static function rule($value) { /*ここでフィルタのルールを書いてやるといいと思うんだ*/ /*例えば、$valueの文字エンコードを調べたり*/ /*改行やタブはいいとしても、Delete等の普通は入力できない制御文字のチェックをするといいです*/ $foo = rand(); if( $foo % 100 != 0) return $value; else die('素晴らしく運がないなぁ君はぁ'); } } |
ランダムで100分の1の確率で処理を受け付ける的な感じになってます。
サンプルです。あくまでサンプルです。
普通だったら文字エンコーディングのチェックとかすると思います。
なぜこの入力フィルタがデフォルトで有効になってないかというと、公式ドキュメントが
「そんなことより出力フィルタが先だ」って言ってた気がする。
最終的に出力フィルタで全部エスケープするよ。って事だろうか。
2. XSSフィルタ
さぁ、なんて読むだろうか。
クロスサイトスクリプティングと読むらしい。
ちなみに、Fuelのセキュリティ機能1の出力フィルタでやった危ないサンプルがあったけど、あれがXSSです。
出力フィルタで使用しているhtmlentitiesだけでは対処が難しい場合、
Securityクラスが用意している「xss_clean()」っていう関数を使えばいいらしいです。
htmLawedというライブラリを使用してるらしいです。
なんでもかんでもタグ文字とかをエスケープするのではなく、危険なコードを安全なものに直したりするらしいんですがショウジキヨクワカラナイシシュツリョクフィルタニタヨリッキリナノデパスデオネガイシマス。
一応サンプル(Viewは割愛)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<?php class Controller_Test extends \Controller { public function action_index() { //以下サンプル3つ。 $data['a'] ='<SCRIPT>alert("(・ω・)")</SCRIPT>'; $data['a'] = Security::xss_clean($data['a']); $data['b'] ='<div>これは大丈夫</div>'; $data['b'] = Security::xss_clean($data['b']); $data['c'] ='<A HREF="javascript:document.location=\'http://www.google.com/\'">XSS</A>'; $data['c'] = Security::xss_clean($data['c']); //出力フィルタをfalseにしておこう return View::forge('sec_test_view.smarty',$data,false); } } |
各3つのサンプルの2行目、xss_clean()の行をコメントアウトしたりして動作を確認できます。
1つ目はスクリプト実行によりアラートが出てきます。
フィルタに通すと「<SCRIPT></SCRIPT>」を取り除いてくれます。
2つ目はそのまま表示されます。全てのタグを取り除くわけではないようです。
3つ目はフィルタを通すと「javascript」の前に「deny:」を付けて無効化(?)してくれたりします。
「<A HREF=・・・」は「<a href=・・・」とか小文字に直してくれて残してくれます。
FuelPHPの公式ドキュメントには、「パフォーマンスの理由」により個別の変数に対して使用することを推奨しているようです。
それよりもなによりも出力フィルタを優先すべきだと言ってるので、出力フィルタをオフにしないように心がけたい。
3. バリデーション (検証)
バリデーションは、あらかじめ作って置いたルールに基づき変数を検証することです。
「ユーザー名は○文字以下まで」
「パスワードは○文字以上○文字以下」
などです。
使い方はこちらを参照してください。
→チュートリアル フォームの作成とDBの使い方
4.CSRF保護
このCSRF、クロスサイトリクエストフォージェリって言います。
XSSと似てますが違います。
CSRFの恐怖はこちらを参照→Wikipedia:クロスサイトリクエストフォージェリ
このCSRFの対策とし
1.ページ作成時に次の2のためのトークンを生成
2.form送信の時にCSRF対策用のトークン(hiddenでおk)を一緒に送信
3.送られてきたトークンをチェックし有効ならそのまま、無効ならアウトォォォ!
では、1のコードから2の送信
1 2 3 4 5 |
<form 〜〜割愛〜〜> <?php echo Form::hidden(Config::get('security.csrf_token_key'), Security::fetch_token()); ?> <input 割愛〜〜> </form> |
Viewで作ってます。面倒なんで。
Config::get(〜〜〜)で「security」の「csrf_token_key」の値を取得します。
デフォルトでは「fuel_csrf_token」という文字列になってます。
Security::fetch_token()でトークンを生成しています。
そして、各フォームの値と一緒に送信します。
そして、次の3のコードでチェック
1 2 3 |
if( Security::check_token() == false ) echo "トークンが一致しません。"; else "トークンが一致。有効なリクエストだぁ"; |
メッセージが長くてうざいけど、チェックする処理自体は非常に短いです。
このCSRF保護機能ですが、中身の実装がやや怪しいらしいです(暗号論的疑似乱数生成とか)
バージョンアップで強化されていくことを願いましょう。
これで一応終了。
もうセキュリティって言葉ってなんだ?
っていうゲシュタルト崩壊が起きてきそうです。
FuelPHP tips Fuelのセキュリティ機能1
0そろそろFuelPHPにも慣れてきたんじゃないっすかぁ?
じゃぁちょっとセキュリティとかっていう面倒くさいものをやりましょうか。
大丈夫大丈夫!FuelPHP優秀だから大丈夫だって!諦めんなよ!あっつくなれよ!
FuelPHPにあるセキュリティ:Security
FuelPHPには最初から以下のセキュリティ機能が入ってたりします。
・出力フィルタ
・URIフィルタ
・SQL文の自動エスケープ
・入力フィルタ
・CSRF保護
・XSSフィルタ
・バリデーション(検証)
上3つの太字で表したものはデフォルトで有効になっています。
多分意識してないと思いますが、コントローラーからビューに変数を渡すときに出力フィルタが働いています。
1つ1つ見ていきましょうか。
1. 出力フィルタ
Securityクラスにhtmlentities()って関数があって、出力フィルタとURIフィルタで使ったりしてます。
この関数は文字列をエスケープして返します。
なんのこっちゃって言う人のために、以下のサンプルをどうぞ。(Viewは適当に作ってね★)
1 2 3 4 5 6 7 8 9 10 |
/*action_index以外省略*/ public function action_index() { //例えばユーザが入力した値を表示するものとする //↓Inputクラスで取得したりしたものとする $data = "<script>alert('(・ω・)')</script>"; //↓第3引数でfalseを指定すると出力フィルタがオフになる return View::forge('test_view',array('data'=>$data) ,false); } |
このサンプルのページにいくと、javascriptのalertが出てきて「(・ω・)」とかふざけた顔文字が出てくる。
顔文字だったらカワイイだけで済むが(かわいいよねこれ(・ω・))
これをユーザーが自由に入力できるとしたら攻撃されまくりである。
例えばユーザー名に
「<script>有害コード</script>」
って入力されたりするかもね。
なんかヤバい感じを味わったら、次は
1 2 3 |
//↓第3引数でfalseを指定すると出力フィルタがオフになる //return View::forge('test_view',array('data'=>$data) ,false); return View::forge('test_view',array('data'=>$data) , true); |
さっき作ったサンプルの上の部分を変更してみよう。
第3引数をfalseからtrueにするのだ。
すると、今度はサンプルで書いたScriptのコードがそのまま出てきたと思う。
ブラウザの機能の「ソースコードを表示」で見てみると、不思議な文字の羅列があったりする。
これは出力フィルタがhtmlタグをそのまんまじゃなく、それを示す違う記号にエスケープしたのです。
ちなみに、第3引数を省略すると、デフォルトでtrue設定になるので安心だ(・ω・)b
便利ですね。
2. URIフィルタ
URIフィルタとは。
まず以下のサンプルをどうぞ
1 2 3 4 5 6 7 8 9 10 11 12 |
class Controller_Test extends Controller { public function action_index($a='') { $data = "<>以外が入力された?"; if($a === Security::htmlentities("<>")) $data = "URIフィルタOn"; else if($a === "<>") $data = "URIフィルタおっふ"; return View::forge('test_view',array('data'=>$data)); } } |
これで 「http://~~~~~/test/index/<>」というURLにアクセスしましょう。(~~~の部分は当然各環境に合わせてください)
action_indexは本来指定しなくてもアクセス出来ますが、パラメーターを$aとして受けとるために記述が必要になってきます。
そしてパラメーターとして「<>」を渡しています。(あくまで例です。他にも試してみてください。)
サンプルでは、この「<>」をSecurityクラスのhtmlentitiesを使用して、URIフィルタが機能しているかどうかを判定しています。
まぁぶっちゃけ”URIフィルタおっふ”は表示される事はないだろう。。。or
オンとかオフとか書きましたが、このURIフィルタをオフにする方法がちょっと見つからなかったので設定はデフォルトのままで放置します。
3. SQL文の自動エスケープ
FuelPHPではSQLインジェクションに対する機能があります。
データベースを扱う部分で説明すると思いますが、クエリビルダーがその役目を負っています。
例えば「DB::select()->・・・」で始まる奴とかですね。
このクエリビルダー機能で発行されたクエリは全てエスケープ済みです。
DBクラスのクエリビルダーってすごく簡単でしかもセキュリティ対策もしてくれてるのです!
いやぁSQL文使わなくても(使えなくても)いいんですよー。
あとの4つはFuelのセキュリティ機能2で説明します。
チュートリアル 複数のアプリケーションをフォルダごとにわける
0
おはようございます。最近21時には寝て3時に起きる、超絶早寝早起き人間のゆうきんです。
FuelPHP にも大分、慣れたことだと思います。
今回は、複数のアプリケーションをフォルダごとにわける方法を説明します。
FuelPHP のモジュール機能を使っても、数が増えすぎると限界がきますからね。
やはり、プロジェクトはわけたいところです。
1.FuelPHPを配置する
これは、終わっていると思うので、配置してあるディレクトリだけ覚えておいて下さい。
今回は、 home/work/ に fuelphp という名前で配置してあるものとします。
2.アプリケーション用のフォルダを作成する
適当な場所にフォルダを作成して下さい。
今回は FuelPHP のフォルダと同じ階層に test というフォルダを作成するとします。
作成したらフォルダ内に FuelPHP から app フォルダ、 public フォルダ、 oil をコピーして下さい。
3.ファイルを書き換える
public/index.php と oil を書き換えます。
コアへのパスがデフォルトとは違うので、1で覚えておいたFuelPHPのパスに変更して下さい。
今回の場合は、以下のようになります。
public/index.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
/** * Path to the application directory. */ define('APPPATH', realpath(__DIR__.'/../app/').DIRECTORY_SEPARATOR); /** * Path to the default packages directory. */ define('PKGPATH', realpath(__DIR__.'/../../fuelphp/fuel/packages/').DIRECTORY_SEPARATOR); /** * The path to the framework core. */ define('COREPATH', realpath(__DIR__.'/../../fuelphp/fuel/core/').DIRECTORY_SEPARATOR); |
oil
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
/** * Path to the application directory. */ define('APPPATH', realpath(__DIR__.'/app/').DIRECTORY_SEPARATOR); /** * Path to the default packages directory. */ define('PKGPATH', realpath(__DIR__.'/../fuelphp//fuel/packages/').DIRECTORY_SEPARATOR); /** * The path to the framework core. */ define('COREPATH', realpath(__DIR__.'/../fuelphp/fuel/core/').DIRECTORY_SEPARATOR); |
相対パスにしていますが、絶対パスでもいいです。
3.コマンド実行
配置した test フォルダに移動して、以下のコマンドを実行してください。
1 |
php oil refine install |
4.Apacheのドキュメントルートフォルダにアプリケーションフォルダのシンボリックリンクを貼り付ける
test/public のシンボリックリンクを、Apache の htdocs フォルダに作成してください。
これで、公開されます。
※本当は test フォルダのシンボリックリンクを作成するらしいのですが、ファルダ構成とか見られてしまう可能性があるので、test/public としてます。
アプリケーションを増やすたびに 2~4 を繰り返して下さい。
では、おやすみなさい。
FuelPHP tips Numクラス
0Uploadクラスとかで、なんかファイルサイズを指定したりする時どんな風に書いてますか?
$size = 1024*1024*8;
とか書いてませんか?
けどこの書き方、なんか数字の羅列で見づらいですね。
慣れてる人は8MBだ、ってすぐ出てくるかもしれませんね。
今回ご紹介する商品はこちら!
FuelPHPに最初から入っている!
Numクラス!
まだ、ちょっとバイトとかビットの数字に慣れてないです・・・
っていうそこのあなた!
これさえあればもう面倒くさい計算なんてしなくていい!
先ほどの例を上げると
$size = Num::bytes(‘8M’);
ほらスッキリ!
文字列を数値に自動で!変換してくれちゃったりするんですよ〜。
みなさん。驚くのはまだ早いですよ?
今回はこれにプラスして!逆変換機能もつけちゃいます!
echo Num::format_bytes(‘1024’); → 1kB
数値を入れればそれを文字列に直してくれます!
さらに!
echo Num::format_bytes(‘1124’,1); → 1.1kB
このように第2引数で小数点以下表示も可能!
けどやっぱり、みなさんが気になるのはお値段の方ですよね〜?
大丈夫です。このNumクラス、
数値→文字列機能
文字列→数値機能
2つセットで!15回払い対応の!0円!
はい、通販番組風の前置きが長くなりましたがNumクラスについて書きます。
Numクラス
数値に関する、型変換や出力を支援してくれます。
::bytes($size=0)
引数で指定した文字列を数値(float)で返します。実はintやfloatも引数として扱えます。
「K,M,G」や「MiB」なんていう特殊なものもあります。
::format_bytes($bytes=0 , [$decimals=0])
第1引数で指定した数値を文字列で返します。その際適切な接頭辞が付けられます。
第2引数は省略可。数値を指定すると小数点以下が表記されます。
例)
1 |
echo Num::format_bytes(1124,1); //→1.1kB |
::quantity($num, [$decimals=0])
第1引数で指定した数値を適切な接頭辞が付けた上で四捨五入します。(多分)
第2引数で数値を指定すると、どこで四捨五入するか小数点以下の場所を指定できます。
例)
1 |
echo Num::quantity('1624006',5); //→1.62401M |
::format($string = “” , $fomart = “” )
見づらいんで↑シングルクォーテーションをダブルクォーテーションにしました。
まずは例)
1 2 3 |
echo Num::format("1234567890" , " (000) - 000 - 0000"); //→ (123) - 456 - 7890 echo Num::format("1234567890" , "0!0#0$0%0&0'0(0)0~,.<>-^;:@[]日本語 0"); //→1!2#3$4%5&6'7(8)9~,.<>-^;:@[]日本語 0 |
なお第2引数の0の羅列は英数字ならなんでもいいらしい。逆を言うと英数字で分けたりとかできない。
日本語で分けれるのが笑える。
(“20120128″,”0000年00月00日”)で2012年01月28日とか出ちゃう。
追記:mask_stringで実験してからこっちも試したらなんかこうなった
1 |
echo Num::format("abcdefghij", "aaa-aaa-aaa-a"); //→abc-def-ghi-j |
::mask_string($string=”” , $format=”” , ignore=””)
例)
1 2 3 |
echo Num::mask_string("1111222233334444" , "**** **** **** 0000"); //→ **** **** **** 4444 echo Num::mask_string("111122223333" , "****-0000-****" , "-"); //→ ****-2222-**** echo Num::mask_string("aaabbbccceee" ,"*** aaa *** 000"); //→ *** bbb *** eee |
数値でも文字列でも可能のようです。
数値は「0」、文字列は「a」とかそういう指定は無いみたいです。
入力された英数字は、formatの英数字部分で表示され、それ以外ではその記号が出力されるみたいです。
ignoreで指定した記号はその際文字数としてカウントしないで無視されるようです。
なのでこんな例も可能
::mask_string(“abcdefghij”, “@@@-@@@-00@” ,”-“); → @@@-@@@-gh@@
お、クレジットカードとかに使えそうじゃん?とか思ったあなた。次の関数を見てくれ。
::mask_credit_card($string , $format=null)
クレジットカード用のmask_string関数が用意されてましたとさ。
例)
1 |
echo Num::mask_credit_card("1111222233334444"); //→ **** **** **** 4444 |
用意周到ですな・・・
基本「format()」を使えばなんとなる。
他にもちょくちょくありましたが、クレジット用みたいにformat()を使いやすくしたっていうものなんで省略します。
番外編:接頭辞
途中で1MiBとかいう特殊な表記が出てきましたが、これには深いわけが。
この接頭辞(k,M,G,Tとかね)って実は2を冪乗とする数値には使っちゃいけないって決まりがあったりする。
なのでコンピュータの世界では1MBって表記するのはダメだったりする。
さり気にキロだけ小文字なのはこれも決まりなのである。「大文字を使ってはいけない」らしい。
大文字にするとケルビンの方になるらしい。
コンピュータ専用の接頭辞があってそれを2進接頭辞と呼びます。
1kB→1KiB
1MB →1MiB・・・
という感じに「i」が付いちゃう。読み方は1KiB「1キビバイト」 1MiB「1メビバイト」という感じになります。
実際は、全然普及してないっぽいよね。Linuxだとけっこうお目にかかりますが。
エクサなんてエクスビってなるんだよ。(読みづらいのがさらに読みづらくなった)
ちなみに接頭辞には1da(デカ 10の1乗)とか不思議なものがある。
チュートリアル フォームの作成とDBの使い方
0次 チュートリアル 複数のアプリケーションをフォルダごとにわける
おはようございます。いつまでも中二病を卒業できないゆうきんです。
今回はフォームの作成と、送信したデータをDBに書きこむということをやってみたいと思います。
現代のWebサイトでDBが絡まないということはとても少ないです。
というわけで、作って行きましょう。
あ、Smartyの使い方ってページ読みました?
今回からビューは全てSmartyを使って書いていくので、読んでおいて下さい。
ユーザに登録させる情報を決める
今回はユーザに ユーザ名、ユーザID、パスワード、e-mailアドレス、を登録させたいと思います。
ユーザ名は1〜8文字まで、ユーザIDとパスワードは半角英数字で4〜12文字という制約を設けます。
データベースの構造を考える
まず前提として文字列は全て utf8_general_ci を使います。
データベース名 test で、テーブル名は users としましょう。
プレイマリ は id というカラムで、オートインクリメントも有効にしておきます。
ame, userid, password, email というカラムも追加しましょう。
全部 text 形式でOKです。
画面遷移を決める
- 入力ページ
- 確認ページ
- 完了ページ
の3つを作成し、上から順に遷移していくものとします。
いろいろ決まった所で作っていきます。
こらから作るファイルはサブフォルダは作らず、controler, model, views のフォルダに配置するものとします。
入力ページの作成
こちらが、入力ページのソースです。
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 31 32 33 34 |
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title>ユーザ情報登録入力ページ</title> </head> <body> {if (isset($errors))} {$errors} {/if} {Form::open('input/confirm')} <p> {Form::label('ユーザ名', 'username')} {Form::input('username', Input::post('username'), ['required'=>'required'])}<br /> </p> <p> {Form::label('ユーザID', 'userid')} {Form::input('userid', Input::post('userid'), ['required'=>'required'])}<br /> </p> <p> {Form::label('パスワード', 'password')} {Form::password('password', Input::post('password'), ['required'=>'required'])}<br /> </p> <p> {Form::label('e-mail', 'email')} {Form::input('email', Input::post('email'), ['required'=>'required', 'email' => 'email'])}<br /> </p> <p> {Form::submit('submit','送信')} </p> {Form::close()} </body> </html> |
Formクラスの説明をします。FormクラスはHTMLタグを生成するクラスです。
ここで使っているものを順次説明します。
Form::open
form開始タグを生成します。
第1引数 実行された時の動作、又は、属性の連想配列(例:array(‘action’ => ‘example/index’, ‘method’ => ‘post’))
Form::close
form終了タグを生成します。
引数はありません。
Form::label
labelタグを生成します。
第1引数 ラベル名
第2引数 関連付けたい部品のID
Form::input
inputタグを生成します。
第1引数 任意のID
第2引数 初期データ
第3引数 タグの属性
Form::password
inputタグを生成します。
使い方は Form::input と同じです。
input タグの属性が password になります。
他にもラジオボタンを生成したり、テキストエリアを生成したりできる関数がありますが、割愛します。
input関数の第2引数で Input::post(‘username’) としていますが、これは username が post されていたら、それを初期値で表示するとういことです。
入力内容に誤りがあったとき、確認ページで修正を選択したとき、などに前回入力したデータを初期値で持たせるということをしたいので、このようになっています。
続いて、こちらがコントローラです。
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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
<?php use Fuel\Core\HttpNotFoundException; class Controller_Input extends Controller { /** * アクションインデックス */ public function action_index() { return View_Smarty::forge('input'); } /** * 確認ページ */ public function action_confirm() { // POST 以外のアクセスを禁止する if( Input::method() != 'POST' ) { throw new HttpNotFoundException; } // 入力チェック $val = $this->get_validation(); // 入力された値が正しかったか? if( $val->run() ) { // 正しい場合は確認ページに遷移 $data['input'] = $val->validated(); return View_Smarty::forge('confirm', $data); } else { // 正しくない倍位は入力ページに戻り、エラーを表示 $input_view = View_Smarty::forge('input'); $input_view->set_safe('errors', $val->show_errors()); return $input_view; } } /** * 入力検証 */ // 検証ルールの定義 public function get_validation() { $val = Validation::forge(); $val->add('username', 'ユーザ名') ->add_rule('required') ->add_rule('min_length', 1) ->add_rule('max_length', 8); $val->add('userid', 'ユーザID') ->add_rule('required') ->add_rule('min_length', 4) ->add_rule('max_length', 12); $val->add('password', 'パスワード') ->add_rule('required') ->add_rule('min_length', 4) ->add_rule('max_length', 12); $val->add('email', 'e-mail') ->add_rule('required') ->add_rule('valid_email'); return $val; } } |
action_index で input ビューを表示。
action_confirm で データが post されていたら、データチェックして confirm ビューを表示。
データに誤りがあれば。エラー内容を input ビューに渡して再表示。
action_confirm で行うデータチェックのルールは get_validation で定義しています。
validation とは?
form の input で入力するデータにルール付を行うことです。
例えばこの文字は30文字しか入力できないとか、4文字以上でなければ認めない、などです。
validation の使い方
Validation::forge メソッドでクラスのインスタンスを生成し、それにルールを加えていきます。
add メソッドで ルール付けを行う input の ID と、任意のフィールド名を指定します。
フィールド名は混乱を避けるために、 input ニ関連付けた label と同じ名前が好ましいです。
そして、 add_rule メソッドでルールを追加します。
ルールの内容はソースを見ていただければわかると思います。
※ メモ:私が悩んだことなのですが trim とは、文字列前後の空白を取り除くphpの標準関数のことです
ルール付けが終わったら run メソッドでデータチェックを行えます。
正しければ true 、間違っていれば false が返ってきます。
validated メソッドでチェックをかけた後のデータを配列で取得することができるので、 confirm ビューニ渡しています。
show_errors メソッドでエラー内容を表示できるので、set_safe メソッドで input ビューに渡しています。
set_safe を使うとエスケープされずに文字列をビューに渡すことが可能です。
確認ページの作成
続いて、 確認ページのソースです。
まずはビューです。
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 31 32 33 34 35 36 37 38 39 40 41 42 |
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title>ユーザ情報登録確認ページ</title> </head> <body> <p> ユーザ名:{$input['username']} </p> <p> ユーザID:{$input['userid']} </p> <p> パスワード:{$input['password']} </p> <p> e-mail:{$input['email']} </p> {Form::open('input/')} {Form::hidden('username', $input['username'])} {Form::hidden('userid', $input['userid'])} {Form::hidden('password', $input['password'])} {Form::hidden('email', $input['email'])} <p> {Form::submit('submit','修正')} </p> {Form::close()} {Form::open('input/conplete')} {Form::hidden(Config::get('security.csrf_token_key'), Security::fetch_token())} {Form::hidden('username', $input['username'])} {Form::hidden('userid', $input['userid'])} {Form::hidden('password', $input['password'])} {Form::hidden('email', $input['email'])} <p> {Form::submit('submit','登録')} </p> {Form::close()} </body> </html> |
確認用に受け取ったデータを表示しています。
そして、修正ボタンを押したら入力ページに現在のデータを post して遷移します。
登録ボタンを押したら確認ページに現在のデータを post して遷移します。
そのためフォームタグは2つ用意しています。
以下が、見たことないと思われる関数の使い方と説明です。
Form::hidden
実際には表示されない input タグを生成します。
第1引数 任意のID
第2引数 送信したいデータ
Config::get
config.php の内容を取得できます。
第1引数 取得したい項目名
第2引数 指定した項目名がなかった場合に、代入するデータ
今回は CSRF 対策のため、security 内の csrf_token_key を取得しています。
CSRF 対策用のトークンを post する際の ID は必ず security.csrf_token_key を指定するようにして下さい。
Security::fetch_token
CSRF 対策のトークンを発行します。
引数なし
次に書くコントローラのソースで説明しますが、このトークンをチェックすることにより、CSRF 対策を行うことが出来ます。
続いてコントローラです。
入力ページで作成した Controller_Input クラスに追加して下さい。
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 |
/** * 完了ページ */ public function action_conplete() { if( Input::method() != 'POST' ) { throw new HttpNotFoundException; } // CSRF対策 if( !Security::check_token() ) { return 'ページ遷移が正しくありません。'; } // DBに書きこむ Model_Input::push_user( Input::post('username'), Input::post('userid'), Input::post('password'), Input::post('email') ); // 完了ページ表示 return View_Smarty::forge('complete'); } |
Security::check_token
引数なし
CSRF 対策トークンをチェックします。
まず post されているかチェック、CSRF トークンチェックを行い、どちらも認証できれば、データベース操作に移ります。
Model_Input::push_user は独自に作ったクラスと関数です。
以下の通りです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<?php class Model_Input extends Model { public static function push_user( $username, $userid, $password, $email ) { $result = DB::insert('users')->set(array( 'username' => $username, 'userid' => $userid, 'password' => $password, 'email' => $email, ) )->execute(); return $result; } } |
確認ページの作成
「登録完了しました」と表示しているだけなので、特に記載しません。
以上で、フォームの作り方の説明を終わります。
大分省きました。
本当は、ユーザ名、ユーザIDとe-mailアドレスの2重チェックとか、データベースに書き込み成功したかのチェックかけたりとかしなければなりません。
ここまで、少し調べれば出来ることだと思うので、気が向いたら書くかも知れないです。
以下、どうでもいい話
これ作ってる最中に、同僚に「e-mailアドレスの変数名って emal じゃなくて email_address じゃないの?」って言われました。
そこで「email_address だと長いから address は?」と返したんですが、「address だと住所じゃん(笑)」と言われてしまいました。
確かに email だと意味が違いますし、 address だと住所になっちゃうんで、 email_addressが正解ですね(笑)
でも、なんか間違いを認めると負けた気がするので、私はずっと emal で通しますよ!
同じ理由で職場のエアコンで暖房を付けることを、ストーブを付けると言いはってます。
では、おやすみなさい。
PHP – アップロードのファイルサイズについて
0POSTメソッドを使用した、クライアントからサーバーへのファイルアップロードについての注意書き。
1. アップロードファイルの最大サイズ
PHPの設定ファイル「php.ini」の以下の項目で設定
1 |
upload_max_filesize = 2M |
単位はバイトのようです。
このupload_max_filesizeが指定するファイルサイズとは、以下の「upfile」で示したファイルの最大許容サイズの事。
1 2 3 4 |
<form action="upload" method="post" enctype="multipart/form-data"> <input type="file" name="upfile" id="upfile"/> <input type="submit" value="アップロード" /> </form> |
現状の設定だと、2MB(デフォルト値)以上のファイルをアップロードすると、PHP側はそれらサイズオーバーしたファイルを破棄する。
この場合、$_FILESで取得できるエラー情報に「UPLOAD_ERR_INI_SIZE」(int型で1)が返る。
1 2 |
$error = $_FILES['upfile']['error']; echo $error; |
エラーコードに関してはPHPの公式を参照してください。http://php.net/manual/ja/features.file-upload.errors.php
2MB以上のファイルをアップロードしたい場合は、upload_max_filesizeの値を大きくすればよし。
2. POSTメソッドにてPOSTできる全体の最大サイズ
若干分かり辛い日本語ですね。
ファイルアップロードでサーバーに送信されるデータは何もファイルだけではありません。
<form>でくくっている中にいろいろな情報がありますね。「enctype=”multipart/form-data”」とかありますね。
これら全部を含めた「POSTできる最大サイズ」ってのんがあります。
1 |
post_max_size = 8M |
例のごとくphp.iniに上記の項目があります。デフォルト値は8M(PHP5だとこのはず)です。
upload_max_sizeでどんなに大きくしても上記のpost_max_sizeに設定した以上のデータは送信できないです。
もし設定サイズをオーバーするデータをPOSTすると、PHPは全て無かった事にします。
もとい、$_POSTと$FILESを空にしちゃいます。
この状態で「$_FILES[“upfile”][“size”]」とか使っちゃうと「そんなもんねぇよ」って怒られます。
大きいなサイズのファイルをアップロードする場合、この値も大きくしなければいけません。
注意して欲しいのは「upload_max_filesize < post_max_size」です
「<=」ではなく「<」でなければいけないです。(多分きっとおそらくメイビー)
3. PHPを実行する時の確保メモリ量
PHPもメモリ確保します。当たり前ですね。
あまり良くわからないので設定項目だけ。
1 |
memory_limit = 128M |
php.ini に上記の項目があります。(デフォルトは128Mだったはず)
メモリの最大確保サイズを指定しています。
基本的に
「upload_max_filesize < post_max_size < memory_limit」
となるようにしましょう。
4. php.ini以外で設定してみる .conf
php.iniはいわば元となる設定ファイル。
大容量アップロードに対応して、あらかじめ大きな値を設定したりすると、目的のコード以外のところでもその設定が反映されちゃいます。
別にいいよっていうならばここは読み飛ばしてください。
上で説明した1〜3の項目はApacheのconfファイルでも設定可能です。
CentOSなら「httpd.conf」
Ubuntuなら・・・いろいろ設定があるので調べて見てください。とりあえず.confに書けばいいと。
そしてディレクティブに以下のような記述をするとおkなわけです。
1 2 3 |
php_value memory_limit 128M php_value post_max_size 8M php_value upload_max_filesize 2M |
5. php.ini以外で設定してみる .htaccess
ディレクトリ毎の設定を変更できる.htaccessでも1〜3を変更できます。
反映させたいphpファイルがあるフォルダと同じ場所に以下の内容の.htaccessを作ればよろし
1 2 3 4 5 |
<IfModule mod_php5.c> php_value memory_limit 128M php_value post_max_size 8M php_value upload_max_filesize 2M </IfModule> |
6. ファイルサイズの制限
まぁ設定でどんな大きくしたって、それを越えるファイルを上げてくる奴がいるかもしれませんね。
いっそ無限にできないの?無限は無理だけど無制限なら可能です。
「memory_limit = -1」とかにすると制限なしという意味になります。
ただし、無制限はちょっとオススメしたくないなぁ。
てことでファイルサイズのチェック方法を書きます。(チェックできれば制限できるはず)
以下、memory_limit,post_max_size,upload_max_filesizeはデフォルト値の128M,8M,2Mとします。
そもそも1~3の設定で制限できてるのでは?という疑問があるかもしれません。
が、問題は項目2の「post_max_size」なんですよ。
これを越えてくるデータをPOSTされると、POSTデータ全部なくなっちゃうわけで。
1 2 3 4 |
$max_filesize = 1024*1024*2; //2Mの意味 if( $_FILES["upfile"]["size"] < $max_filesize) echo "OK"; else echo "NG"; |
とかあったら残念な事になる。
2MB以下のファイルをアップロードすると、OKが表示されますね。
2MB以上のファイルだとNGが表示されますが、が、が、
「8MB以上のファイル」だと事情が変わってきます。
この例であれば、8MB以上のファイルでOKが表示されてしまうかもしれません。
上の項目2でも書いてますが、そもそも$_FILESが空になってしまうからです。
じゃぁどうするかというと、
お手軽ということで以下のコードで
1 2 3 4 |
$size = 1024*1024*2 //2MBの意味 if( $_SERVER['CONTENT_LENGTH'] < $size ) echo "OK"; else echo "NG"; |
このようにすればいいかな。ヘッダーの情報を見ています。
この値はクライアントが書き換え可能ですが、やましい事ない人は書き換えたりとかしませんよね。
書き換えたりしてきたら全部エラーページもなにもなしに処理中断でいいかと。
7. テストするに当たって・・・(テスト工程ではありません)
今回やたらつまったんですよ。
get_cfg_var()でテストしてたんですよ。
.htaccessとかでいじっても値が変更されないなぁとか思ってたんですよ。
get_cfg_var()がphp.iniの値しか見ないとか思ってなかったんですよ。
phpinfo()かini_get()使わないといけないって思わなかったんですよ。
・・・誠に残念である。
phpinfo()使いましょうね。はい。
(・ω・)