忍者ブログ
[PR]
×

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



2025/01/16 09:20 |
PHP5.4.4 イテレータ関数
イテレータに対して何かする関数があったので使ってみる。
<?php
	// 適当なサンプル
	Class Sample implements IteratorAggregate{
		private $hide = array( 'hide1', 'hide2' );
		private $show = array( 'show1', 'show2' );
		/**
		* @Override
		* イテレータを取得する
		* @return ArrayIterator $this->showのイテレータ
		*/
		public function getIterator(){
			return new ArrayIterator($this->show);
		}
	}
	$sample = new Sample();
	
	// イテレータから配列にする array ( 0 => 'show1', 1 => 'show2' )
	$array = iterator_to_array($sample);
	var_export($array);
	
	// これと同じ
	$array = array();
	foreach($sample as $key=>$val){
		$array[$key] = $val;
	}
	
	// オブジェクトのカウントはCountableを実装しないと正しくない →1になる
	print(count($sample));
	
	// 要素数を正しく取得できる →2
	print(iterator_count($sample));
	
	// 全要素でcallbackFunctionをコール…のつもりだったのだが何故か両方ともshow1になる
	iterator_apply($sample->getIterator(), 'callbackFunction', array($sample->getIterator()));
	
	// 一度イテレータを変数に取り出さないと何故かうまく動かない
	$iterator =  $sample->getIterator();
	iterator_apply($iterator, 'callbackFunction', array($iterator));
	
	/**
	* イテレータの現在値をprintするだけ。
	* @param Iterator イテレータ
	* @return boolean true
	*/
	function callbackFunction(Iterator $value){
		print($value->current());
		return true;
	}
iterator_to_array()はイテレータから配列に変換する、iterator_count()はイテレータの要素数を数えるという関数です。
正直count()のデフォルトがiterator_count()でいい気がするのですがどうでしょう。

iterator_apply()はイテレータの全要素に対してユーザ関数を適用するというもので、array_walk()と似たようなものです。
ただなんか与える引数がめんどくさいんですよね。
ノートにも書かれていますが、第一引数のイテレータはループに使うだけで中身は無視されます。
単純に第三引数をなくして第一引数にするとかでは駄目だったのでしょうか。
PR


2013/03/27 22:34 | Comments(0) | PHP
Zend Framework2.1.3 Zend\Stdlib\DateTime
Zend\Stdlib\DateTimeはPHPデフォルトのDateTimeクラスの拡張です。

追加されるメソッドはただひとつ、createFromISO8601()だけです。
<?php
	header('Content-type: text/html; charset=UTF-8');
	require_once('path/to/channel/vendor/autoload.php');
	use Zend\Stdlib\DateTime;
	
	// 'Y-m-d\TH:i:sO'形式のデータ
	$str = '2013-01-01T10:00:00+0900';
	
	$datetime = DateTime::createFromISO8601($str, new \DateTimeZone('Asia/Tokyo'));
	$datetimeDefault = \DateTime::createFromFormat(\DateTime::ISO8601, $str, new \DateTimeZone('Asia/Tokyo'));

$datetimeDefaultのほうはデフォルトのDateTimeを使ったもので、このふたつは全く同じ値になります。

違いはというと、DateTime::ISO8601のフォーマットは'Y-m-d\TH:i:sO'なのですが、それとは微妙に違う'Y-m-d\TH:i:s.uO'形式のデータを与えた場合にも正常にパースするようになります。
ってどうでもよすぎる。
一体なんのために存在するんだ、これ。


全然関係ないが忍者ブログの編集画面が変化して死ぬほど使いづらくなった。



2013/03/22 23:43 | Comments(0) | PHP
Minecraft1.4.7 ArsMagica 5.37.006 その4 エッセンスアイテム
前回空気中のエッセンスを用いてアイテムを錬金しました。
今回はこのエッセンスを固着してアイテム化していきます。

神秘の混合物(Arcane Compound)はネザーラック*2、焼石*2、グロウストーンダスト*2、レッドストーン*2。
それを焼くと神秘の灰(Arcane Ash)。


この灰は今後たくさん要求されるのでまとめて作っておきましょう。
ダイヤモンド、神秘の灰、黒曜石*2、木材*5でエッセンス精製装置(Essence Refiner)。
設置すると壮絶に格好いいインベントリが開きます。


中央に神秘の灰を、周囲に規定のアイテムを入れることで動作し、エッセンスをアイテム化してくれます。
エッセンスアイテムは一部の強力な魔法を唱えるのに必要となります。
詳しいレシピはWikiを参照。

さて、他にもエッセンスを消費して何かする機器が幾つかあるので作ってみます。
魔術竈(Calefactor)はVinteumの粉、レッドストーン、ラピスラズリ*2、焼石*4。
神秘の再構成器(Arcane Reconstructor)はダイヤモンド、紫染料*2、焼石*5。


魔術竈は燃料のかわりにエッセンスで焼いてくれる、すなわち燃料不要のかまどです。
神秘の再構成器は武器防具を修理してくれる、金床の上位機種です。
アイテムやモブをどんどん生贄に捧げ、便利な魔道ライフを送りましょう。



マインクラフト1.4のまとめ


2013/03/20 21:13 | Comments(0) | PHP
Minecraft1.4.7 ArsMagica 5.36.040 その2 魔法を使う
前回ファイアボルトを作りました。
同じようにルーンをつかって様々な魔法書を作っていくわけですが、闇雲に当てずっぽうでルーンを当てはめていってもそうそう魔法書が作れるわけではありません。
なにしろ最大9個のルーンを、順番も正しく当てはめないといけません。
しかもこのレシピ、前回のファイアボルトのような基本魔法以外は、ユーザごとにランダムで決まるという特性があり、他者のレシピを聞いても全く意味がありません。

そこで必要となるのが魔法のレシピ。
前回紹介したような建造物やスポーンブロックの宝箱などから手に入ります。
これを使用すると魔法の作り方を覚え、文机のGUI左上のKnown Spellsというところに出てくるようになります。
選択すると、ルーンの置き方がうっすらと表示されるので、あとはそれに合わせて配置すればよいということになります。


あとはできた魔法を手に持って右クリックで使えばいいのですが、ArsMagicaの魔法は何十種類もあるので魔法だけでアイテム欄が埋まりかねません。
それをどうにかするため、呪文書(Spell Book)があります。
レシピは紙*2、糸*3、皮*4。


手に持ってShift+右クリックでインベントリが開き、これまでに作った魔法を収めることができます。
右側は保存スペースで、左側は呪文スロットです。


呪文書を手に持つと左上にスロットが表示されます。
ZXで使いたい呪文を選択し、右クリックで直接使用することができます。

魔法は非常に大量にあるので全部は紹介しきれません。
ここでは特に便利な魔法としてMarkとRecallだけ紹介します。
これはまあベッドとルーラです。

Markを唱えたところがホームとして登録されます。
その後旅に出て、旅先でRecallを使うと一瞬にしてホームに戻ることができます。
ただし、消費MPは距離の2乗に比例して増えるため、あまり遠くだとMPが足りずに帰還できないことがあります。
とりあえず近場で試してみて、MP消費量や、あとは魔法の使い方を練習しておくとよいでしょう。
魔法の中には周囲に被害をもたらす危険なものもあるので注意が必要ですが、MarkとRecallはなんの被害もないので練習に適しています。
慣れたら徐々に他の攻撃呪文なんかも使っていくとよいかもしれません。


マインクラフト1.4のまとめ



2013/03/15 22:45 | Comments(0) | PHP
Zend Framework2.1.1 Zend\Code\NameInformation
執筆時点(2013/02/08)ではヘルプに一切存在しない謎のクラス、Zend\Code\NameInformationを触ってみます。
まあ、他にもヘルプに載ってないものってたくさんあるんですけどね。
<?php
	require_once('path/to/channel/vendor/autoload.php');

	//NameInformation
		$nameInformation = new Zend\Code\NameInformation();
		
	//useから完全修飾名に
		$nameInformation->setUses(array('Zend\Config\Writer'));
		$name1 = $nameInformation->resolveName('Writer\Ini');
	
	//namespaceから完全修飾名に
		$nameInformation->setNamespace('Zend\Config\Reader');
		$name2 = $nameInformation->resolveName('Ini');
出力結果。

string(22) "Zend\Config\Writer\Ini"
string(22) "Zend\Config\Reader\Ini"


どうも本気でただこれだけのクラスのようです。
setNamespace()とかsetUses()とか名前が付いていますが、実際にネームスペースやuseを設定してくれたりするわけではないようです。
まあ、そんなものどうやって設定するんだって話ですが。

なお、上記では実在するクラスを指定していますが、非実在クラスを指定しても特にエラーが出たりはしません。
ファイルやクラスの存在をチェックしたりはせず、単に格納して取り出しができるだけのようです。
正直本気で使いどころに困る。


2013/02/08 23:59 | Comments(0) | PHP
Zend Framework2.0.6 Zend\Config\Processor
ZF2にもZend\Configが存在します。
読み込む方のZend\Config\Reader、書き込む方のZend\Config\Writerがありますが、正直使い方はZF1と全く一緒なのでパス。

日本語情報が全く存在しない、ZF2で追加されたとおぼしきZend\Config\Processorという謎クラスがあったので触ってみます。
コンフィグの例はいつものダミーです。
<?php
	require_once('path/to/channel/vendor/autoload.php');
	
	//例
	$conifOption = array(
		'webhost'  => 'www.example.com',
		'database' => array(
			'adapter' => 'pdo_mysql',
			'params'  => array(
				'host'     => 'db.example.com',
				'username' => 'dbuser',
				'password' => 'secret',
				'dbname'   => 'mydatabase'
			)
		)
	);
	
	//Zend\Config
		$config = new Zend\Config\Config($conifOption, true);
	
	//表示
		print($config->database->params->host);
		
	//大文字にするフィルタ
		$processorFilter = new Zend\Config\Processor\Filter(new Zend\Filter\StringToUpper());
	
	//フィルタを通す
		$processorFilter->process($config);
	
	//表示
		print($config->database->params->host);
結果は、
"www.example.com"
"WWW.EXAMPLE.COM"

見事に大文字になってしまいました。

Zend\Config\Processorは、コンフィグに対して全体的に処理を行うことができるようです。

Zend\Config\Processor\Filterは、Zend\Filterのインスタンスを渡すことで、該当の処理をコンフィグ全体に設定可能です。
ユーザ入力値を設定として保存する際にZend\Filter\StringTrimを通したり、Zend\Filter\Encryptを使って暗号化して保存したりといった用途が考えられるのではないでしょうか。

などと無理矢理使い道を考えてはみましたが、正直使うことないよな。


2013/02/01 23:18 | Comments(0) | PHP
Zend Framework2.0 Zend_Validate.php
composerでインストールするとZF2の本体は
vendor/zendframework/zendframework/library/Zend
とかいう変な場所に置かれてしまうわけですが、その近くに
vendor/zendframework/zendframework/resources/languages/ja/Zend_Validate.php
という謎のファイルを発見しました。

中身は単なる配列で、Zend_Validatorなどで使える値が入っているようです。
なんだこれ。
おそらくどこかでオートロードするような機能があるのでしょうが、どうやって使うのが正解なのか全くわかりません。
とりあえず無理矢理読み込んでみます。
<?php
	require_once('path/to/channel/vendor/autoload.php');
	
	//設定
		$validatorOptions = array(
			'translatorTextDomain'=>'ja'
		);
		$translatorOptions = array(
			'translation_files' =>array(
				array(
					'type' => 'phparray'
					,'text_domain'=>'ja'
					,'filename'=>'path/to/channel/vendor/zendframework/zendframework/resources/languages/ja/Zend_Validate.php'
				)
			)
		);
	
	//Ipバリデータ
		$validator = new Zend\Validator\Ip($validatorOptions);
	
	//有効なIPアドレスか
		$isValid = $validator->isValid('192.168.0.256');
	
	//発生したエラーメッセージを取得
		$errorMessages = $validator->getMessages();
	
	//Translatorをセット
		$translator = Zend\I18n\Translator\Translator::factory($translatorOptions);
		$validator->setTranslator($translator);
	
	//再度チェック
		$isValid = $validator->isValid('192.168.0.256');
		$errorMessagesJp = $validator->getMessages();

Fatal error: Class 'Locale' not found in path\to\channel\vendor\zendframework\zendframework\library\Zend\I18n\Translator\Translator.php on line 228

あふん。

Localeは国際化関数に含まれるクラスです。

http://php.net/manual/ja/intl.installation.php
> PHP 5.3.0 以降には同梱されています

php.iniに
;extension=php_intl.dll
という行があり、デフォルトで無効化されていました。
ところがこの行を有効化したら、実際にはファイルが存在するのに「icuuc46.dllが見つからない」とか言われて起動しなくなりました。
原因は不明ですが、xampp\phpにあったicuuc*.dllを片端からxampp\apache\binにコピペしたらなおった。

実行結果。
array(1) {
  ["notIpAddress"]=>
  string(50) "The input does not appear to be a valid IP address"
}
array(1) {
  ["notIpAddress"]=>
  string(53) " 入力値は IP アドレスではないようです"
}
無事日本語化されました。
いやまあ、filenameを直接指定するとか明らかに変なので、ここらへんオートロードでどうにかなるとは思うのですが、よくわかりません。

Zend_ValidateというよりZend\I18nの話だなこりゃ。


2013/01/18 23:59 | Comments(0) | PHP
Zend Framework2.0.6 Zend\Version
Zend\Versionは、現在導入されているZF2のバージョンを確認できます。

このクラスは何故か他と同じ階層に入っていません。
他のZendクラスはvendor/zendframework/zendframework/lib/以下に入っているのに、
こいつはvendor/zendframework/zend-version/に入っています。
他にもzendservice-twitterとかzendrestとか、独立した場所に入っているのが幾つかあるのですがいったいどういう基準なのでしょう。

他と共通ではありませんが、Composerのautoloadは使えるようになっています。
使ってみましょう。
<?php
	require_once('path/to/channel/vendor/autoload.php');
	
	//現在のバージョン
	print(Zend\Version\Version::VERSION);
	
	//Github最新版のバージョン
	print(Zend\Version\Version::getLatest());
	
	//最新版であるか否か
	print(Zend\Version\Version::isLatest());
	
	//引数がGithub最新版より新しければ1、同じなら0、古ければ-1
	print(Zend\Version\Version::compareVersion('2.0.6'));
まあ見てのとおり、使い方は極めて単純です。
これはおそらくComposerでのインストール、バージョンアップの判断に使っているのだろうと思われます。
それ以外で何に使うのかはよくわかりません。
ZF2のバージョン2.0.5以上じゃないと動作しないプログラムがバージョンチェックに使うとかそういうやつでしょうか。


2013/01/11 23:43 | Comments(0) | PHP
Zend Framework2.0.6 Zend\Dom\Query
Zend\Dom\QueryはHTMLをDOMで扱うクラスです。

ZF1.11のZend_Dom_Queryを使いましたが、ぶっちゃけ同じです。

<?php

	//Zend\Dom\Query
		require_once('path/to/channel/vendor/autoload.php');
		$domQuery = new Zend\Dom\Query();
	
	//パース
		$text = file_get_contents('http://framework.zend.com/manual/2.0/en/index.html');
		$domQuery->setDocument($text, 'UTF-8');
	
	//パースしたドキュメントの形式 docXml / docHtml / docXhtml
		print($domQuery->getDocumentType());
	
	//libxml_get_errors
		var_dump($domQuery->getDocumentErrors());
	
	//CSSパスを指定
		$nodeList = $domQuery->execute('body div#main-content-wrapper div#site-content section.manual div#programmersreferenceguideofzendframework2 div#zendframeworkreference div.section h3');
	
	//中身を順に処理
		foreach($nodeList as $key=>$domElement){
			//DOMElementが入ってくる
			print($domElement->firstChild->nodeValue . '<br />');
		}
	
	//CSSパス→XPathに変換できる
		print($nodeList->getXpathQuery());
query()がexecute()にかわったくらいで、ほぼそのまま利用できます。
馴染みがない上にわかりにくいXPathではなく、よく使うCSSパスで扱えるのが非常に便利ですね。

ちなみにこのCSSパスからXPathへの変換、Zend\Dom\Css2Xpathで行われているのですが、なんと100行程度しかありません。
私がやったら1000行くらいかかりそうだ…


2013/01/04 20:44 | Comments(0) | PHP
Zend Framework2.0 Zend\Json
Jsonを気軽に扱えるようになるクラス…ではなく、XMLからJsonに変換するクラスです。
なにしろPHPにはjson_decodeという便利極まりない関数がデフォルト装備されているので、単にJsonを扱うだけのクラスはぶっちゃけ不要なんですよね。
<?php
	require_once('channel/vendor/autoload.php');
	
	$array = array('foo'=>'bar', 1=>2);
	$xml= '<書籍目録> <書名>XML入門</書名> <著者>筒井</著者> <書名>続・XML入門</書名> <著者>小松</著者> </書籍目録>';

	//エンコード
	$json = Zend\Json\Json::encode($array);
	
	//デコード
	$stdClass = Zend\Json\Json::decode($json);
	
	// JSONの整形
	$jsonPritty = Zend\Json\Json::prettyPrint($json, array("indent" => " "));
	
	// XMLからJsonに
	$jsonXml = Zend\Json\Json::fromXml($xml);
	$stdClassXml = Zend\Json\Json::decode($jsonXml);
	
	var_dump($json, $stdClass, $jsonXml, $stdClassXml);
結果。
string(19) "{"foo":"bar","1":2}"

object(stdClass)#2 (2) {
  ["foo"]=>
  string(3) "bar"
  ["1"]=>
  int(2)
}

string(142) "{"\u66f8\u7c4d\u76ee\u9332":{"\u66f8\u540d":["XML\u5165\u9580","\u7d9a\u30fbXML\u5165\u9580"],"\u8457\u8005":["\u7b52\u4e95","\u5c0f\u677e"]}}"

object(stdClass)#3 (1) {
  ["書籍目録"]=>
  object(stdClass)#7 (2) {
    ["書名"]=>
    array(2) {
      [0]=>
      string(9) "XML入門"
      [1]=>
      string(15) "続・XML入門"
    }
    ["著者"]=>
    array(2) {
      [0]=>
      string(6) "筒井"
      [1]=>
      string(6) "小松"
    }
  }
}
めでたくJsonに変換、およびJsonから元に戻すことができました。
簡単ですね。
ただしJsonからXMLに戻すことができないという片手落ちです。なんでだ。

Zend\Json\Jsonと同じ場所にZend\Json\Encoder、Decoderクラスがあり、一見これを使ってエンコードデコードしているように見えますが、実はjson_encodeが存在すればそれを使ってエンコードしています。
json_encodeが存在しない場合のみZend\Json\Encoderを使って自力でエンコードします。
ところでZF2.0の最低要求バージョンはPHP5.3であり、json_encode()はPHP5.2からPHPコアに含まれ標準インストールされます。
つまりZend\Json\Encoder/Decoderクラスは死にクラス。
	Zend\Json\Json::$useBuiltinEncoderDecoder = true;
とするとjson_encode()を使わないようにできますが、ネイティブ関数を拒否してあえて再発明をする理由も見当たらず、存在意義は不明です。

ちなみにJson::encode()に配列ではなくインスタンスを渡した場合、そのクラスにtoJson()メソッドがあればそちらを呼んで返してくれるといった隠し機能もありますが、直接読んだ方が早いので出番はありません。


2012/12/24 21:14 | Comments(0) | PHP

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