PHPは最近の他の言語とは違ってシングルスレッドなので、一回のリクエストで複数の処理を同時に実行したりといったことは通常はできません。
常に上から順に処理を進めていきます。
どうしてもやりたいなら`php hoge.php &`などと別プロセスで動かすといった手段しかありませんでした。
ところでなにやらpthreadsとかいうモジュールを見つけたので使ってみます。
LinuxであればPECLからインストールしましょう。
Windowsではバイナリが落ちてたので拾ってきます。
php_pthreads.dllをエクステンションのディレクトリに、pthreadVC2.dllは環境変数Pathが通っているところに置きます。
そしてphp.iniに以下を記述して再起動。
extension=php_pthreads.dll
これでpthreadsが使用可能になります。
phpinfo()にpthreadsという項目が追加されるのを確認しましょう。
それではさっそく実行。
TestThread::start()は、TestThread::run()を呼び出しますが、その処理の終了を待たずにすぐに次に進みます。
これでスレッド処理が簡単に行えます。
これで並列処理なんかも簡単に書けるようになりましたね。
まあスレッドが必要になるような処理をPHPで書くなよという話ではありますが。
常に上から順に処理を進めていきます。
どうしてもやりたいなら`php hoge.php &`などと別プロセスで動かすといった手段しかありませんでした。
ところでなにやらpthreadsとかいうモジュールを見つけたので使ってみます。
LinuxであればPECLからインストールしましょう。
Windowsではバイナリが落ちてたので拾ってきます。
php_pthreads.dllをエクステンションのディレクトリに、pthreadVC2.dllは環境変数Pathが通っているところに置きます。
そしてphp.iniに以下を記述して再起動。
extension=php_pthreads.dll
これでpthreadsが使用可能になります。
phpinfo()にpthreadsという項目が追加されるのを確認しましょう。
それではさっそく実行。
<?php class TestThread extends Thread{ /** * @Overide * startしたときに呼ばれる */ public function run(){ // 時間のかかる処理 sleep(10); // このスレッドのIDを確認 print($this->getThreadId()); // これを呼び出したスレッドのIDを確認 print($this->getCreatorId()); } } // TestThreadを別スレッドで起動 $testThread1 = new TestThread(); $testThread1->start(); $testThread2 = new TestThread(); $testThread2->start(); $testThread3 = new TestThread(); $testThread3->start(); $testThread4 = new TestThread(); $testThread4->start(); $testThread5 = new TestThread(); $testThread5->start();10秒かかる処理が5個あるということで一見50秒かかりそうですが、実際は10秒で処理が完了します。
TestThread::start()は、TestThread::run()を呼び出しますが、その処理の終了を待たずにすぐに次に進みます。
これでスレッド処理が簡単に行えます。
<?php class TestThread extends Thread{ public function run(){ sleep(10); } } // TestThreadを起動 $testThread = new TestThread(); $testThread->start(); // Thread::run()がまだ走っているか → true var_dump($testThread->isRunning()); // Thread::run()が終了するまで待機 $testThread->join(); // Thread::run()がまだ走っているか → false var_dump($testThread->isRunning());join()はスレッドが終了するまで待機してくれます。
これで並列処理なんかも簡単に書けるようになりましたね。
まあスレッドが必要になるような処理をPHPで書くなよという話ではありますが。
PR
甲賀忍法帖 山田風太郎忍法帖1 山田 風太郎
☆☆☆☆
ニンジャスレイヤーは、すっかり超能力者となってしまった最近のニンジャが、外国人特有の日本観と融合してできあがった現代の申し子なのだ。
……というわけでは全く無かった。
体色を変化させて壁に溶け込んだり、皮膚から相手の精気を吸収したり、体毛が針のように尖って相手を刺し殺したり、等々、どう見ても忍者ではなくニンジャである。
そんな人外大魔境の忍者大戦が発表されたのは1958年。
なんと50年も前から既にニンジャは存在していたのだ。
さて、江戸時代初期を描いた時代小説なのに距離がメートルであったり章タイトルが「甲賀ロミオと伊賀ジュリエット」とかまさにやりたい放題の本作。
時代考証も史実も無視した荒唐無稽な世界観。
こんな適当どこかで見たことありませんか。
そう、山田風太郎こそ、半世紀早かった元祖ラノベ作家なのである。
現代ラノベとは、登場人物がさくさく死んでいくという一点でずいぶんな違いがありますが。
ん?
ということは、現代のラノベも半世紀後には文学として読まれている可能性があったりするのだろうか。
それはラノベ読みの立場としても、なんというか非常に嫌な未来予想図である。
マジカルシェフ少女しずる1 水 あさと
☆☆☆
その場のノリと勢いだけで突き進む、あらゆる意味でバカバカしいナイス極まりない作品。
読み終わった後に何も残らない作品は数あれど、これほど何も残らないことが正しい作品を私は他に知らない。
なんか2巻も出るらしいですが、いやあ、こういうのは単発でいいです。うん。
芦屋さんの猫。1 瀬田 ヒナコ
☆☆☆
レーカンの作者買いだったのですがこちらは微妙。
いやなんかねえ、世界が狭すぎて話が展開しないんだよな。
なんか語る言葉すらも出てこない。
怒首領蜂最大往生 (超限定版) ケイブ
少しだけプレイしましたが、モードによってはよく喋ります。
ギンガフォースもでしたが、わりと好みなのでもっと他のタイトルでもやってほしいですね。
まあ、喋るストーリー系STGでフィロソマに敵うタイトルは未だ出てきていないわけですが。
プレイするとコインが手に入り、壁紙や音楽などおまけが購入できます。
繰り返しプレイのモチベーションになっていいかんじです。
だがどうして壁紙のランダム機能がないんだろう。
シューティングラブ。10周年 ~XIIZEAL & ZEAL~ スペシャルパック トライアングル・サービス
シューティングラブは実績780/1000と、それなりにやりこんでます。
他のSTGに比べると見た目こそどうしても地味なのですが、そのぶんSTGの根幹である「撃つ、避ける」を骨太に味合わせてくれる作品でした。
しかし今はSTGだけでも3つも待ってるから出番がきびしいのう。
オペの部族は全員感染しているそうだ。
残っているのは墓に眠る先祖だけ、ということで墓を暴きに行く。
何故かボートで行くという、どうしてそんな離れたところに墓があるんですかね。
と思いきや、単に元々は別の場所に村があって、今は避難してただけだった。
元の村は既にゾンビで溢れていたため、とりあえず皆殺しにして進む。
耐性を持ってなかった者がこうなり、耐性のあった者は避難していたということか。
オペの部族は、死後の復活を願ってゾンビを食べるらしい。うへえ。
墓に辿り着いたら女が一人倒れていた。
オペが「悪魔だ」とか言って殴りかかろうとしたが、プルナが撃って止めた。
というか撃ち殺した。
ええええええ。
どんな超展開だよ、せめて手で止めろよ。
倒れてた女はイェレマといい、この村の出身ではあるらしい。
噛まれた後もなく、ゾンビの肉も食べていないようです。
ここから村まで戻るのですが、インフェクテッドがやたら大量に襲いかかってきて大変。
後ろに火炎瓶を投げつつダッシュで逃げます。
村に戻ると、何故かモーウェンが襲われていました。
ゾンビ共を蹴散らし、どうにか船まで逃げ帰る。
イェレマは一度村を逃げ出して、町で生活していたことがあるそうです。
そのため他の村人より知識があり、言葉も流暢に話すことができます。
彼女の父親が皆にゾンビの脳を食べるように指示したらしく、皆素直に従ったが、イェレマだけは知識があったので食べなかったらしい。
ん、ということはイェレマの父がオペなのか?
無事彼女を研究所に保護したところ、ホワイト大佐からまた連絡。
絶対モーウェンが知ってるから聞き出して早く来いとのこと。
モーウェンに聞くと、やはり知っていたが、危険だから教えたくなかった、でも2回も助けられちゃしょうがないということだった。
まずは懐かしのモーズビー市街に寄って、ガソリンとタイタスへのプレゼントを回収。
タイタスというのは門番か何かで袖の下を通さないといけないのかね。
どちらも単に運ぶだけで、特に特殊な敵が出てくるわけではないのですぐです。
今度はさらに懐かしい、ジンの父親の工房です。
ここでボートを改造し、そしてジンは父親との決着を付けました。
そしてようやく監獄島へ潜入しようと思った矢先、ホワイト大佐からまた連絡。
「研究所で悲鳴が聞こえた!急げ!」
予想通りというか何というか、研究所が大変なことになっているようです。
急いで研究所に戻ります。
イェレマはどうなった、そしてなによりワクチンはどうなった?
デッドアイランド ZOTY脱出記
残っているのは墓に眠る先祖だけ、ということで墓を暴きに行く。
何故かボートで行くという、どうしてそんな離れたところに墓があるんですかね。
と思いきや、単に元々は別の場所に村があって、今は避難してただけだった。
元の村は既にゾンビで溢れていたため、とりあえず皆殺しにして進む。
耐性を持ってなかった者がこうなり、耐性のあった者は避難していたということか。
オペの部族は、死後の復活を願ってゾンビを食べるらしい。うへえ。
墓に辿り着いたら女が一人倒れていた。
オペが「悪魔だ」とか言って殴りかかろうとしたが、プルナが撃って止めた。
というか撃ち殺した。
ええええええ。
どんな超展開だよ、せめて手で止めろよ。
倒れてた女はイェレマといい、この村の出身ではあるらしい。
噛まれた後もなく、ゾンビの肉も食べていないようです。
ここから村まで戻るのですが、インフェクテッドがやたら大量に襲いかかってきて大変。
後ろに火炎瓶を投げつつダッシュで逃げます。
村に戻ると、何故かモーウェンが襲われていました。
ゾンビ共を蹴散らし、どうにか船まで逃げ帰る。
イェレマは一度村を逃げ出して、町で生活していたことがあるそうです。
そのため他の村人より知識があり、言葉も流暢に話すことができます。
彼女の父親が皆にゾンビの脳を食べるように指示したらしく、皆素直に従ったが、イェレマだけは知識があったので食べなかったらしい。
ん、ということはイェレマの父がオペなのか?
無事彼女を研究所に保護したところ、ホワイト大佐からまた連絡。
絶対モーウェンが知ってるから聞き出して早く来いとのこと。
モーウェンに聞くと、やはり知っていたが、危険だから教えたくなかった、でも2回も助けられちゃしょうがないということだった。
まずは懐かしのモーズビー市街に寄って、ガソリンとタイタスへのプレゼントを回収。
タイタスというのは門番か何かで袖の下を通さないといけないのかね。
どちらも単に運ぶだけで、特に特殊な敵が出てくるわけではないのですぐです。
今度はさらに懐かしい、ジンの父親の工房です。
ここでボートを改造し、そしてジンは父親との決着を付けました。
そしてようやく監獄島へ潜入しようと思った矢先、ホワイト大佐からまた連絡。
「研究所で悲鳴が聞こえた!急げ!」
予想通りというか何というか、研究所が大変なことになっているようです。
急いで研究所に戻ります。
イェレマはどうなった、そしてなによりワクチンはどうなった?
デッドアイランド ZOTY脱出記
前回の続き。
http://bloggdgd.blog28.fc2.com/blog-entry-278.html
http://bloggdgd.blog28.fc2.com/blog-entry-279.html
http://php.net/manual/ja/function.array-splice.php
http://php.net/manual/ja/function.array-merge.php
数々の証言によりarray_merge()よりarray_splice()のほうが早いのは確定的に明らかですが、では実際前回やった測定では何故array_splice()が異常に遅かったのかというお話。
http://bloggdgd.blog28.fc2.com/blog-entry-272.html
http://okwave.jp/qa/q8109749.html
私も全然気付いてなかったのですが、実はarray_flatten2()にはそもそも「フラット化できないことがある」というバグがありました。
ということで
> array_flatten3のarray_mergeをarray_spliceに書き換え
てみました。
array_splice()使ったこと無いからこの使い方が適切なのかはわかりませんが、想定通りarray_merge()より早くなりました。
んで、毎回array_shift()してからarray_splice()って意味ないよな、と少しだけ書き換えてみたのがこちら。
微妙に早くなりましたが、やはりarray_walk_recursive()には全然敵いませんね。
原因は全くわかりませんが、array_flatten2()と同じような気がします。
さて、私の頭ではこれ以上の関数は思いつきませんでした。
再帰を使わずにより早く動作する手段は果たして見つかるでしょうか?
というかarray_flatten2()が遅かった原因は不明のままかよ。
http://bloggdgd.blog28.fc2.com/blog-entry-278.html
http://bloggdgd.blog28.fc2.com/blog-entry-279.html
http://php.net/manual/ja/function.array-splice.php
http://php.net/manual/ja/function.array-merge.php
数々の証言によりarray_merge()よりarray_splice()のほうが早いのは確定的に明らかですが、では実際前回やった測定では何故array_splice()が異常に遅かったのかというお話。
http://bloggdgd.blog28.fc2.com/blog-entry-272.html
http://okwave.jp/qa/q8109749.html
私も全然気付いてなかったのですが、実はarray_flatten2()にはそもそも「フラット化できないことがある」というバグがありました。
ということで
> array_flatten3のarray_mergeをarray_spliceに書き換え
てみました。
<?php function array_flatten7($array) { $tmp = array(); while (($val = array_shift($array)) !== null) { if (is_array($val)){ array_splice($array, 0, 0, $val); }else{ $tmp[] = $val; } } return $tmp; }
関数 | 処理時間 | 展開後の個数 |
---|---|---|
array_flatten7 | 0.16667秒 | 68228 |
array_splice()使ったこと無いからこの使い方が適切なのかはわかりませんが、想定通りarray_merge()より早くなりました。
んで、毎回array_shift()してからarray_splice()って意味ないよな、と少しだけ書き換えてみたのがこちら。
<?php function array_flatten8($array) { $tmp = array(); $array = array_values($array); while (isset($array[0])){ if (is_array($array[0])){ array_splice($array, 0, 1, $array[0]); }else{ $tmp[] = array_shift($array); } } return $tmp; }
関数 | 処理時間 | 展開後の個数 |
---|---|---|
array_flatten8 | 0.14735秒 | 68228 |
微妙に早くなりましたが、やはりarray_walk_recursive()には全然敵いませんね。
<?php function array_flatten9($array) { $array = array_values($array); $i=0; while (isset($array[$i])){ if (is_array($array[$i])){ array_splice($array, $i, 1, $array[$i]); }else{ $i++; } } return $array; }というかもうarray_shift()とか$tmpとか要らなくね、と思って上記のようにしてみたら、こちらは30秒を超える問題外の遅さでした。
原因は全くわかりませんが、array_flatten2()と同じような気がします。
さて、私の頭ではこれ以上の関数は思いつきませんでした。
再帰を使わずにより早く動作する手段は果たして見つかるでしょうか?
というかarray_flatten2()が遅かった原因は不明のままかよ。
関数 | 処理時間 | 展開後の個数 |
---|---|---|
array_flatten5 (array_walk_recursive) | 0.06959秒 | 68228 |
array_flatten1 (iterator_to_array+RecursiveIteratorIterator) | 0.08642秒 | 68228 |
array_flatten6 (foreach+RecursiveIteratorIterator) | 0.11780秒 | 68228 |
array_flatten8 (while (isset($array[0]))) | 0.14735秒 | 68228 |
array_flatten7 (array_shift+array_splice) | 0.16667秒 | 68228 |
array_flatten3 (array_shift+array_merge) | 0.19846秒 | 68228 |
array_flatten4 (再帰呼出し) | 0.32668秒 | 68228 |
array_flatten2 (each) | Maximum execution time of 30 seconds exceeded | |
array_flatten9 ($i++) | Maximum execution time of 30 seconds exceeded |
ZF2では少し便利なSPLの拡張があります。
配列で取り出すメソッド、シリアライズするメソッドが追加されています。
これで便利になったかと思いきや、実はこいつら、全く使いどころがありません。
元々iterator_to_array()で配列に取り出すことが可能でした。
なんでメソッドじゃなくて関数なのかは分かりませんが。
ちなみにtoArray()はiterator_to_array()を使わずforeachで中身を取り出しています。何故か。
で、PHP5.4で素のSPLにserialize()が実装されてしまいました。
さらに困ったことにserialize()の互換性がありません。
つまり、Zend\Stdlib\SplStackとSplQueueを使う必要性が全く無くなってしまったということです。
Zend\Stdlib\SplPriorityQueueについては、何故かまだtoArray()やserialize()が無いので今のところ使い道はありますが、今回のZend\Stdlib\SplStackについては、もはや存在意義が終了したと言っていいでしょう。
では何故紹介した。
<?php require_once('path/to/channel/vendor/autoload.php'); $sample = array(1,2,3,4,5); // キューとスタックの拡張 $queue = new Zend\Stdlib\SplQueue(); $stack = new Zend\Stdlib\SplStack(); foreach($sample as $key=>$val){ $queue->push($val); $stack->push($val); } // 配列に取り出す $array = $queue->toArray(); $array = $stack->toArray(); // シリアライズ $queueSerial = $queue->serialize(); // シリアライズから元に戻す $queue2 = new Zend\Stdlib\SplQueue(); $queue2->unserialize($queueSerial);
配列で取り出すメソッド、シリアライズするメソッドが追加されています。
これで便利になったかと思いきや、実はこいつら、全く使いどころがありません。
<?php $sample = array(1,2,3,4,5); // デフォルトのSplQueue $default = new \SplQueue(); foreach($sample as $key=>$val){ $default->push($val); } // iterator_to_arrayで配列に取り出せる $array = iterator_to_array($default); // 実はPHP5.4で素のSPLにserialize()が実装された $defaultSerial = $default->serialize(); $default2 = new \SplQueue(); $default2->unserialize($defaultSerial); // 互換性はない $default2->unserialize($queueSerial); // UnexpectedValueException
元々iterator_to_array()で配列に取り出すことが可能でした。
なんでメソッドじゃなくて関数なのかは分かりませんが。
ちなみにtoArray()はiterator_to_array()を使わずforeachで中身を取り出しています。何故か。
で、PHP5.4で素のSPLにserialize()が実装されてしまいました。
さらに困ったことにserialize()の互換性がありません。
つまり、Zend\Stdlib\SplStackとSplQueueを使う必要性が全く無くなってしまったということです。
Zend\Stdlib\SplPriorityQueueについては、何故かまだtoArray()やserialize()が無いので今のところ使い道はありますが、今回のZend\Stdlib\SplStackについては、もはや存在意義が終了したと言っていいでしょう。
では何故紹介した。
ずっと前、色々と半端なPear::Text_Figletを紹介しましたが、今回はZend謹製のZend\Text\Figletを使ってみます。
このように文字がAAとして表示されます。
このAAは特にフォントを解析したりているわけではなく、単に辞書ファイルで置換しているだけです。
Pear::Text_Figletと同じ仕組みでした。がっくり。
辞書ファイルはflfという拡張子で規格化されています。
まとめサイトはありますが、やはりというか日本語はありません。残念。
setSmushModeに設定できる値はSM_SMUSH以外にも色々あるのですが、ほとんど変わらないレベルで、正直なんのためにあるのか分かりませんでした。
なんかソースがいまいちZendっぽくない感もあって微妙。
<?php header('Content-type: text/html; charset=UTF-8'); require_once('path/to/channel/vendor/autoload.php'); use Zend\Text\Figlet\Figlet; // Figlet $figlet = new Figlet(); // デフォルト以外のフォントを使用する場合セット $figlet->setFont('roman.flf'); // LEFT/CENTER/RIGHT $figlet->setJustification(Figlet::JUSTIFICATION_LEFT); // 横幅 超えたら改行 $figlet->setOutputWidth(100); // 指定するとstrrev (鏡文字ではない) // $figlet->setRightToLeft(Figlet::DIRECTION_RIGHT_TO_LEFT); // 指定すると余白を詰める // $figlet->setSmushMode(Figlet::SM_SMUSH); // 表示 print($figlet->render('Hello World'));
ooooo ooooo oooo oooo `888' `888' `888 `888 888 888 .ooooo. 888 888 .ooooo. 888ooooo888 d88' `88b 888 888 d88' `88b 888 888 888ooo888 888 888 888 888 888 888 888 .o 888 888 888 888 o888o o888o `Y8bod8P' o888o o888o `Y8bod8P' oooooo oooooo oooo oooo .o8 `888. `888. .8' `888 "888 `888. .8888. .8' .ooooo. oooo d8b 888 .oooo888 `888 .8'`888. .8' d88' `88b `888""8P 888 d88' `888 `888.8' `888.8' 888 888 888 888 888 888 `888' `888' 888 888 888 888 888 888 `8' `8' `Y8bod8P' d888b o888o `Y8bod88P"
このように文字がAAとして表示されます。
このAAは特にフォントを解析したりているわけではなく、単に辞書ファイルで置換しているだけです。
Pear::Text_Figletと同じ仕組みでした。がっくり。
辞書ファイルはflfという拡張子で規格化されています。
まとめサイトはありますが、やはりというか日本語はありません。残念。
setSmushModeに設定できる値はSM_SMUSH以外にも色々あるのですが、ほとんど変わらないレベルで、正直なんのためにあるのか分かりませんでした。
なんかソースがいまいちZendっぽくない感もあって微妙。
レンタルマギカ 魔法使い、貸します! 三田 誠
☆☆
あーもーその秘められた力がなんちゃら系はもういいです。
いや、もっときちんと話が描かれていればいいのですが、それまでほとんど何の描写もなかったくせに脈絡なくいきなり最強とか言われても読者置いてきぼりなわけで、なんかもう勝手にやってください。
長く続いたシリーズみたいですし、今後そういうところが明らかになっていくのかもしれませんが、既にもう続きを読む気力がありません。
どうせ最強やるんだったら11eyesくらいに溜めてからにしてください。
いやあ11eyesは実に良いゲームでした。
かなえルート以外は素晴らしい仕事をしたよ、うん。
そして最後に最大の問題点を指摘しておこう。
レンタルしてねえ
子ひつじは迷わない 走るひつじが1ぴき 玩具堂
子ひつじは迷わない 回るひつじが2ひき
☆☆☆☆
安楽椅子探偵もの、探偵はひねくれた少女、とくればもうテンプレ極まりない作品です。
が、本作の場合持ち込み先が生徒会のお悩み相談室ということもあり、よくある他の探偵もののように殺伐とはしていません。
謎そのものは正直たいしたことがなく、鋭い推理とかそういうのはあまりありません。
というか探偵役より頭の良い人物が普通に出てくる時点で、完全なミステリとしての方向性は放棄されています。
ですがそこらへんのゆるいところが、持ち込まれる相談とちょうど相場が合っている感じです。
恋愛相談にじっちゃんの名を賭けられても困るってものですよ。
相談への応え方も少し変わっており、ホームズ役は論理的に回答そのものを答え、そしてワトソン役がそれを相談相手に対して適切な(とワトソン役が思っている)形で応えるという二段構えになっています。
これによりホームズ役が単純にワトソン役に道を指し示すだけではなく、二人が共に相手に影響を与えていくという物語の深みが出てきます。
まあ深みってほど深い話でもないですが。
あとホームズ役が二人に分かれただけという可能性もないでもないです。
この手の作品には珍しく、探偵側の心理描写が入っているのが面白いところです。
ただ、主人公側のキャラクターが皆起伏が少ないせいで淡々と進んでしまうイメージがあります。
このあたりはもう少しやりようがあったのではないかと思います。
なお全く期待せずに、スニーカー大賞を取ったということも知らずに読み始めたからこの評価です。
大賞だったからという理由で読んだら「まあ悪くはないけど、大賞なのにこの程度?」と思ってしまっていただろうことは間違いなかったところ。
暗号少女が解読できない 新保 静波
☆☆☆
こちらはかわってドタバタハーレムラブコメもののミステリ…というかパズルもの。
縦読みとかそういった折句、文字遊びが中心で、謎は全部解けた!みたいな推理は全くありません。
またパズルそのものも、解けなくても見れば何となくわかる程度です。
なのでミステリとしてではなく、パズルをだしにしたラブコメとして読むといいでしょう。
ラブコメとしてはほどよくまとまっていて、微妙な甘さをそれなりに味わうことができます。
記憶力が無駄にいい設定が最初以外あまり生かされていないのは気になるところです。
ただ、こちらもスーパーダッシュ小説新人賞大賞として読んでいたら「この程度」で終わっていたと思います。
彼女たちのメシがマズい100の理由 高野 文具
☆☆
他の二人はともかく、ヒロインには言ってやれよ。
「レシピ通りに作れ」と。
それだけで大半の問題は解決するはず。
つうか味覚障害は病院に連れて行け。
あと最後の終わり方が最悪でした。
こいつはあれだ、うん、積極的につまらない。
やはり不味い飯の表現では食前絶後に敵うタイトルはないな。
Zend\Text\Tableは、配列からテーブルタグが作れる…わけではなくテキストでテーブルを作ります。
MySQLのコマンドライン出力みたいなやつです。
出力は以下のようになります。
出力はHTMLタグのない純粋なテキストのため、基本的にコンソールやテキスト出力用です。
また、残念ながら幅の自動調整機能がないため、わざわざTable::setColumnWidthsで設定しなければならず面倒です。
あと配列をそのまま突っ込む機能もないようです。
デコレータとして最初からAscii以外にBlankとUnicodeが用意されており、Blankを指定すると罫線のない出力が得られます。
Unicodeはよくわかりませんでした。
しかし一番欲しい人が多いであろうZend\Text\Table\Decorator\Htmlは何故か存在しませんでした。
また、何気に右端左端の'|'と中間の'|'を区別していないという暴挙のため、ちょっと凝ったデコレータを自作しようとしても作成は不可能です。
なんというファッキンな仕様。
微妙に、というか色々と使い辛いZend\Text\Tableでした。
MySQLのコマンドライン出力みたいなやつです。
<?php require_once('path/to/channel/vendor/autoload.php'); use Zend\Text\Table\Column; // テーブル $table = new Zend\Text\Table\Table(); // 設定 // 描画タイプ $table->setDecorator('ascii'); // カラムの横幅は指定必須 $table->setColumnWidths(array(4, 6, 8, 10, 10)); // 行をセット for($i=0; $i<5; $i++){ // 行 $row = new Zend\Text\Table\Row(); // カラムをセット for($j=0; $j<4; $j++){ // カラム $column = new Zend\Text\Table\Column(); // 値 $column->setContent('i:' . $i . ' j:' . $j); // colspan $column->setColSpan(1); // align $column->setAlign(Zend\Text\Table\Column::ALIGN_LEFT); // 行に追加 $row->appendColumn($column); } // カラムを直接行に追加 $row->createColumn('text', array('align'=>Column::ALIGN_CENTER)); // テーブルに追加 $table->appendRow($row); } // 表示 print($table->render());
出力は以下のようになります。
+----+------+--------+----------+----------+ |i:0 |i:0 |i:0 j:2 |i:0 j:3 | text | |j:0 |j:1 | | | | +----+------+--------+----------+----------+ |i:1 |i:1 |i:1 j:2 |i:1 j:3 | text | |j:0 |j:1 | | | | +----+------+--------+----------+----------+ |i:2 |i:2 |i:2 j:2 |i:2 j:3 | text | |j:0 |j:1 | | | | +----+------+--------+----------+----------+ |i:3 |i:3 |i:3 j:2 |i:3 j:3 | text | |j:0 |j:1 | | | | +----+------+--------+----------+----------+ |i:4 |i:4 |i:4 j:2 |i:4 j:3 | text | |j:0 |j:1 | | | | +----+------+--------+----------+----------+
出力はHTMLタグのない純粋なテキストのため、基本的にコンソールやテキスト出力用です。
また、残念ながら幅の自動調整機能がないため、わざわざTable::setColumnWidthsで設定しなければならず面倒です。
あと配列をそのまま突っ込む機能もないようです。
デコレータとして最初からAscii以外にBlankとUnicodeが用意されており、Blankを指定すると罫線のない出力が得られます。
Unicodeはよくわかりませんでした。
しかし一番欲しい人が多いであろうZend\Text\Table\Decorator\Htmlは何故か存在しませんでした。
また、何気に右端左端の'|'と中間の'|'を区別していないという暴挙のため、ちょっと凝ったデコレータを自作しようとしても作成は不可能です。
なんというファッキンな仕様。
微妙に、というか色々と使い辛いZend\Text\Tableでした。
名前のとおり文字列操作を行う、と思いきや実は文字コード変換Wrapperのようです。
strlen()やmb_strlen()、iconv_strlen()といった関数を意識せずに使い分けることができます。
これはStrategyパターンだっけ。
まあ、いつだったかのZend\Math\BigIntegerと同じような内容です。
あとは適当に値を突っ込むだけで自動的に適切な関数を使用して変換や取得を行ってくれます。
文字列操作Wrapperの実体はZend\Stdlib\StringWrapper\StringWrapperInterfaceを実装している何らかのクラスですが、その中身について意識する必要は全くありません。
setEncoding()はStringUtils::getWrapper()の際に呼ばれるので基本的には不要です。
getWrapper()およびsetEncoding()の引数に少し注意が必要で、mb_convert_encoding()などと逆で、前の文字コードから後ろの文字コードに変換します。
strlen()やsubstr()などの文字コードも、setEncoding()の第一引数で指定したものが使われます。
またStringUtils::registerWrapper()で自作のWrapperを登録したりもできるみたいですが、そんな機能使う人なんて滅多にいないだろうからまあいいや。
使い道を無理矢理考えてみるとするならば、文字コード変換ではなく暗号化機能として使うとかでしょうか。
strlen()やmb_strlen()、iconv_strlen()といった関数を意識せずに使い分けることができます。
これはStrategyパターンだっけ。
まあ、いつだったかのZend\Math\BigIntegerと同じような内容です。
<?php require_once('path/to/channel/vendor/autoload.php'); use Zend\Stdlib\StringUtils; // 対応している文字列操作Wrapper一覧 $wrappers = StringUtils::getRegisteredWrappers(); // 引数がUTF-8か $isUtf8 = StringUtils::isValidUtf8('あいうえお'); // PCRE正規表現をサポートしているか $isPcre = StringUtils::hasPcreUnicodeSupport(); // 適切な文字列操作Wrapperを取得 $wrapperClass = StringUtils::getWrapper('UTF-8', 'SJIS-win'); $wrapper = new $wrapperClass(); // 現在の文字列操作Wrapperが対応している文字コード一覧を取得 $encoding = $wrapper->getSupportedEncodings(); // 現在の文字列操作Wrapperが引数の文字コードに対応しているか $isSupported = $wrapper->isSupported('EUC-JP'); // 変換する文字コードを設定 前→後に変換 $wrapper->setEncoding('UTF-8', 'EUC-JP'); // 変換実行 (UTF-8からSJIS-winに) $str = $wrapper->convert('あいうえお'); // その他 $len = $wrapper->strlen('あいうえお'); $sub = $wrapper->substr('あいうえお', 1, 3); $pos = $wrapper->strpos('あいうえお', 'う'); $pad = $wrapper->strPad('text', 10, '埋め', STR_PAD_RIGHT); $wrap= $wrapper->wordWrap('あいうえお', 3, '。', true);StringUtils::getWrapper()に変換したい文字コードを渡すと、対応した文字列操作Wrapperを持ってきてくれます。
あとは適当に値を突っ込むだけで自動的に適切な関数を使用して変換や取得を行ってくれます。
文字列操作Wrapperの実体はZend\Stdlib\StringWrapper\StringWrapperInterfaceを実装している何らかのクラスですが、その中身について意識する必要は全くありません。
setEncoding()はStringUtils::getWrapper()の際に呼ばれるので基本的には不要です。
getWrapper()およびsetEncoding()の引数に少し注意が必要で、mb_convert_encoding()などと逆で、前の文字コードから後ろの文字コードに変換します。
strlen()やsubstr()などの文字コードも、setEncoding()の第一引数で指定したものが使われます。
またStringUtils::registerWrapper()で自作のWrapperを登録したりもできるみたいですが、そんな機能使う人なんて滅多にいないだろうからまあいいや。
使い道を無理矢理考えてみるとするならば、文字コード変換ではなく暗号化機能として使うとかでしょうか。