PharDataクラスは、Pharをextendsしているのでpharの関連機能かと思いきや、実はphar全く関係なしに使うことができる圧縮ファイル操作クラスで、どっちかというとZipArchiveの仲間です。
またPharのようにphp.iniを設定することなく使用することができます。
とりあえず適当なzipファイルに対して使用してみます。
<?php
//コンストラクタ
$pharData = new PharData('hoge.zip',
FilesystemIterator::CURRENT_AS_FILEINFO | FilesystemIterator::KEY_AS_FILENAME
);
//zip内のファイルを順に辿る
foreach($pharData as $key=>$val){
//FilesystemIterator::KEY_AS_FILENAMEを指定しているので$keyはファイル名になる
print($key);
//FilesystemIterator::CURRENT_AS_FILEINFOを指定しているので$valはPharFileInfoクラスになる
print(get_class($val));
}
//zipにファイル追加
$pharData->addFile('mushroom.gif');
$pharData->addFile('mushroom.gif', 'mushroom2.gif');
//zipのファイル削除
$pharData->delete('mushroom.gif');
unlink('phar://hoge.zip/mushroom2.gif');
PharDataのコンストラクタの例にはCURRENT_AS_FILEINFOとかKEY_AS_FILENAMEとかいう謎の定数が書かれているのですが、これらは実際には定義されていません。PharData extends Phar extends RecursiveDirectoryIterator extends FilesystemIteratorとなっており、FilesystemIterator::CURRENT_AS_FILEINFOとかFilesystemIterator::KEY_AS_FILENAMEとかのクラス定数が定義されているのでこれらを設定することができます。
http://www.php.net/manual/ja/class.filesystemiterator.php#filesystemiterator.constants
あとはPharData::addFile()で圧縮ファイルを解凍せずにファイルを追加したり、PharData::delete()で削除したりといった操作を簡単に行うことができます。
ちなみにforeachとかに使うインデックスはオブジェクト作成時に作成したらそのままらしく、addFile()後にループしても出てきません。
それはまだいいのですがdelete()後にforeachするとFatal errorになります。
Fatal error: Uncaught exception 'RuntimeException' with message 'Cannot access phar file entry '/hoge.gif' in archive 'C:/hoge.zip''
まあ正直素直にZipArchive使っておけば、という気がしないでもない。
世界最大の個人情報流出+2ヶ月のオンライン停止
http://www.sony.co.jp/SonyInfo/News/Press/201105/11-0527/
PS3用ソフト2タイトル+PSPソフト2タイトル
XBOX
10000円値下げ
http://game.watch.impress.co.jp/docs/20020515/xbox.htm
コントローラ、ソフトなどからどれかひとつ
XBOX360
2週間のオン不安定、停止
http://bb.watch.impress.co.jp/cda/news/20715.html
Undertow 800ゲイツ(約1000円)
3DS
10000円値下げ
http://www.nintendo.co.jp/info110728/index.html
FCのVC10タイトル+GBAのVC10タイトル 約10000円相当
どう見ても任天堂が一番の大盤振る舞いです。
そもそも値下げでの補填自体XBOX以来の滅多にないことですし。
ということで買ってきました。
一万値下げごときよりVCだろ、どう考えても。
これで任意のソフトが選べるのであれば最高だったんだけどさすがにないか。
同時購入ソフトは言うまでもなくゼルダ、あと前から気になってたんですが買う機会がなかったゴーストトリックをついでに買ってきました。
今のところ他にほしいソフトがいまいち見当たらないのが残念ですが、まあVCだけでも当分遊べるだろうからいいでしょう。
ちなみに3DS本体の購入者アンケートには「VCの残りはソーラーストライカーかXを入れてくれ」って書いたんですがまあ無理じゃろうなあ。
なお時オカにはサントラ引換券がついてきました。
何故同梱じゃないのかはいまいちわかりませんが、普通の価格でサントラ付きっていいですね。
ファミ通XBOX360 2011年9月号
☆☆☆☆
今月は売上5桁ソフトが4本もあるよ!やったね!
うん、さみしすぎるのでみんなもっと買おうぜ。
特集としてプラコレ100本記念に前プラコレタイトルリスト、クロレビ特典付き紹介がありました。
8月は発売本数が少なめなので、夏休みにトロピコ以降するものがないなんてときにちょっと過去を振り返ってみるといいかもしれません。
おまけはGoW3の超かっこええ折り込みポスター。
だがコール、ベアードよりアーニャの方が大きいとはどういうことだ。
幻の女 ウイリアム・アイリッシュ
☆☆☆☆
いやあ、見事に騙された。
ちょっとヒントの後出しが一部あるので推理しろと言われても困りますが、読んでる間は気になりません。
あとほんの少しのところまで辿り着いた目撃者、証言者、キーパーソンが次々と事故死してしまい、一体何が、そしてこの後どうなるのかという期待感で飽きさせません。
そして最後に一気に明かされるミステリとしての謎解きは見事でした。
が、しかし一体なんなんだそのオチは。
その展開は本当に必要だったのかと。
Test Drive Unlimited 2
インスタントチャレンジでインスタントマネー! 20
インスタントチャレンジで$10,000を獲得
レポーター 30
全撮影ポイントで撮影
2011/07/29の実績
HALF-MINUTE HERO SMNC
優しき勇者 10
サーシャを倒さずに「呪いと勇者」をクリア
2011/07/28の実績
Test Drive Unlimited 2
トレジャーハンター! 25
トレジャーハントでのボーナスカー全6台を所有
HALF-MINUTE HERO SMNC
勇者30 20
勇者30をクリアした
2011/07/24の実績
HALF-MINUTE HERO SMNC
女神の戦士 10
シングルプレイヤーモードで1回のクエストで女神に通算3000G捧げた
この利用法、Phar::webPhar()あたりをよく読めば書いてあるのですが、物凄く便利っぽい機能にもかかわらず何故か何処にもこれを使ってみたという人が見あたらない不思議。
まあとりあえずでっちあげてみたのがこちら。
http://blog.cnobi.jp/v1/blog/user/8f14c19eb01af9c2e80c7f2ad07dc8ca/1311957002
中身は昔作った超適当なフォームなのでソースの参考にしてはいけませんが、以下の3ファイルが入っています。
input.php
<?php
//初期化
header("Content-Type: text/html; charset=UTF-8");
error_reporting(E_ALL ^ E_NOTICE);
$shimei = '';
$mail = '';
$sex = '';
//引数を確認
if($_REQUEST['comp']){
//引数があれば入力チェック
$shimei = $_REQUEST['shimei'];
$mail = $_REQUEST['mail'];
$sex = $_REQUEST['sex'];
$error_message = '';
if(empty($shimei)){ $error_message.= "氏名が入力されていません<br />";}
if(empty($mail)){ $error_message.= "メアドが入力されていません<br />";}
if($sex!=1 && $sex!=2){$error_message.= "性別が入力されていません<br />";}
if($error_message){
//エラーがあれば戻る
require_once('phar://index.phar/input.tpl');
exit();
}else{
//エラーがなければ保存して終了
file_put_contents('form.txt', $_REQUEST, FILE_APPEND);
require_once('phar://index.phar/comp.tpl');
exit();
}
}else{
//引数が無ければ入力画面
require_once('phar://index.phar/input.tpl');
exit();
}
input.tpl
<?php if($error_message){print('<div style="color:red;">'.$error_message.'</div>');} ?>
<form method="POST" action="<?php print(htmlspecialchars($_SERVER['PHP_SELF'])); ?>">
氏名:<input type="text" name="shimei" maxlength="64" value="<?php print(htmlspecialchars($shimei)); ?>"><br />
メアド:<input type="text" name="mail" maxlength="64" value="<?php print(htmlspecialchars($mail)); ?>"><br />
性別:
<input type="radio" name="sex" value="1"<?php if($sex==1){print(" checked");} ?>>男
<input type="radio" name="sex" value="2"<?php if($sex==2){print(" checked");} ?>>女<br />
<input type="submit" name="comp" value=" 登録 ">
</form>
comp.tpl
投稿を受け付けました。<br /> ご協力ありがとうございましたこのファイルをひとつぽんとサーバ上に置くだけでフォームが完成という、配布などに非常に便利な機能となっています。
ちなみにこのpharファイルの作成方法は以下のようになっています。
<?php
$phar = new Phar('index.phar', 0);
$phar->addFile('input.php');
$phar->addFile('input.tpl');
$phar->addFile('comp.tpl');
$phar->setStub('<?php
Phar::webPhar("index.phar", "input.php" );
__HALT_COMPILER(); ?>');
いやあ、__HALT_COMPILER();なんて初めて使ったよ。Phar::webPhar()が、pharアーカイブを直接呼び出しで利用できるようにするフロントコントローラです。
このメソッドを呼んでおくと$_REQUESTとかの処理を適切に割り振って、pharアーカイブ内でそのまま使用できるようにしてくれます。
第二引数の'input.php'を指定すると、index.pharが呼ばれたときにアーカイブ内の'input.php'が実行されるようになります。
このPhar::webPhar()をセットしているPhar::setStub()はローダスタブをpharアーカイブにセットするメソッドです。
で、そのローダスタブって何なのかというと、今回のようにpharファイルが直接呼び出された、あるいはrequire_once('phar://index.phar')と直接pharアーカイブがインクルードされた際に自動的に実行される部分です。
前回までのようにpharアーカイブ内の一部ファイルだけを呼び出した際には実行されません。
ちなみにデフォルトだと、phar未対応のPHPでpharをエミュレートする機能を追加し、その後自動的にアーカイブ内の'index.php'を実行してくれます。
Pharクラスにはなんかすごい数のメソッドが詰まっていて一見よくわからないのですが、実際使うメソッドはほとんどありません。
Phar::getModifiedとかどんなときに使うんだよって話ですよ。
まず必要なのはphp.iniの設定変更。
pharの作成を公開サーバで行う必要は皆無なので、デフォルトでは禁止されています。
phar.readonly = 0
phar.require_hash = 0
を設定することでpharアーカイブの作成が可能になります。
http://php.net/manual/ja/phar.configuration.php#ini.phar.readonly
では作成。
<?php
$phar = new Phar('TestClasses.phar', 0);
$phar->addFile('TestClass1.php');
$phar->addFile('TestClass2.php');
$phar->addFile('TestClass3.php', 'subdir/filename.php'); //別名で保存
$phar['TestClass4.php'] = file_get_contents('TestClass4.php'); //配列形式でも保存可能
$phar->addFile('mushroom.gif'); //PHP以外も保存可能
ファイル'TestClasses.phar'に5ファイルを詰め込みました。実に簡単ですね。
完成したものが、前回使用したpharファイルになります。
いったん作ったpharアーカイブは、普通のファイルと同じようにファイル操作関数で操作が可能です。
<?php
require_once('phar://TestClasses.phar/TestClass1.php');
require_once('phar://TestClasses.phar/TestClass2.php');
require_once('phar://TestClasses.phar/subdir/filename.php');
require_once('phar://TestClasses.phar/TestClass4.php');
print(file_get_contents('phar://TestClasses.phar/mushroom.gif'));
画像ファイルをrequire_once()したりすると当然エラーになります。Phar::addFile()の第二引数を指定すると、指定した別名で保存できます。
呼び出しすときも別名での指定となります。
またPhar::addFile()のかわりに、$phar['TestClass4.php']のように配列でも保存可能です。
今回はテスト用のどうでもいいデータでしたが、実際に活用されているものとしてはgo-pear.pharがあります。
まあこれXAMPPに入ってるやつは動かないんですけど。
画像はこちらのフリー素材を使用させていただきました。
http://www.lovecandied.com/
そしたらヨドバシの近くでなんかデモ行進をやってました。
てっきり原発反対デモなんだろうなあと思ってたら最初に聞こえたのが「戦争反対!」
このタイミングで反米とは珍しいなあ、と思ったら次の発言が「革命起こせ!」
な ん だ そ れ は
わずか2秒で戦争肯定とはミリデレ大先生も裸足で逃げ出す驚きの一貫性だ。
あまりに珍妙なそのフレーズが強烈すぎて、それ以外に何を主張していたのか全く記憶に残っていません。
結局何のデモだったんだろう。
やおよろっ!4 なつみん
☆☆☆☆
週刊サンデーからクラブサンデーに左遷されながら細々続いていたやおよろっ、目標のわずか0.001%であるところの94人目にして打ち切り。
序盤の意味不明のシュールさがよかったんだけど最終刊では何故か意味不明な感動巨編に。
いやまあこっちも好きなんですけどね。
しかしよく考えてみたら蚊って。
波打際のむろみさん3 名島 啓二
波打際のむろみさん4
☆☆☆☆
これまでの人魚のイメージをぶち壊す酒飲み人魚、むろみさんと愉快な仲間たちによる謎漫画。
既にもう隠れる気無いだろうってレベルで露出しまくってるんですが何故か世間には知られていないみたいです。
主人公が冷静沈着なせいでなかなか展開はありませんが、ほんのちょっとだけ重い話もさらっと出てきたりして今後どうなるのか展開に目が離せないところです。
中間管理職刑事 秋月りす
☆☆☆
どう見てもいつもの課長と田中さんです。
そんなミスマッチにも程があるキャストでお送りする謎のハードボイルド刑事漫画。
殺人課という最も危険な課を扱っているにもかかわらず、いつも通りのどこかユルい秋月りす節が炸裂します。
なんか後書きで失敗作扱いされたとか書いてあるんだけどそんなことはないと思うぞ。
ITサービスマネージャ本試験問題
午後の重点対策がもう少しで読み終わるので、次の一冊として本試験問題と予想問題集どちらを買おうか店頭で検討。
立ち読みしてみたところ、なんと予想問題集には午後2の回答例が載っていないという致命的欠陥が発覚。
本試験問題の購入と相成りました。
重点対策にも本試験問題の一部が例題として出ているのでわりと重複になってしまうのが微妙ですが、まあやらないよりはマシでしょうということで。
Test Drive Unlimited 2
エクスプローラ 50
5000km(3107マイル)走破
イージーマネー 10
F.R.I.M.で$100,000獲得
2011/07/21の実績
Test Drive Unlimited 2
ゴッド オブ カー 50
購入可能な車をすべて所有
カーティスト 15
5つの車に装飾
戴冠 75
すべてのチャンピオンシップとカップに勝利
チューニングマニア 5
車を最大までチューニングする
2011/07/20の実績
メモリーズオフ ゆびきりの記憶
ハッピーバースデーちなつ 3
ちなつの誕生日にゲームをした。
Test Drive Unlimited 2
高速そして最高級 10
5秒間400km/h(249mhp)で走行(任意のゲームモード)
2011/07/18の実績
Test Drive Unlimited 2
サブプライムショック? 30
各レベルの家を1件ずつ所有
コクピットマニア 20
コクピットビューで500km(311マイル)を走破(任意のゲームモード)
http://php.net/manual/ja/phar.using.intro.php
あとpharでググってもマニュアルのコピペサイトと「PHP5.3ではpharという機能が使えるぜ!」みたいな記事ばっかりで、実際に使ってみたという話が全然出てきません。
どういうことなんですかね。
仕方ないのでここで実際に使ってみます。
pharとは、要するに単に複数のファイルをひとつにまとめられるというだけのことみたいです。
概念としては、zipみたいに複数のファイルをひとつに固めておいて、使うときに特定のファイルだけ取り出すというイメージでしょうか。
というか実際にpharとzipの変換とかもできたりします。
とりあえず使ってみましょう。
こちらに簡単なpharファイルを用意しました。
中には5つのファイルがありますが、4つはこんな中身のないクラスです。
TestClass1.php
<?php
public static function getClassName(){
function getClassName(){
return __CLASS__;
}
}
もうひとつは画像ファイルです。ではこれを読み込んでみます。
<?php
require_once('phar://TestClasses.phar/TestClass1.php');
require_once('phar://TestClasses.phar/TestClass2.php');
print(TestClass1::getClassName());//"TestClass1"
print(TestClass2::getClassName());//"TestClass2"
非常に簡単です。'phar://'はpharストリームラッパーで、これからpharファイルを指定することを示しています。
次の'TestClasses.phar'がpharファイル名、最後の'TestClass1.php'がpharアーカイブ中の具体的にインクルードしたいファイル名となります。
このように、pharアーカイブは一見ひとつのファイルですが実質的に複数のファイルとして取り扱うことができ、ファイルをまとめて配布したいときなどに便利です。
ちなみに中を見ればわかりますが基本的に単なるテキストなので、プログラムの隠蔽には使えません。
ところでpharってなんて読むんですかね。ぴゃー?
DOMはいったんDOMElementにしてしまうと元のHTMLに戻すのが何故か大変、SimpleXMLはアバウトなHTMLを読み込んでくれない、XMLパーサは使い方がやたらややこしい、と一長一短というか一短一短です。
そもそも何れもXML用であってHTML用ではないので当たり前かもしれませんが。
HTMLの誤りを修正するためのツールとしてTidyというものが存在しますが、どういうわけかPHPから利用することが可能です。
で、これがHTMLのパーサとしてもわりと優秀です。
さすがにDOMDocument::getElementById()ほどの便利メソッドはありませんが、比較的簡単にHTMLを掘っていくことが可能です。
とりあえず作成。
<?php
//HTMLを取得
$html = file_get_contents('http://yuubiseiharukana.blog.shinobi.jp/Entry/501/');
//Tidy
$tidyConfig = array('indent' => true, 'output-xhtml' => true, 'wrap' => 200);
$tidy = new tidy();
$tidy->parseString($html, $tidyConfig, 'utf8');
//<body>を取得
$tidyBody = $tidy->body();
//本文を取得
//CSS上のパス:html body div#whole div#contents div#main div div.entry_table div.entry_text
$tidyText = $tidyBody->child[1]->child[4]->child[1]->child[1]->child[0]->child[1];
print($tidyText);
Tidyのコンフィグはここらへんに一覧がありますが、いまいちなんなのかよくわかりません。よくわからないのでサンプルのまま使用しています。
あとはTidyオブジェクトに対してHTMLタグの入れ子の順番を指定するだけで、非常に簡単に本文を取得できます。
とはいえ、例では番号を直接指定しているのですが実はあまりよくない方法です。
何故ってchild[1]やchild[4]は、単にノード内の要素を上から順に数えた値なので、タグをひとつ追加されるだけでずれてしまうのです。
本当はXPathやCSSパスで指定するのが安全なのですが、残念ながらそのような機能はないようです。
ということで子ノードを順に取得してひとつひとつ確認していくしかありませんが、ところが何故かTidyはforeachやcount()が使えません。
従ってたとえば子ノードのうち特定のタグを取得したい場合は以下のように書く必要があります。
<?php
//Countable、Traversable
count($tidyBody); //必ず1になる
foreach($tidyBody as $key=>$val){
//$tidyBody[0]のプロパティのループになってしまう
}
//<div id="whole">を取得
$loop = 0;
while(1){
$tmp = $tidyBody->child[$loop];
$loop++;
if(!$tmp){break;}
if($tmp->id !== TIDY_TAG_DIV){continue;}
if($tmp->attribute['id'] !== 'whole'){continue;}
$tidyWhole = $tmp;
break;
}
//<div id="contents">を拾う
$loop = 0;
while(1){
$tmp = $tidyWhole->child[$loop];
$loop++;
if(!$tmp){break;}
if($tmp->id !== TIDY_TAG_DIV){continue;}
if($tmp->attribute['id'] !== 'contents'){continue;}
$tidyContents = $tmp;
break;
}
ちょっとどうなんだって気がする。あとUndefined propertyのNoticeが出るのも微妙。
ふと思ったが、TidyでXHTML化してSimpleXMLに突っ込んだ方が早くない?という気がしてきた。
これまで使ってたやつがホイールが誤動作を起こすようになり、下スクロールしようとしても上に行ったりで操作が困難になってきました。
マウス売り場とか久々に見たんですが、前マウスを買ったときは無線のほうがレアな存在だった気がするのですが今やすっかり無線が主流なんですね。
買ったのはロジクールのM510。
実は初めての無線マウス。
価格のわりに高級っぽいかんじで、どこでも操作できるのは非常に便利ですね。
ちょっと左ボタンのストロークが大きいのと、前使ってたのより少し小さめなのが気になりますが、かなり満足な出来。
しかしうっかりどこかで紛失してしまいそうだ。
ほんとにあった霊媒先生5 松本 ひで吉
ほんとにあった霊媒先生6
ほんとにあった霊媒先生7
ほんとにあった霊媒先生8
☆☆☆☆
ほんとに女性だったとはびっくりだ。
女性でこの絵でこの漫画ってのにさらにびっくりだ。決して第一線で活躍する名選手とは言えませんが、脇を固める名脇役的ポジションの作品です。
あんまり持ち上げすぎて壊れたりすることなく地味に続いていってほしいものです。
ってかそれ以前に月刊少年ライバル自体聞いたことないので本誌が先に終わらないか心配ですが。
ところで初期は4コマだった気がするんだが、いつのまにか普通のストーリー形式になってきてるな。
バード -最凶雀士VS天才魔術師1 青山 広美,山根 和俊
☆☆☆
麻雀漫画の最高傑作バードが今現代に蘇……らなくてよかったのに。
ゴドフリーは萌え女になってるしバードは氷の本性を隠そうともしてないし、そしてなにより得体の知れない不気味な恐ろしさを持っていた蛇がただの変態に成り下がってやがる。
よくあるがっかリメイク、駄リメイクの狭間に本作も迷い込んでしまいましたとさ。
まあつまらないって力説するほどつまらないというほどでもないので原作を読んだことがなかったら読んでもいいかもっていうかそれより原作を再版してください。