aswww log

エンジニアの技術録。アプリとかウェブとか

fuelPHP1.6くらいで日付Validation関数独自実装

fuelPHPにて入力チェックの機構として以下のValidationクラスがある。

Validation Class

数値チェックや長さチェックは以下のとおりできる。

$validation = Validation::forge();
$validation->add('id', 'ID')
           ->add_rule('valid_string', 'numeric')
           ->add_rule('max_length', 11);

日付に関しても'valid_date'というものが用意されているのだが、これが何故かうまくいかず、常にエラーになってしまう。

//うまくいかない例
$validation->add('date', '日付')
           ->add_rule('valid_date', 'YYMMDD');

引数の日付型の指定が違うのかと色々調べたが、原因わからず。Validationなら調べるよりも独自で実装したほうが解決が早いと考え、独自実装することにした。


まず、fuel/app/classes/myvalidation.phpに以下のとおり実装する。ちなみに日付はyyyymmdd形式(例:20131126)で渡される想定。

<?php
class MyValidation
{
    //yyyymmdd形式の数値が$dateに入る
    public static function _validation_date_yyyymmdd($date)
    {
	if(!empty($date) && ctype_digit($date)){
	    if(checkdate(substr($date, 4, 2), substr($date, 6, 2), substr($date, 0, 4))){
			return true;
	    }
        }
	Validation::active()->set_message('date', ':label が不正です');
	return false;
    }
}

checkdateは日付を正確にチェックしてくれる。
それでコントローラーを以下のとおり実装する。

$validation = Validation::forge();
$validation->add_callable('myvalidation');   //myvalidation.phpを使用する
$validation->add('date', '日付')
           ->add_rule('date_yyyymmdd');      //独自関数指定

これで実装完了。ちゃんと20160229を指定するとtrueに、20150229を指定するとfalseが返ってくる。完成。
検索で出てこない時は独自で実装しちゃったほうがいいこともあるのね。

javascriptで時間操作がベンリ

今時jQueryといいつつも、jQueryがそもそもjavascriptのライブラリなわけだから当然jQueryを使う=javascriptを使う になるわけで。
そのjavascriptのDateオブジェクトの時刻操作が以外と便利なことが判明したのでメモ。

Dateオブジェクト生成したい場合は以下のとおり生成できる。

//引数無しで現在日時で生成
var date=new Date();
//引数有りで指定日時で生成(例は2013年11月20日 2:23)
var date=new Date(2013,11-1,20,13,2,23);

※Dateオブジェクトではなぜか月を0〜11で扱われてしまうので-1しとく。

これで例えば時間だけを取りたい時は以下のとおりに取り出せる。

//時間を取り出す(この場合hourの値は2)
var hour = date.getHours()

しかしこれだけでなく、setメソッドを使えば何分後とかの計算もしてくれる。

date.setMinutes(date.getMinutes()-60);

ここで優秀なのが、60分後を指定するとちゃんと時間をインクリメント(繰り上げ)してくれるとこ
つまり、以下の場合、「2時23分」を指定したDateオブジェクトに60(分)をsetしたため、Dateオブジェクトのもつ時刻は60分後の「3時23分」になる。(date.getHourの値が3になる)

var date=new Date(2013,11-1,20, 2,23);
//60(分)をsetする
date.setMinutes(date.getMinutes()+60);

ちなみにsetメソッドの引数に"-"(マイナス)を指定すれば何分前を指定することができる。これならjavascriptで時間操作の繰り上げ繰り下げに悩まされることはなさそう。

参考:
Date Object(setメソッド)
http://www.artemis.ac/contents/javascript/jsdate.htm
JavaScript による日付・時刻・時間の計算・演算のまとめ
http://www.hoge256.net/2007/08/64.html

Twitter Bootstrapのデザインカスタマイズお役立ちサイト

CSSフレームワークTwitter Bootstrapについて。
 Twitter Bootstrap(以下、Bootstrap)はあらかじめナビヘッダーやボタンなど多くのパーツがCSSで定義されているので、その定義されたclassを指定してあげるだけでフラットなデザインができたりする優れものだったりする。配色などは公式ダウンロードページでカスタマイズできるものの、トータルデザインを考慮しつつ配色カスタマイズを考えるはなかなか難しい。
 そこで、Bootstrapのカスタマイズに役立つ無料の便利サイトをいくつか紹介してみる。


○画像イメージから拡張テンプレートを自動生成してくれるサイト
 WEBに公開されている画像を参考に、イメージにあった配色のBootstrapカスタマイズテンプレートを提供してくれるのが以下のサイト。画像にサイトロゴなんかを設定して[Go Lavish]ボタンを押せばサイトロゴのデザインにあったテンプレートが出力される。完成品も修正できるので、完成度高い。今やっている案件ではこのテンプレートを採用している。

   Lavish, Bootstrap like a King


○カラーテーマ集
 そのまま様々なカラーのテーマテンプレートを無料で提供しているサイト。配色がキレイなものばかり。

   カラーテーマ一覧


○ボタンの色拡張CSS自動生成サイト
 テンプレートではないのだけど、Bootstrapのボタンの色を細かくグラフィカルに指定した拡張用CSSを出力してくれるサイト。ただし、色によってはhovar時の色が合わなくて自分で調整しないといけない自体になるところが難点。

   Beautiful Buttons for Twitter Bootstrappers



以上。これらのツール使った上でどうしても納得いかないところだけカスケードしたりして、いいかんじに仕上げてください。
参考:http://getbootstrap.com/css/

Autoloader::add_classesに追記するとoilでエラーになる件

FuelPHPの話。simpleauthを拡張した直後にoil実行したらerrorになった。

~/modules/admin$ php oil g controller history index

Fatal error: Class 'Error' not found in /home/account/modules/admin/fuel/core/bootstrap.php on line 79
Fatal error: Class 'Config' not found in /home/account/modules/admin/fuel/core/bootstrap.php on line 47

'Error'が無いといわれたのでrequire_onceでFuel\Core\Errorを読み込んでみたり、core内を色々(一時的に)書きこんでみたけどわからん。
そして最終的に以下のsimpleauthを拡張したtipsterauthに関する記述が原因だと気づいた

Autoloader::add_classes(array(
      'Auth\\Auth_Login_Tipsterauth' => BASEPATH.'packages/auth/classes/auth/login/tipsterauth.php',
      'Auth\\Auth_Acl_Tipsteracl' => BASEPATH.'packages/auth/classes/auth/acl/tipsteracl.php',
      'Auth\\Auth_Group_Tipstergroup' => BASEPATH.'packages/auth/classes/auth/group/tipstergroup.php',
));

#ちなみに BASEPATH=~/modules/admin/fuel/base
#このBASEPATH配下に実在するモジュールをAutLoaderに書きこんでいた。

ここで、Autoloaderに書き込むのはAPPPATH.以下でないと読み込めないのかと考え、以下のとおり記述を修正し、モジュールも配置し直した。

'Auth\\Auth_Login_Tipsterauth' => APPPATH.'classes/base/packages/auth/classes/auth/login/tipsterauth.php',
'Auth\\Auth_Acl_Tipsteracl' => APPPATH.'classes/base/packages/auth/classes/auth/acl/tipsteracl.php',
'Auth\\Auth_Group_Tipstergroup' => APPPATH.'classes/base/packages/auth/classes/auth/group/tipstergroup.php',

結果、エラーは解消された。
このことから、やはりエラーの原因はAPPPATH配下に置かなかったことだと考えた。しかし、この話を知人のSEにしたらAPPPATH配下でなくてもいけるとのことらしい。もしかしらたこれは邪道な解決方法なのか?取り急ぎはエラーが出なくなったからいいけど、時間ある時に別のやり方を検証してみようかと思う。

参考:
Class not found fuelphp oil http://stackoverflow.com/questions/16865795/class-not-found-fuelphp-oil
[FuelPHP]独自オリジナル認証ドライバをsimpleauthを参考に実装する1 http://to-developer.com/blog/?p=155

負のスパイラル突入中

更新頻度が低くて管理人不在に思われちゃうとアレなので現状報告を。

ここ一ヶ月作り→手戻り→作り→追加要件による手戻り→作りみたな感じで、かなり生産性無い具合に忙しい感じです。
こういう時だからこそ書きたいネタが沢山なのですが、更新する時間も惜しんじゃう現状。
技術ネタはそこまで鮮度重視じゃないのでとりあえず下書き保存して後々公開することにしましょう。

直近の課題としてモチベーション管理です。会社勤めの時は残業のだらけでも残業代が出るっていうかなり大きいモチベーションアップ要素があったのですが、フリーの場合だと時間かけるだけ自分が損なのでそれは使えませんね。

うーん、、、難しいですね。。。

oilによるViewとController生成

FuelPHPのoilコマンドでController・Viewの枠組みがだけ生成する方法。

php oil g controller Controller名 [メソッド名1] [メソッド名2]...

これをするとControllerとそのメソッドに紐づくviewファイルを生成してくれる。
例えばこんな感じ。

php oil g controller login index
	Creating view: /[APPPATH]/views/login/index.php
	Creating controller: /[APPPATH]/classes/controller/login.php

地味にめんどくさいクラス追加作業が一行で終わっちゃう。
不精さんにオススメ。

ちなみに他にViewModelとかも一緒に生成してくれるコマンドもあるけど、今回はModel・View・Controllerしか使わない予定なのでこれで十分なり。

phpでhtmlをparseする方法まとめ

スクレイピングバッチにかかせないのがhtmlのparse。いくつか方法をためしたのでまとめて見る。

1)PDOMDocumentとかを駆使して連想配列化する方法
 取得するHTMLによれば、おそらく最も手間がかからない方法。 手順は以下のとおり。

・file_get_contents()でHTML取得
・DOMDocumentのloadHTML()を使用してHTMLをXMLへ整形
・simplexml_load_string()でSimpleXMLElementオブジェクトへ変換
・json_encode()でJSON化。更にjson_decode()してArray化。

ただ、loadHTML()時に一番上にXMLタグが無いだけで怒られるし、file_get_contents()の時点で文字コード変換したのに何か文字化け(?)で怒られたりして使用を断念。

参考:PHPでHTMLをパースして解析する簡単な方法

※ちなみにDOMDoccumentが使えるかどうか調べるためのソースは以下のとおり。

<?php
print_r(get_loaded_extensions());
print_r (get_extension_funcs ("DOM"));

参考
PHPでDOM のモジュールが使えません!

2)Simple HTML DOM Parserを使用する方法
 結構有名なライブラリ。HTML取得からオブジェクト化までをfile_get_html()でやってくれるスグレモノ。導入方法と使い方を以下のとおり。

・zipファイルをダウンロードし、"simple_html_dom.php"のみを任意のディレクトリにコピーする。
phpファイルにてrequire(任意のディレクトリ/simple_html_dom.php)する。
・file_get_html()を使用してHTMLがParseされたオブジェクトを取得する。
 ※simple_html_dom.phpは関数集なので直接関数を呼んでしまって良い。

あとは取得したオブジェクトに$html->find('a')とか$html->find('img', 0)->srcとかして情報を取得する。(jQueryチックな操作感)やや柔軟だが、やはりタグが閉じられてなかったりするとお手上げ。あと重い。でも人気。解説サイトもたくさんある。

参考
PHP Simple HTML DOM Parser Manual(本家?)
PHP Simple HTML DOM Parser
誰でもスクレイピング!DOM要素を引っこ抜くSimple HTML Dom

3)preg系関数で正規表現とかを用いて頑張ってParseする方法
 これが一番めんどくさくいけど一番柔軟で一番確実な方法。1)2)で紹介した方法を用いた場合でも最終的にはこれを併用することになるのではないかな。よっぽど整形されたHTML相手でなければ。やり方はHTMLソースとにらめっこしてほしい情報をpreg_split()やらpreg_replace()を用いて一個一個取得する感じです。

参考
PHP マニュアル


他にも触ってないけどphpQueryというライブラリが気になった。名前のとおりjQueryライクな感じで要素へアクセスできるらしい。時間あるときに試したい。

参考
スクレイピング応用編-phpQuery
スクレイピング用おすすめライブラリ『phpQuery』の基本的な使い方