忍者ブログ
[PR]
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。



2025/07/29 16:03 |
PHP5.4.7 トレイト
PHP5.4でtraitという機能が追加されています。

クラスAをextendsしてるけど、ここに追加でクラスBとクラスCもextendsしたい、そんな要求を概ね叶えてくれる機能です。
<?php
	// 基底クラス
	class A{
		public function hoge(){
			print('クラスAのメソッドhoge');
		}
	}

	// trait
	trait B{
		public function hoge(){
			print('トレイトBのメソッドhoge');
		}
		public function fuga(){
			print('トレイトBのメソッドfuga');
		}
		public function foo(){
			print('トレイトBのメソッドfoo');
		}
	}

	trait C{
		public function fuga(){
			print('トレイトCのメソッドfuga');
		}
		
		private $int = 1; // プロパティ
	}

	// Aを継承したクラス
	class D extends A{
		// トレイトB,Cを使用
		use B, C{
			// 被っているメソッドfugaはBを使用
			B::fuga insteadof C;
		}
		
		// @Override
		public function foo(){
			print('クラスDのメソッドfoo');
		}
		
		// トレイトのprivateを参照可能
		public function getInt(){
			print($this->int);
		}
	}
		
		// 優先順位は自分自身 > trait > 基底クラス
		$d = new D();
		$d->hoge(); // トレイトBのメソッドhoge
		$d->fuga(); // トレイトBのメソッドfuga
		$d->foo();  // クラスDのメソッドfoo
		$d->getInt(); // 1
interfaceではメソッドの定義しか行えずロジックは書けませんでした。
クラスとはひとつしかextendsできないため、extends A, B, Cができませんでした。
トレイトを使うことによってこれらの問題点を解消し、ロジックを書いたうえで複数extendsのようなことを行うことができるようになります。

トレイト内のprivateな値も参照できていることから、普通のextendsより強い結びつきということがわかります。
実際はもっと単純に、useしたtraitは全部合わせてひとつのクラスと看做すと考えればよいでしょう。
要するにもうPartial classってことでいいよね。


PR


2013/06/21 23:37 | Comments(0) | PHP
AuraPHP 1.0.1 Aura.Http
Aura.Httpは、HTTPリクエストを行ったりするライブラリです。
実体はCURLのラッパですが、CURLが無かったときは自力でリクエストしてくれるみたいです。
あとheader()等ブラウザに返すレスポンスも出力できるようです。

ということで早速使ってみようとしたのですが、とりあえずコンストラクタが異様にめんどいです。
こんなのサンプルがないと絶対わからんわ。
なんでAura\Http\Message\Factoryを2回も使っているのでしょうか?
これについては素直にinstance.phpを使った方がよいでしょう。
ていうか何故instance.phpの自動インクルードはないのでしょうか。

インクルードしてしまえば使用方法自体は非常に簡単です。
使ってみましょう。
<?php
	require_once('path/to/channel/vendor/autoload.php');

	// Aura.Http
	$http = require_once('path/to/channel/vendor/aura/http/scripts/instance.php');
	
	// リクエスト
		$request = $http->newRequest();
		$request->setMethod(Aura\Http\Message\Request::METHOD_GET);
		$request->setUrl('http://example.com/hoge.php');
		// BASIC認証
		$request->setAuth(Aura\Http\Message\Request::AUTH_BASIC)
			->setUsername('user')->setPassword('pass');
		
		// 送信実行
		$stack = $http->send($request);
	
	// 返り値はSplStackだが必ず[0]
		// 本文
		$body = $stack[0]->getContent();
		// ステータス
		$statusCode = $stack[0]->getStatusCode(); // 200
		$statusText = $stack[0]->getStatusText(); // OK
		
		// レスポンスヘッダのリスト
		$headers = $stack[0]->getHeaders();
		// Content-Lengthヘッダ
		$contentlength = $stack[0]->headers->{'Content-Length'}; // Aura\Http\Header
		
		// Cookie
		$stack[0]->getCookies(); // Aura\Http\Cookie\Collection
		// PHPSESSID
		$stack[0]->getCookies()->PHPSESSID; // Aura\Http\Cookie
		
	// 2回目のリクエスト
		$request2 = $http->newRequest();
		$request2->setUrl('http://example.com/fuga.php');
		// セッション引き継ぎ
		$request2->setCookies($stack[0]->getCookies());
		
		$stack2 = $http->send($request2); // ここでエラー
……エラーになりました。
どういうことだよ。

Array to string conversionというNoticeが発生します。
発生箇所はAura\Http\Adapter\Curl.phpです。
一回目のsend()の時点のデータが、その後newRequest()で新しいリクエストを取得したのにも関わらず残ってるのですよね。

これを回避するには、再度ややこしいコンストラクタを使って完全に新たなHTTPオブジェクトを作らないといけないっぽいです。
せっかくのnewRequest()意味なし。
うーむ、Auraは素晴らしいフレームワークだ、って話自体が微妙なことになってきたような気がしないでもないような。


AuraPHPの記事



2013/06/17 23:48 | Comments(0) | PHP
買ったものリスト 2013/06/16

ハームフル・ビューティフル1 高崎 ゆうき
☆☆☆

世間ではエロ漫画家が次々と殺されている。
そんなさなか、身分を隠してエロ漫画を描いている主人公の元に 「貴方の秘密知ってます」の一文が。
いったいこれはミステリなのかサスペンスなのか……!?

と面白そうな素材なのですが、描写がとっちらかっててどうにも見辛いです。
あと普通に主人公が死んだうえでリスタートするというくだりは本当に必要だったのかと。
それが本当に意味のある伏線だったらごめんなさいするしかありませんが、しかし1巻の展開を見る限りでは必要性のあるものだとは全く思えませんでした。
実際のところはどうなのでしょうね。


スーパーSISTERみお3 こいずみ まり
☆☆☆

残念な方のこいずみまり成分が多めの完結編。
主人公と妹の仲は何も変わらずのままで、周囲の話がメインとなっています。
タイトル何処行ったって感じです。
あと、終盤の例によって分量間違ったかのような超展開はなんなのだ。


ベン・トー 9.5 箸休め ~濃厚味わいベン・トー~ アサウラ
ベン・トー10 恋する乙女が作るバレンタインデースペシャル弁当350円
☆☆☆☆

9.5は短編集、10は本編という分類ではありますが、内容としては10も短編集のようなものです。
食べ物の描写については本当に凄いものがありますが、それに加えて佐藤や白粉の妄想も達人レベルに達しつつあり、色々と近付くのが危険なことになりつつあります。
あと、ついに白梅が狼の世界を知ってしまうことになったのですが、何か大きな展開があるかと思えばずいぶんあっさり流されました。
ところでHP部の話の主軸はまったく進まなかったのですが、10巻の最後でようやく進展がありました。
今後一体どこに向かうのでしょうか。


不思議系上司の攻略法1 水沢 あきと
☆☆

おまえら本当に社会人か?
残念な行動や描写が多すぎる。
対決シーンとか本当は盛り上がる場所のはずなのに、違法手段を取ったにも関わらずまさかの徒手空拳とかねえよ。
というか根本的な話として、SEに副業は物理的に無理だ。



2013/06/16 20:56 | Comments(0) | 買ったもの
AuraPHP 1.0.0-beta1 Aura.Filter
Aura.Filterは、名前のとおりフィルタリングを行います。
とりあえず最大の問題点を挙げておくと、使用するフィルタを手動で登録しないといけません。
デフォルトで用意されているフィルタについてもです。
Zend_Filterのようなオートロード機構もありません。
デフォルトのコンストラクタはこんなことになっています。
$ruleCollection = new \Aura\Filter\RuleCollection(
	new \Aura\Filter\RuleLocator([
		'alnum'                 => function() { return new Rule\Alnum; },
		'alpha'                 => function() { return new Rule\Alpha; },
		'between'               => function() { return new Rule\Between; },
		'blank'                 => function() { return new Rule\Blank; },
		'bool'                  => function() { return new Rule\Bool; },
		'creditCard'            => function() { return new Rule\CreditCard; },
		'dateTime'              => function() { return new Rule\DateTime; },
		'email'                 => function() { return new Rule\Email; },
		'equalToField'          => function() { return new Rule\EqualToField; },
		'equalToValue'          => function() { return new Rule\EqualToValue; },
		'float'                 => function() { return new Rule\Float; },
		'inKeys'                => function() { return new Rule\InKeys; },
		'int'                   => function() { return new Rule\Int; },
		'inValues'              => function() { return new Rule\InValues; },
		'ipv4'                  => function() { return new Rule\Ipv4; },
		'max'                   => function() { return new Rule\Max; },
		'min'                   => function() { return new Rule\Min; },
		'regex'                 => function() { return new Rule\Regex; },
		'strictEqualToField'    => function() { return new Rule\StrictEqualToField; },
		'strictEqualToValue'    => function() { return new Rule\StrictEqualToValue; },
		'string'                => function() { return new Rule\String; },
		'strlenBetween'         => function() { return new Rule\StrlenBetween; },
		'strlenMax'             => function() { return new Rule\StrlenMax; },
		'strlenMin'             => function() { return new Rule\StrlenMin; },
		'strlen'                => function() { return new Rule\Strlen; },
		'trim'                  => function() { return new Rule\Trim; },
		'upload'                => function() { return new Rule\Upload; },
		'url'                   => function() { return new Rule\Url; },
		'word'                  => function() { return new Rule\Word; },
	])
);
なんとも残念な感じです。
Composerのオートロードは諦め、instance.phpをインクルードするのがよいでしょう。

名前はフィルタですが、実際はバリデーションとフィルタを同時に行います。
<?php
	// Aura.Filter
	$filter = require_once('path/to/channel/vendor/aura/filter/scripts/instance.php');
	
	// 失敗したら全フィルタリングを即打ち切り
	$filter->addStopRule('a', $filter::IS, 'alnum');
	$filter->addStopRule('a', $filter::FIX, 'int');
	
	// 失敗したら該当の値は打ち切り、他は続ける
	$filter->addHardRule('b', $filter::IS, 'email');
	$filter->addHardRule('b', $filter::FIX, 'alpha');
	
	// 失敗しても続ける
	$filter->addSoftRule('c', $filter::IS, 'bool');
	$filter->addSoftRule('c', $filter::FIX, 'blank');
	
	// フィルタ実行
	$data = array( 'a'=>'a1', 'b'=>'hoge@example.jp', 'c'=>'c3' );
	$success = $filter->values($data); // false
	
	// $dataは直接書き換えられる
	// array( 'a'=>1, 'b'=>'hogeexamplejp', 'c'=>NULL )
	
	// 失敗時に原因を取得
	$filter->getMessages();

Aura\Filter\RuleCollectionにバリデーションとフィルタのルールを与え、最後に値をvalues()で渡すという形でフィルタリングを行います。
values()は参照渡しになっているので、与えたデータが直接変更されます。
返り値はバリデーションとフィルタが成功したらtrue、ひとつでも問題があればfalseとなります。
失敗時の原因は別途getMessages()で取得します。

ルールの与えかたは3種類あります。
addSoftRule()は、該当のルールでバリデーションが失敗しても、失敗を記録するだけで次のルールに進みます。
基本的にこれを使うことが多いでしょう。
addHardRule()は、失敗したら同じ値に対してその後のルール適用は行いません。
例の場合、'email'判定に失敗したら、'alpha'への変換を実行しない、となります。
それ以外の値、上記では'a'や'c'については影響を及ぼしません。
addStopRule()は、失敗した時点で全てのフィルタリングを即座に中止します。

これらは第二引数に与える値によって挙動が変化します。
まずバリデーションとして、RuleCollection\ISであれば===、IS_NOTは!==、IS_BLANK_ORは===もしくはNULLです。
次にフィルタとして、FIXであれば正規表現による置換、FIX_BLANK_ORであれば置換、ただし''などはNULLにする、となります。
基本的にはRuleCollection\IS等でバリデーションだけを行い、電話番号欄に数値以外があったらRuleCollection\FIXで数値を削除といったふうに追加でフィルタリングを行うという運用になるでしょう。
ルールはコンストラクタを見るとわかるとおり、最初から30種類ほど用意されているので、大抵はそれらを使うだけで事足りるはずです。

なお、Aura.Filterはあくまで入力値に対するフィルタリングを行うだけなので、値をHTMLやSQLに渡す際のエスケープはもちろん別途行わなければなりません。
入力値フィルタでhtmlspecialchars()やmysqli_real_escape_string()を行うのは大間違いなので行わないようにしましょう。
もちろんその手のフィルタは最初から存在しません。


AuraPHPの記事



2013/06/14 23:35 | Comments(0) | PHP
AuraPHP 1.0.0 Aura.Autoload
Aura.Autoloadは、名前のとおりオートローディングを扱います。
自作ライブラリなどをオートロードするのに使えます。
クラス名さえ規則的に決めていれば、その後一切のrequire_once()が不要になります。
<?php
	require_once('path/to/channel/vendor/autoload.php');
	
	// Aura.Autoloader
	$loader = new \Aura\Autoload\Loader();
	// spl_autoload_register
	$loader->register();
	
	// デフォルトではinclude_pathが対象
	$foo = new Foo(); // ./Foo.php
	
	// クラス名がBarで始まる場合、↓をベースディレクトリにする
	$loader->add('Bar', '/dir1');
	$bar = new Barbara(); // /dir1/Bar.php
	
	// ネームスペースHogeで始まる場合、↓をベースディレクトリにする
	$loader->add('Hoge\\', '/dir2');
	$fuga = new Hoge\Fuga(); // /dir2/Hoge/Fuga.php
	
	// 個別に指定
	$loader->setClass('Piyo', '/dir3/baz.php');
	$piyo = new Piyo(); // /dir3/baz.php
	
	// 指定クラスのフルパスを取得
	$exist = $loader->find('Hoge\Foo\Bar'); // 存在しなければfalse
	
	// ロード済のファイルを取得
	$loaded = $loader->getLoaded();
	
	// spl_autoload_unregister
	$loader->unregister();

オートロードを有効にするには、基本的にファイル名=クラス名とすることが前提となります。

単にregister()するだけでも、include_pathからファイルを探してくれます。
add()メソッドで、クラス名の接頭辞、ネームスペースで抽出し、該当の条件であれば特定のディレクトリから探すという設定が可能になります。
ネームスペースが切ってあった場合、自動的にディレクトリを掘って探します。
これはAuraの命名規則と同じ構造となります。

setClass()は完全に特定のクラスを呼び出すとき専用で、クラス名とは別のファイル名を指定可能です。
まあ、こっちはrequire_once()と変わらない気もしますが。

このように、クラス名の取り決めさえしておけば一切インクルードを書かなくても済むようになる、非常に便利なAura.Autoloadでした。

しかしAuraそのものはオートローディングをComposerに任せていてAura.Autoloadを使っていないというこの現実。


AuraPHPの記事



2013/06/12 23:25 | Comments(0) | PHP
AuraPHP 1.0.0 Aura.Router その3
前回前々回とURLをパースしてルーティングを行いましたが、逆にルートからURLを作成することも当然可能です。
<?php
	require_once('path/to/channel/vendor/autoload.php');
	
	// Router
		$router = new Aura\Router\Map(
			 new Aura\Router\DefinitionFactory()
			,new Aura\Router\RouteFactory()
		);
	
	// ルート
		$router->add('date1', '/{:year:(\d+)}/{:month:(\d+)}/{:day:(\d+)}', array(
			'values' => array( 'controller' => 'date', 'action' => 'read' )
		));
		$router->add('date2', '/{:year}{:month}{:day}', array(
			'params' => array( 'year' => '(\d\d\d\d)', 'month' => '(\d\d)', 'day' => '(\d\d)' )
		));
	
	// ルートからURLを生成
		$router->generate('date1', array(
			'year'=>'2013', 'month'=>'01', 'day'=>'02'
		)); // '/2013/01/02'
		
		$router->generate('date2', array(
			'year'=>'2013', 'month'=>'01', 'day'=>'02'
		)); // '/20130102'
generate()メソッドに必要な情報を与えると、URLの具体的な値として帰ってきます。
あとは返り値にリンクするだけで、翌日翌月次の記事といったリンクが作成可能です。
url_for()が簡単にできました。


AuraPHPの記事


2013/06/10 22:44 | Comments(0) | PHP
買ったものリスト 2013/06/09

迷宮街クロニクル2 散る花の残すもの 林良介
迷宮街クロニクル3 夜明け前に闇深く
迷宮街クロニクル4 青空のもと道は分かれ
☆☆☆

基本的にこの手の作品は好物なので高得点になりがちなのですが、それでも本作は微妙だ。
なんのかんの言いつつ中断もせずに読み通したので面白くないということはないのは確かですが、それでも楽しいとは思えませんでした。
原因ははっきりしていて、主人公の造形に全く魅力を感じることができなかったところです。
なんかこう全体が気に入らないんだよな。
目的も意志もなく、それなのに覚悟だけはできている。なんだそれ。
その覚悟も、死を覚悟していない人を軽蔑していたのに、いざ自分はとなったらあれである。
なんともがっかりですよ。

あとゴンドラな、地上から穴開けたら駄目なのか?


2999年のゲームキッズ上 渡辺 浩弐
2999年のゲームキッズ下
☆☆☆☆☆

あれー、1999年や2000年ほど覚えている話が多くなかった。
というかほとんど覚えてない。
年を取ると昔のことばかり思い出すのじゃよー。

個々の話自体は相変わらずのブラックユーモアたっぷりのディストピアですが、本作では多くの作品が基本的にひとつの世界観を共有している点がこれまでとは違います。
正直なところその世界観にあまり目新しいところを感じられないのが残念ではあります。
これまでどおり単品の話もあり、それらのクオリティは相変わらずなので十分に元は取れる名作です。


2013/06/09 22:01 | Comments(0) | 買ったもの
今週の実績 2013/06/09
2013/06/06の実績

怒首領蜂 最大往生

真璃亜の完 20
真璃亜でクリアしました。(Arcade HD・Ver.1.5・Novice)

コンプリート 30
3キャラ(朱理、光、真璃亜)でクリアしました。(Arcade HD・Ver.1.5・Novice)

更なる上達への道 25
3面までを2コンテニュー以内でクリアしました。(Arcade HD・Ver.1.5)

上達への道 15
2面までをノーコンテニューでクリアしました。(Arcade HD・Ver.1.5)

思わぬ花火! 5
オートボムを発動させました。(Arcade HD・Ver.1.5・Novice)

桜夜の完 20
桜夜でクリアしました。(Xbox 360)

全力中の全力! 10
自機変形後、ハイパーを使いました。(Xbox 360)

朱理の完 20
朱理でクリアしました。 (Arcade HD・Ver.1.5・Novice)

朱理 5
朱理を選択しました。 (Arcade HD・Ver.1.5・Novice)

真璃亜 5
真璃亜を選択しました。(Arcade HD・Ver.1.5・Novice)

2013/06/03の実績

怒首領蜂 最大往生

地下通路を越えて 25
5面をクリアしました。 (Arcade HD・Ver.1.5・Novice)

光の完 20
光でクリアしました。 (Arcade HD・Ver.1.5・Novice)

5000HIT 30
5000HITを達成しました。(Arcade HD・Ver.1.5・Novice)

良いボムしてるね! 5
ボムを使いました。(Arcade HD・Ver.1.5・Novice)

拾蜂億点 20
スコアが18億点に到達しました。(Arcade HD・Ver.1.5・Novice)

郊外を越えて 20
4面をクリアしました。 (Arcade HD・Ver.1.5・Novice)

住宅地を越えて 15
3面をクリアしました。 (Arcade HD・Ver.1.5・Novice)

1000HIT 15
1000HITを達成しました。(Arcade HD・Ver.1.5・Novice)

ハイパー! 5
ハイパーを使用しました。(Arcade HD・Ver.1.5・Novice)

蜂億点 15
スコアが8億点に到達しました。(Arcade HD・Ver.1.5・Novice)

水源地を越えて 10
2面をクリアしました。 (Arcade HD・Ver.1.5・Novice)

GET 5
ボムアイテムを取得しました。(Arcade HD・Ver.1.5・Novice)

市街地を越えて 5
1面をクリアしました。 (Arcade HD・Ver.1.5・Novice)

スタンバイ 5
ハイパーシステムをスタンバイさせました。(Arcade HD・Ver.1.5・Novice)

光 5
光を選択しました。 (Arcade HD・Ver.1.5・Novice)

輝く蜂は蜜の味 25
MAX HITが10000以上のときに蜂アイテムを取得しました。(Xbox 360)

大錬金! 15
ダブルアタックで弾消しの発生する敵を撃破しました。(Xbox 360)

MAXハイパー! 10
Lv10ハイパーを使用しました。(Xbox 360・Arcade HD・Ver.1.5・Novice)

大往生直前 10
ダブルアタックを使ってエネルギーを0まで減少させました。(Xbox 360)

命を削る力 25
ダブルアタックを1プレイ中に30秒以上使いました。(Xbox 360)

徹底的に剥いてやる!1 15
1面ボスのパーツを全て破壊しました。(Xbox 360)

出撃します! 5
ゲームをプレイしました。 (Xbox 360・Arcade HD・Ver.1.5・Novice)

桜夜 5
桜夜を選択しました。(Xbox 360)


2013/06/09 20:13 | Comments(0) | 実績
PHP5.4.7 PHPでフィボナッチ数F38を求める
http://d.hatena.ne.jp/satosystems/20121228/1356655565
こちらのサイト、多種の言語でフィボナッチ数F38を求めています。
PHPは85.417秒と、残念ながらかなり遅い方です。
これを最適化してみましょう。
<?php
	
	// by satosystems
	// http://d.hatena.ne.jp/satosystems/20121228/1356655565
	function fib1($n){
		if ($n < 2){ return $n; }
		return fib1($n - 2) + fib1($n - 1);
	}
	
	// by Dan Kogai
	// http://blog.livedoor.jp/dankogai/archives/50958771.html
	function fib2($n){
		if($n < 2){return $n;}
		return fib2_sub(1, 1, $n);
	}
	function fib2_sub($a, $b, $c){
		if ($c <= 2){ return $a; }
		return fib2_sub($a+$b, $a, $c-1);
	}
	
	// by NurseAngel
	function fib3($n){
		$fib0 = 0;
		$fib1 = 1;
		$ret = 0;
		for($i=0; $i<$n; $i++){
			$ret = $fib1;
			$fib1 = $fib0 + $fib1;
			$fib0 = $ret;
		}
		return $ret;
	}
	
	// by C言語による最新アルゴリズム事典
	function fib4($n){
		return floor( pow((1+sqrt(5))/2, $n) / sqrt(5) + 1/2 );
	}

関数処理時間F(38)の値
fib1()34.29149秒39088169
fib2()0.00005秒39088169
fib3()0.00002秒39088169
fib4()0.00002秒39088169

fib1はフィボナッチ数列の定義そのものです。
何も考えずに実装したらこうなることでしょう。
しかしこちらは、計算時に自分自身を2回呼び出します。
つまり引数が1増えるにつれ、fib1()を呼び出す回数がおよそ2倍になります。
計算量はO(2n)となり、効率の非常に悪いオーダーです。
もうfib1(100)なんて求めようとすると、反応がなくなってしまいます。


fib2は少々わかりにくいですが、上から順ではなく下から計算しています。
fib2_sub()の1回目に与えている1,1という引数は、順にF2、F1の計算結果です。
あとはfib2_sub()の再帰呼び出しで計算します。
fib2_sub()の2回目の引数はF2+F1つまりF3、F2、数値の37です。
fib2_sub()の3回目の引数はF3+F2つまりF4、F3、数値の36です。
…と順に下っていき、最後のfib2_sub()の引数はF38、F37、数値の2となります。

これによって引数が1増えても、fib2()の呼び出しは1回しか増えません。
計算量はO(n)となり、劇的に改善どころかとんでもない速度になりました。
というかこの時点で早すぎてfib2(38)では計算する意味がないレベル。
fib2(1000)でも余裕で計算可能です。


正直既にこの時点で終わりでいいんじゃね、という気もしますが、よく見てみたらfib2_sub()の再帰って実は計算には全く使わず、ループ回数をカウントしてるだけです。
カウントしてるだけならfor()でいいだろう、ということでfib3()です。
こちらも単純に下から足してるだけで、やってることはfib2()とほぼ同じです。
ただ再帰の関数呼び出しが無くなったせいか、速度もさらに上がっています。

ぱっと見ループを1回削れそうな気がしますが、削ろうとするとfib3(0)あたりの計算がうまくいかないのであえてこうしています。
ifで分岐すると却って遅くなるようでした。


さて、実は再帰もループも使わずにフィボナッチ数を一発で求める公式が存在します

Fn = ( φn - (-φ)-n ) / sqrt(5) = [φn / sqrt(5) + 1/2 ]
ただしφは黄金比

といってもn乗とかの計算は出てきますけどね。
ルートとか割り算とか入ってるくせに計算すると必ず自然数になるとか意味がわからない。
計算量はO(1)でいいのかな、これ?

早すぎてfib3()と違いが分かりませんが、F2000とかを求めようとするとfib4()のほうが早くなるようです。
どちらにしろ0.1秒以下なので実用上はほとんど変わらないレベルですが。
まあともかく、結論としては、フィボナッチ数を求めるアルゴリズムでfib1()だけを書いてるサイトは投げ捨ててしまえ、ってことでいいですかね。






2013/06/07 23:58 | Comments(0) | PHP
AuraPHP 1.0.0 Aura.Router その2
前回、'index.php/2013/1/2/3'でルーティングした際にはcontrollerやactionがありませんでした。
これでは'index.php/a/b/1'の場合と揃えて、
    $controller = new {$route->values['controller']};
    $controller->{$route->values['action']};

とか書けません。
そこでパラメータやパース方法については別途設定することができます。

<?php
	require_once('path/to/channel/vendor/autoload.php');
	
	// Router
		$router = new Aura\Router\Map(
			 new Aura\Router\DefinitionFactory()
			,new Aura\Router\RouteFactory()
		);
	
	// パラメータの追加
		$router->add(
			 'date1'
			,'/{:year:(\d+)}/{:month:(\d+)}/{:day:(\d+)}'
			,array('values' => array(
				'controller' => 'date', 'action' => 'read'
			))
		);

	// パース方法を別途設定
		$router->add(
			 'date2'
			,'/{:year}{:month}{:day}'
			,array('params' => array(
				'year' => '(\d\d\d\d)', 'month' => '(\d\d)', 'day' => '(\d\d)'
			))
		);

	// パース
		$route = $router->match($_SERVER['PATH_INFO'], $_SERVER);
	
		// 'index.php/2013/1/2' でアクセスした場合
		$route->name; // date1
		$route->values; // array('controller'=>'date', 'action'=>'read', 'year'=>'2013', 'month'=>'1', 'day'=>'2')
	
		// 'index.php/20130102' でアクセスした場合
		$route->name; // date2
		$route->values; // array('year'=>'2013', 'month'=>'01', 'day'=>'02')
まずadd()の使用方法の拡張をふたつ。

前者はadd()の第三引数にvaluesを指定しています。
match()で引っかかったときに、valuesを指定した値も一緒に帰ってくるようになります。
URLにコントローラやアクションを指定せずとも、任意のコントローラに振り分けることができるようになりました。

後者は、URLの形式と正規表現を別々に指定しています。
こちらの表記の方が、普通の正規表現なのでわかりやすいと思います。

最後、ブログの閲覧、更新など複数のルーティングを一括登録する方法です。
<?php
	// ルーティンググループの登録
	$router->attach('/blog', array(
		'routes' =>array(
			 'blog_top' => '/'
			,'blog_edit' => '/{:id:(\d+)}/edit'
			,'blog_read' => array(
				 'path' => '/{:id}{:format}'
				,'params' => array(
					 'id'     => '(\d+)'
					,'format' => '(\.json|\.atom)?'
				)
				,'values' => array(
					'format' => '.html'
				)
			)
		)
	));
	
	// パース
		$route = $router->match($_SERVER['PATH_INFO'], $_SERVER);
		
		// 'index.php/blog/' でアクセス
		$route->name; // blog_top
		$route->values; // array('action'=>'blog_top')
		
		// 'index.php/blog/1' でアクセス
		$route->name; // blog_read
		$route->values; // array('action'=>'blog_read', 'format'=>'.html', 'id'=>'1')
		
		// 'index.php/blog/1/edit' でアクセス
		$route->name; // blog_edit
		$route->values; // array('action'=>'blog_edit', 'id'=>'1')
sfDoctrineRouteCollectionみたいな便利おまとめルートはないので結局個別に設定が必要ですが、これでブログの作成/閲覧ルーティングがひととおりできあがりました。

#全然関係ないけどSymfonyは今まで使ったことがあるFWの中で最も使いにくい


AuraPHPの記事



2013/06/05 23:20 | Comments(0) | PHP

<<前のページ | HOME | 次のページ>>
忍者ブログ[PR]