配列にフィルタリングして必要な値だけ取り出す

2009/05/08 | PHPの基本

配列を処理するならたいていの場合foreachだ。ループ処理するのが簡単。でもPHPでは配列を処理するための関数がいろいろ用意されている。常識的に考えれば、それらの関数を使ったほうが早く動作するはず。

array_filterという関数を見つけた。というか前から興味を持っていた関数だ。配列をループ処理し、各値の要不要を判断して間引いてくれる関数だ。この間引き処理で、foreachを使うよりarray_filterのほうがどのくらい早くなるのか試してみた。

(1) foreachの場合
$filtered=array();
foreach($values as $value){
  if($value[‘age’]>3){
    $filtered[]=$value;
  }
}

(2) array_filterの場合
function age($value){
  if($value[‘age’]>3){
    return true;
  }else{
    return false;
  }
}
$filtered=array_filter($values,’age’);

と二つのサンプルで比べてみた。結果・・・foreachのほうが倍くらい早かった。おいおい。なんでだろ。(2)だと関数を読んでるから遅くなるのかな。

simpleXMLはnamespaceに注意

2009/04/23 | XML

simpleXML関数が便利、ということを以前に確認した。これでウェブサービスを使ったサイト構築がずいぶんと簡単になった。しかし今日問題にぶち当たった。

「AmazonウェブサービスにRESTでリクエストを投げ、受け取ったXMLをsimpleXMLに放り込んで、XpathでXMLツリー構造内を検索して配列にする」ということをやりたかった。実際そのように記述してみたけど結果はNG。最後の配列が空になってしまう。なぜ。

$xmlObj =simplexml_load_string($xml);
$items=$xmlObj->xpath(‘//Item’);
var_dump($items);

楽天ではこんな感じで取得できた。楽天のときは、タグ名に「:(コロン)」があってうまく処理できずとまどったが、Xpathを使って切り抜けることができた(というかXMLをたどらなくていいのでこちらのほうが簡単)。今回も例にならってXpathをつかったけど、うまくいかなかった。理由はどうもnamespace(タグ内にxmlnsとかってかいてあるアレ)のようだ。楽天のときはnamespaceがなかったので問題が出なかっただけ。で、書き直した。

$xmlObj=simplexml_load_string($xml);
$nsArray=$xmlObj->getNamespaces();
$ns=array_shift($nsArray);
$xmlObj->registerXPathNamespace(‘amazonns’,$ns);
$items=$xmlObj->xpath(‘//amazonns:Item’);
var_dump($items);

Xpathを使用する際、namespaceが定義されている場合は、「namespaceはこれですよ」と登録しないといけないようだ(登録するときに適当に名前「amazonns」をつける)。Xpathで検索をかけるときは、その名前を使い、名前の配下のタグを検索させるような構造になるようだ。

とりあえず、これで結果を取得することはできた。しかし、やっぱりXMLの奥は深そうだ。

インタラクティブなプログラムを作る

2009/03/26 | CLI

PHPはウェブのためだけの言語ではなくて、コマンドラインからも実行することができるし、Windowsのexeファイルだって作ることができる(納品したことがある)。

PHPでコマンドラインから起動するプログラムを作るのに、インタラクティブに動作するプログラムを作らないといけない案件をもった。インタラクティブなプログラムとは、プログラム中で何らかの入力を促されるような、対話形式のプログラムを指す。そういえば昔N88ベーシックでそういうのがあったなぁ、と懐かしく思い出したけれど、PHPではどうやったらできるんだっけ。でも調べたら、やっぱりできることがわかった(コマンドライン版というくらいなんだから、それくらいできないと・・・)。

ob_end_clean();
echo(‘Input your name: ‘);
$name=fgets(STDIN); 
echo(‘Your name is “‘.$name.'”‘);

ミソはSTDIN。通常はfopenする等したリソースをfgets関数の引数として与えるのだが、そこをSTDINと標準入力からの入力待ち状態にしてやるとよい。あと1行目。バッファリングをonにしていると、プログラム終了まで何も出力されない(表示=プログラム終了)ので、順次表示するようにしてやる。

すっきり。

Smartyテンプレート内でPHPスクリプトを書くときに

2009/03/16 | Smarty

すでにテンプレート内でロジックを書くということ自体がいけないのだが、それでもどうしてもやらなければいけないときがある(というかそのほうがソースがきれいになる)。

Smartyは専用タグを使うPHPのテンプレートエンジンだけど、テンプレートの中にPHPプログラムを直接書くこともできる(書かないでいいものなら書かないほうがいい)。例えばこんなふうに。

{php}
print(‘This is PHP script’);
{/php} 

そもそもこういうふうな処理をかかなければならないわけだから、何らかの変数処理というのも必要になるわけだし、変数だってテンプレートにSmarty変数として使用していたものを使いたくなるのも人情だ。そんな場合は、こういう具合に書く。

$smarty->assign(‘myText’,’This is PHP script’);

{php}
print($this->get_template_vars(‘myText’);
{/php} 

プログラム本体内でmyTextという名前でアサインされた変数を、テンプレート内のPHPスクリプトから呼び出す例だ。ミソは「get_template_vars」メソッド。Smarty関数を書くときにも時々使ったりする。これを使って呼び出せばいい。

でも、やらなくてすむのなら、やらないほうがいい。

simplexmlでどうやって値を取得するか

2009/03/12 | XML

simplexmlでいろいろお試し中。現時点では「タグにコロンが含まれていた場合」の挙動を除けば快適に使えているのだが、少しだけ困った問題が起こった。問題自体は解決できたのだが、それに気づくまでちょっと時間がかかってしまったのと、スマートなやり方でないような気がしたのでちょっとメモ。

xml内の特定のタグでくくられた「値」を取得するのに、以下のように記述した。

$xmlObj =simplexml_load_string($result);
$status=$xmlObj->Header->Status;
var_dump($status);

個人的には’Success’とか’Error’とかの文字列を期待したのだが、出力された結果はこんな感じ。

object(SimpleXMLElement)#4 (1) { [0]=> string(7) “Success” }

オブジェクトが返された。まぁ、これはこれでいいのだけれど、このときに’Success’という文字列を取得する方法がわからなくて困った。「$status->0」なんてしてもやっぱり取得できない。でも、不思議なことに「print」すると「Success」と表示される。なぜ。

結論から言うと、strval($status)とすることで文字列を取得できた。これってスマートな方法なんだろうか。他に関数とか用意されていないのかな。後述の「printすれば」というとこをは理解できた。自動的に型変換されて出力されていたわけ(自動変換はいい場合もあれば、事を複雑にする可能性もあることを実感)。

ま、とりあえず、できた。


守谷市(まちの情報ポータル) 無料アンケートレンタルjpForm.net