ZendFramworkの未来
によると、今回、ZendFrameWorkの開発をリードしてくれていたMikeがZend社を去ります。
なんてことが載ってる。
うーん、どうなるんだろう。
SPL関数 ArrayIterator
ArrayIterator と ArrayObject
Javaで言うところの、ArrayList だ
ArrayObjectは、array() 関数で出来るArrayをもう少しObject志向にしたもんだ。
<?php
$array = array( "a", "b", "c" );
$current = current( $array );
?>
は全然オブジェクト指向っぽくない。
これをオブジェクト指向っぽいプログラミングスタイルにする
<?php
$array = array( "a", "b", "c" );
$array = new ArrayObject( $array );
$current = $array->getIterator()->current();
?>
これでオブジェクト指向っぽくなってきた。
ただ、コレではコードが増えただけで、何したいか分からない。
<?php
$array = new ArrayObject( $stdClass->propList() );
$cnt = $arra->count();
?>
もうすこしオブジェクト指向っぽくなった。
foreachに入れてやる。
<?php
$array = new ArrayObject( $stdClass->propList() );
foreach( $array as $value ){
print( $value );
}
?>
わざわざWrapする必要があるのか?
あるんですよ。
たとえば、配列から奇数のIDだけを取り出すとき
<?php
$array = new ArrayObject( $stdClass->propList() );
foreach( $array as $key => $value ){
if( ($key % 2) == 0 )continue;
print( $value );
}
?>
こんなこと書いてたら見通しが悪い。(そう思って)
そんなときは、ArrayIteratorとArrayObjectの該当部分だけを書き換えてやる
<?php
class OddArrayIterator extends ArrayIterator{
public function next(){
if( parent::valid() ){
parent::next();
}
if( parent::valid() == false ){
return;
}
return parent::next();
}
}
$array = array( "a", "b", "c" );
$array = new ArrayObject( $array , 0 , "OddArrayIterator" );
foreach( $array as $value ){
print( $value );
}
?>
この実行結果は、
#takuya php> a c
となり、奇数だけが取得できる。
こうやって適当に拡張していけばいい。
これでソースがスッキリして、見通しが良くなる。
とくにループの中で if や swtich を使って配列を探すときにはこのモデルを使えばスッキリする。
配列から特定の物だけを取り出しつつ配列を取得して処理していく。
GoFモデルでいう、IteratorとVisitorの組み合わせだ。
GoFモデルのようなパターンを簡単に扱えるからSPL関数は便利なのだろう。
SPL関数って便利なんじゃ?
foreach( hoge->getIterator() as $key => $value ){ dosomething(); }
と書くことが出来る。
スッキリする上に、名前空間を汚さない。
PHPの内部Interfaceである。Iteratorと Iterator Aggregateを実装したのがArrayItearorとArrayObjectのペア。
ペアで使うのでわかりにくいか
ArrayObject は java.util.ArrayList のようなものだ
ArrayIterator は java.utl.Iterator(Interface)の様なものだ。
わざわざ配列に入れなくても、簡単にループを回せる。
ディレクトリを再帰的に探すときは
CachingIteratorとDirectoryIteratorをペアにして使う。
----------------------
追記。
デザインパターンが分かってないと辛い。
Iteratorデザインパターンは、知っているだけではしんどい。
Iteratorが使えるか使えないかはAggregateを作れるかどうかだ。
Aggregateが分かったらSPL関数はすぐ理解できた。
さようなら、DB_DataObject。こんにちはPDO
PDO に切り替えた。
PDOの使い方は、java.sqlのパッケージによく似ている。
PDOはプリペアードステートメントを前提に高速処理をするようだ。今のところ使わないけど。
PODの使い方。<br />
postgreSQLでネイティブドライバと比較しながら観てみる
ネイティブドライバ
<?php
$sql = "SELECT * FROM users;";
$dsn = "hoge"
$con = pg_connect( $dsn );
$res = pg_query( $con, $sql );
while( $obj = pg_fetch_object( $res ) ){
$array[] = $obj;
}
pg_free_result( $res );
pg_close( $con );
?>
この結果は
<?php
array[0] = object(stdClass) {
"name":public => "foo";
"tel" :public => "00xx11xx";
}
array[1] = object(stdClass) {
"name":public => "foo";
"tel" :public => "00xx11xx";
}
?>
こんな感じ。pg_fetch_objectすれば、JOINの結果もObjectで返ってくる。<br />
PDOで書くと。
<?php
$sql = "SELECT * FROM users;";
$dsn = "hoge"
$pdo = new PDO( $dsn );
$stmt = $pdo->query( $sql );
$favorites = array();
while( ( $obj = $stmt->fetchObject() ) ){
$array[] = $obj;
}
?>
個人的には、arrayで取り出すより、Objectにする方が好き。Objectだと参照渡しだし。クラス指定できるし。
DB_DATAOBJECTの利点はCreateTableのクラス自動生成と自動生成とJoinのSQL自動生成なんだけど。。複雑じゃなかったら自作した方が早いね。
pdoStatement::fetchObject使えばベースになるOBJECTはすぐ取り出せるわけだし。
range() は便利だぞ
ruby では配列を単純定義できる。PHPでも同じようなことできないか
ruby のソースコード読んでるとうらやましい。
-----------------------------------------------
for i in 0...100
sum = sum + (@barcode.slice(i,1).to_i * (i+1))
end
------------------------------------------------
あんまり意味無いかも知れないけど、forよりタイプ数が少なくて嬉しい。Shift押す回数が減るからね。
<?php
foreach( range(0,9) as $i ){
hoge( $array[$i] );
}
?>
配列に値があるか調べる
配列に値があるか調べる。
配列内に探す文字列があるかどうか。配列内を検索する。
<?php
$dia["先発"] = "普通";
$dia["次発"] = "特急";
$dia["次々発"] = "快速急行";
//特急あるかな?
var_dump (in_array( "特急", $dia ) ); //true
var_dump (array_search("特急", $dia)); //次発
//特急でも快速急行でもどっちかあるかな?
var_dump (in_array( array("特急", "快速急行") , $dia ));//これはできない
var_dump (array_search( array("特急", "快速急行") , $dia ));//これはできない
?>
in_array( array("特急", "快速急行") , $dia )と array_search( array("特急", "快速急行") は
$dia[] = array("特急", "快速急行");を探しに行く
PHPのArray関数は分かりにくい。
Classのメンバ変数(フィールド)に値をセットするとき。引数調べていくのは面倒です。
配列に値があるか調べるには?
配列にキーがあるか調べるには?
<?php
public function loadConfig( $ini_file_name ){
$ret = false;
if(is_exist( $ini_file_name )){
$ret = $this->setConfig( parse_ini_file( $ini_file ) );
}
return $ret;
}
public function setConfig($ini_array){
//配列に値があるか、調べる
if(is_array( $ini_array ) && sizeof( $ini_array ) > 0)
{
//空の要素を含む配列があれば・チ去しておく
$ini_array = array_diff( $ini_array, array( "" ) );
//必須
$indispensables = array( "smarty_dir", "template_dir", "complie_dir", "cache_dir" );
$ret =array_key_exists( $ini_array, $indespensables );
//
return $ret;
}
return false;
}
?>
また、配列にキーが・ðððððZットされていない場合、配列に値がセットされて渡されたかどうか
<?php
public function doSomething( $arg ){
if( ! is_array($arg) ) return false;
$indispensables = array( "smarty_dir", "template_dir", "complie_dir", "cache_dir" );
return in_array( $arg, $indispensables );
}
?>
もうすこし別のやり方があって、
<?php
public function doAnything( $arg ){
return array_search( array( "smarty_dir", "template_dir", "complie_dir", "cache_dir" ), $arg );
}
?>
配列にキーがセットされているか調べる array_key_existsは使わなくてもコーディングできるわけで。
配列演算子を使う。意外と便利。
<?php
if( key($array1) == key($array2){
hoge();
}
?>
(*)配列演算子http://jp2.php.net/manual/ja/language.operators.array.php
array_keys() と key() の違い。[0],[1]などの添え字をkeyと認識するかどうか
http://jp2.php.net/manual/ja/function.key.php
http://jp2.php.net/manual/ja/function.array-keys.php
で、チェックしたIniファイルをクラスにだだだだっと流し込む
<?php
public function __construct( $ini ){
$config = $this->loadConfig($ini);
foreach( $confing as $key => $value ){
$this->$key = $value
}
}
?>
これで、Smartyの設定のためだけにClassを拡張しなくて済みます。
やっぱ設定のためダメにClass拡張ってイメージわかない。
メンバ変数追加や、メソッド追加、を書き換えたいときにExtendsだよなぁ。
と自分ルール決めた。
PHPってThere is more than one way to do it 何よねぇ。
配列の添え字を修正する
PHPの配列は、数字順に並んでいるわけでもないので、便利な様で不便。
<?php
$array = array();
$array[] = "赤星";
$array[] = "関本";
$array[] = "シーツ";
$array[] = "金本";
$array[] = "今岡";
$array[] = "浜中";
unset($array["4"]);
Var_dump::display($array);
?>
と定義すると、Var_dump::display($array)の結果は
Array
(
[0] => 赤星
[1] => 関本
[2] => シーツ
[3] => 金本
[5] => 浜中
)
になる。
連番にならない。困った。for(var$i;sizeof($array)<$i;i++){}でアクセス出来ないよ。
foearchを使えばいいじゃん?確かに。
array_pop(); array_shift();使って配列をStackやQueueでアクセスすればいい。
array_valuesで配列を作り直しもアリだよね。
<?php
$array = array();
$array[] = "赤・ッ";
$array[] = "関本";
$array[] = "シーツ";
$array[] = "金本";
$array[] = "今岡";
$array[] = "浜中";
unset($array["4"]);
$array = array_values($array);
Var_dump::display($array);
?>
結果がコレ
Array
(
[0] => 赤星
[1] => 関本
[2] => シーツ
[3] => 金本
[4] => 浜中
)
これで添え字を修正出来る。unset() 以外に、配列から要素を消す関数があるのかも知れないな。。。