2008年10月20日月曜日

PHPの比較関数と型

empty($a) と is_null($a) が違う結果を返す $a は
$aempty($a)is_null($a)
""TRUEFALSE
array()TRUEFALSE
falseTRUEFALSE
"0"TRUEFALSE
0TRUEFALSE


isset($a) と (boolean) ($a) が違う結果を返す $a は
$aisset($a)(boolean) ($a)
""TRUEFALSE
array()TRUEFALSE
falseTRUEFALSE
"0"TRUEFALSE
0TRUEFALSE


また、isset() と empty() は undefined な変数を評価しても
「Notice: Undefined variable」が発生しないので
緩い評価には「empty()」厳密な評価には「isset()」と
「!演算子」を併用することで使い分けが出来る。

2008年10月15日水曜日

配列への追加(PHP 5)

検証した環境は5.2。

$a = array("a" => 1, "b" => 2, "c" => 3);
$b = array("b" => 20, "c" => 30, "d" => 40);
として

($a + $b) === array("a" => 1, "b" => 2, "c" => 3, "d" => 40)
($b + $a) === array("b" => 20, "c" => 30, "d" => 40, "a" => 1)
array_merge($a, $b) === array("a" => 1, "b" => 20, "c" => 30, "d" => 40)
array_merge($b, $a) === array("b" => 2, "c" => 3, "d" => 40, "a" => 1)
が成立する。

+ 演算子は遠慮がちで、関数 array_merge はわりと強気だというお話。

2008年9月11日木曜日

PEAR HTTP_Client::post()で基本認証

先の「post()」。
ソース見てたらもう一つ引数が取れることに気がつきました。
それがヘッダ。

$header = array(
 'Authorization' => 'Basic ' . base64_encode($user . ':' . $pass)
);
$Client->post($url, $post, $encoded, $files, $header);

とかやると、基本認証が仕掛けられているページでもアクセスできます。
($user, $pass が正しければね)

PEAR HTTP_Client::post()でファイル送信

ここには
integer HTTP_Client::post (
 string $url,
 mixed $data [, boolean $preEncoded = FALSE [, array $files = array()]]
)
とあって、
■string $url
URL を指定します。
■mixed $data
送出するデータを指定します。
■boolean $preEncoded
データがすでに urlencode されているかどうかを指定します。
■array $files
アップロードするファイルを指定します。配列の要素は、 以下の形態であるべきです:array(name, filename(s)[, content type])。 HTTP_Request::addFile() を参照してください。

などと説明がある。実はこれは嘘。
HTTP/Client.phpのソースを当たると

...
foreach ($files as $fileData) {
  $res = call_user_func_array(array(&$request, 'addFile'), $fileData);
...

という記述がある。つまり
 $files = array('file1', '/home/user1/fileA.txt');
では駄目で、
 $files = array(array('file1', '/home/user1/fileA.txt'));
としておかないと意図したようには動かない。

ただ、この実装のおかげで
「一度のPOSTで複数のファイルが送れる」
という恩恵もある。
解説がちゃんとしてないだけで、こっちの方が便利ではある。

…ところがソース中のmethod post()のコメントにも
  * @param  array Files to upload. Elements of the array should have the form:
  *      array(name, filename(s)[, content type]), see HTTP_Request::addFile()
とか平気で書いてあるから困ったもんだ。


※なお、この文章は「HTTP_Client Ver 1.1.1」に基づいております。

2008年8月29日金曜日

prototype.js each を抜けたい

Ajax を楽に実装したくて prototype.js に手を出した。
目的は達成したが、目的以外がめんどくさい−というか危険なことに。
特に配列(new Array とか [] とか)に独自の機能を持たせているので

for (a in arrayObj)
{
 ...
}

とかやってたとこが、軒並み全滅の憂き目にあっている。
それで、上記形式箇所を

arrayObj.each(
 function()
 {
  ...
 }
);

てな感じに書き直している。
それはいいのだが、ループを抜ける際に
「break」を使っていたところがエラーになってしまった。
ループじゃないから駄目ということらしい。
で、どうするのかっつったら
「throw $break」
これで解決した。

と言っても現状、throw の意味もわからなければ
$記号の意味もわからないので、わかったら書いとこう…。

あ、あととりあえず該当箇所の全書き換えは辛いので
「prototype.js」を呼び出すページを制限することにしました。
こっちのがずっと楽だし。

2008年8月22日金曜日

CSSのセレクタ

スタイルシートの指定方法。
何に対して指定するのか、を指定する方法をすぐ忘れる。

xx {}
これはタグへ対しての指定。xx は div とか span とか。

xx yy {}
これもタグへの指定だが、
<xx>ここは指定されず</xx>
<yy>ここも指定されず</yy>
<xx><yy>ここが指定される</yy></xx>
<xx><zz><yy>こうなってても指定される</yy></zz></xx>

xx,yy {}
これだと両方指定される。
<xx>ここが指定される</xx>
<yy>ここも指定される</yy>

.xx {}
これは class="xx" に対する指定。
xx.yy {} だと <xx class="yy"> が対象になる。

#xx {}
これは id="xx" に対する指定。


たぶん、#xx,yy.zz {} なんて指定もできるんだろうな。
実際そんなケースがあるかどうかはおいといて。

2008年8月20日水曜日

svn のホスト切替

svn(サブバージョン)というバージョン管理ソフトがある。
どっかのホストに元ネタ(これをリポジトリという)があり、
それを任意のクライアントから引っ張り出して編集し、ホストに戻すと
その更新順序だとか変更箇所のバッティングだとかを管理してくれる
便利なモンである。

これで開発プロジェクトの管理をしていたのだが、ゆえあってその
ホストが引っ越しをすることになった。
そうすると、開発環境に今までとは違うサーバにリポジトリがあることを
教えてやらねばならない。

そのコマンドが「svn swtch」である。具体的には
「svn://svnhost1/projectA」から
「svn://svnhost2/projectA」への
引っ越しだとすると

svn sw --relocate svn://svnhost1/projectA svn://svnhost2/projectA

となる。
オプション「switch」は「sw」と省略可能である。
スイッチ「--relocate」はリポジトリの位置が変わったときに使う。
…しかし、リポジトリの位置が変わらないのに「svn switch」を使うのって
どんな事態なんだろう。