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」を使うのって
どんな事態なんだろう。

2008年8月6日水曜日

exim4

debian にデフォルトで入ってる MTA がこれ。
exim4 はデフォルト設定では自分以外にメールが出せない。
設定項目「dc_eximconfig_configtype」を
dc_eximconfig_configtype='internet'
と書き換えた後、daemon をリロードなりリスタートすれば再設定完了。

ちなみにデフォルト設定では「'local'」だが、かつては「'none'」だった。
また、設定ファイル名も現在は「update-exim4.conf.conf」だが、
以前は別の名前だったような。

2008年7月17日木曜日

PHPでモジュールが読み込まれない!

そんな時は php.ini の「extension_dir」を見てみよう。
記述された内容と、実際に「*.so」が置かれている場所が
違ってるかもしれないから。
あと、自分が見ている php.ini が
本当に読み込まれているかも確認した方がいい。
cli/ と間違うことは少ないだろうが、
apache2/ と cgi/ を間違えたことならある。

2008年7月16日水曜日

ExecCGI

ExecCGI と書かれてなきゃCGIは動かない。
それは憶えてた。

けど、どこに書くのか。
「/usr/lib/cgi-bin」は sites-available/default にあったけど…
と思って「public_html」で /etc/apache2/* あたりを grep すると
あるサーバでは apache2.conf
別のサーバでは userdir.conf に

Directory /home/*/public_html>

</Directory>

が記述されていた。ちなみに

前者は Apache/2.0.54
後者は Apache/2.2.3

である。

2008年7月14日月曜日

こんなことまで忘れてしまうのかと

そう思うとちょっと憂鬱だが。

apache2でphpを動かしたい


・事の起こり
php ファイルを作成し、ブラウザにURL打ち込んだらファイルがDLされた。

・確認1
php5.conf、php5.load: enmodされてないどころかavailableに存在してない。

・実行
apt-get install libapache2-mod-php5

・確認2
php5.conf、php5.load: 共にenmodにavailableへのリンクあり。けどやっぱりダウンロードされる。

・実行
apache2 restart

・確認3
これでブラウザからもPHPの実行が確認された。

今回の備忘ポイントは追加するモジュールの名前「libapache2-mod-php5」だな。

2011/07/25 追記
「ドキュメントルート配下ではPHPが動作するが、UserDirでは動作しない」という現象が確認された。
調べてみると mods-enabled/php5.conf の設定に原因があるらしい
     12         <Directory /home/*/public_html>
     13             php_admin_value engine Off
     14         </Directory>
このへんが見るからに怪しいので「php_admin_value engine On」と修正してapacheを再起動する。
結果、動作は変わらず。PHPファイルがダウンロードされる。
よく見るとその直前に
      8     # To re-enable php in user directories comment the following lines
      9     # (from <IfModule ...> to </IfModule>.) Do NOT set it to On as it
     10     # prevents .htaccess files from disabling it.
     11     <IfModule mod_userdir.c>
     12         <Directory /home/*/public_html>
と書いてあるではないか。なので、とりあえず「php_admin_value engine Off」をコメントする。
apacheを再起動すると、期待通りPHPが実行されるようになった。
コメント行の記述にあるようにIfModule全体をコメントしたほうが処理は軽くなるはずなので、
運用は全体をコメントアウトしよう。

2008年7月11日金曜日

psql 8.1.2

ALTAR TABLE で SET DEFALT CURRENT_TIMESTAMP と指定した。
確認のため \d したところ
「default now()」
と表示された。

なんかちょっとショックだった。

2008年7月10日木曜日

オブジェクトか?

bool is_object($foo)
$foo がオブジェクトであれば真。

bool is_a($foo ,'bar')
$foo がクラス「bar」のオブジェクトであるか、「bar」を継承したクラスのオブジェクトであれば真。
ただしこの関数はPHP5では非推奨であり、演算子「instanceof」を用いて
($foo instanceof bar)
と記述するのが推奨だとか。この「bar」は文字列ではないことに注意。

string get_class($foo)
オブジェクト$fooのクラス名を返す。

bool class_exists ('bar')
クラス「bar」が定義されていれば真。

2008年7月9日水曜日

vsftpd の設定

/etc/vsftpd.conf で設定。
anonymous_enable はNO(アノニマスでの使用はしない)
local_enable はYES(アカウントのあるユーザーでログイン)
write_enable はYES(書き込み権アリ)
local_umask は022(できるファイルのパーミッションは755)
listen はデフォルトでNO。YESにしても動くらしいがよくわからない。
NOにすると自分ではポートをlistenせず、誰かが呼んでくれないかと
ひたすら待つことになるから、vsftpd を呼ぶ人を用意せねばならない。

呼ぶ人は inetd である。inetd じゃなくてもいいのかもしれないが、
他に同じようなことをしてくれる人を知らないので inetd で行く。
inetd は/etc/inetd.conf で設定する。
ここに「/usr/sbin/vsftpd」を含む行を追加すればおk。
(今回、具体的な追加内容は省略)

あと、hosts.deny をちゃんと設定していると新しいサービスは蹴られるので
hosts.allow にサービスを追加しておくように。

2008年7月8日火曜日

userdir

apache2 でモジュール「userdir」を導入しないまま「hoge.com/~user/fuga.html」をリクエストしたらどうなるか。

/var/www/~user/fuga.html を探られた。
当たり前といえば当たり前だな。

どうでもいいけど「~」は「チルダ」か「ティルデ」というのが一般的らしい。
「ティルダ」とかいう人は少ないのか。

補遺
モジュール追加 → a2enmod
モジュール削除 → a2dismod

adduser した時に public_html も作っとく

adduser に先だって /etc/skel/ に public_html を作っておく
これでおk