Unknown::Programming このページをアンテナに追加 RSSフィード

2006-05-24 愚痴

PHPがどうにも好きになれない理由

仕事柄PerlPHPも使うんだけど、どうにもPHPが好きになれない。

いったいなんでだろうか。先にPerlから入ったもんだから後から入ったPHPに対して不満があるのかな?

ま、とにかく両方やっててPHPが微妙だなぁと思う部分を列挙してみよう。

ただPHPに関してそれほど詳しくないので間違っている部分もあるかもしれません。

あ、ちなみにここでいうPHPってのはPHP4(PHP4.4.1)のことです。

  • 変数のtypeミス(strict 'vars')

これが一番痛い。

まさしくPerlでstrictを使わずに実装してるような、そう、まるで先祖帰りしてるような感覚になってしまうので本当につらい。

変数のスコープが関数単位でしか発生しないのが痛い。

これによりif条件の場合のみとかループ中でしか使わない変数とかを定義できない。

つまり、変数の存在範囲を細かく設定できないのだ。

僕はPerlで実装する時は配列ハッシュを良く使い分けてます。

例えばref関数でARRAYなら配列用の処理、HASHならハッシュ用の処理をするようなケースがあったとします。


 # 例えばこんなん
 if( ref $param eq 'ARRAY' ) {
     print $param->[0];
 }elsif( ref $param eq 'HASH' ) {
     print $param->{hoge};
 }

こういうことをPHPでやろうと思ったときにできない、何故できないかというとPHP配列ハッシュ(連想配列)も同じだから。

array関数で定義する際に、


 $param = array('a','b','c');

とすれば配列だし、


 $param = array( 'key1' => 'a', 'key2' => 'b', 'key3' => 'c' );

とすればハッシュになるので、現在$paramが配列なのか、ハッシュなのかを判別する完璧な手段が無いのです。

一応それっぽいやり方として、


 function is_hash (&$array) {
     reset($array);
     list($key,$val) = each($array);
     return is_numeric($key) ? false : true;
 }

みたいな感じでやれば殆どの場合判別できるんですけど、でもこれでもハッシュのキーに数値を使っていた場合は配列に誤認識されることになります。

  • 例外処理

これもPHPが好きになれない大きな理由のひとつ。

一応set_error_handlerってのがあるんだけどグローバルに定義するものなので局所的には使いにくい。

また、エラーハンドラ用の関数を予め定義しておかないといけないのもめんどくさい。


 # Perlの場合 
 eval {
    a();
 };if($@){
     print 'a';
 }
 
 # PHPの場合
 function a_error($no,$string,$file,$line) {
     print 'a';
 }
 set_error_handler('a_error');
 a();
 restore_error_handler();

で、もうひとつ。

例外処理終了後の処理の制御ができないのもイタタタです。


 # Perlの場合
 sub a {}
 sub b {}
 sub c { die "c\n" }
 sub d { die "d\n" }
 
 eval {
     a();
     b();
     c();
     d();
 };if($@){
     my $string = $@;
     chomp $string;
     print $string;
 }
 print '_hoge';

これを実行すると「c_hoge」と表示される。

で、これをPHPでやるとしたら・・・、


 # PHPの場合
 function error_handler($no,$string,$file,$line) {
     print $string;
 }
 function a() {}
 function b() {}
 function c() { trigger_error('c'); }
 function d() { trigger_error('d'); }
 set_error_handler('error_handler');
 a();
 b();
 c();
 d();
 restore_error_handler();
 print '_hoge';

「cd_hoge」と表示される。

何故こんなことになるかというと、set_error_handlerでエラーハンドラを設定した場合、エラーを補足後、エラーのあった場所に戻って処理が続行されるから、です。

したがってPHPの場合は例外処理のやり方としてクラス設計段階から常に戻り値にエラーフラグを返すようにするなどの処置が必要となります。


 function a () {
        :
        :
     return array($error_flag,$ret);
 }
 
 list($error_flag,$data) = a();
 if($error_flag) {
     print 'error!';
 }

実際PEARDBクラスとかは例外が発生した場合に常に戻り値にエラークラスを返すような仕様になってますな。

関数リファレンスが使えない。

一応、Perlのシンボリックリファレンスみたいな感じで文字列から関数を呼ぶことはできるのでそれで代用は可能。

一応create_functionってのがあるんですが、あれって結局グローバルな空間に関数名として使えない文字列で関数を定義してるだけなんで、

使えば使うほどガンガン関数が定義されていくのでちょっと微妙です。


 $a = create_function(
     '$b=9',
     'print $b;'
 );
 $a(); // 9と表示される

create_functionで定義される関数名の仕様が「NULL文字lambda_連番」なので、


 $a = create_function(
     '$b=9',
     'print $b;'
 );
 $hoge = "\x00lambda_1";
 $hoge() // 9と表示される

って感じでアクセスできたりします。

個人的によくクロージャを使うのでこれができないのは悲しいですね。

一応ググってみたらno titleとかあったりしてそれらしいことは出来るみたいなんですが、

どっちにせよ楽に実装することはできないようです。

便利なライブラリ群が無い、いや、一応PEARっていうのがあるんだけどCPAN程豊富じゃないしPEARに属さない一匹狼クラスとかも多くてわかりにくい。

このほかにも細かいことを言うとメソッドチェーンができなかったり、多重継承(Mix-in)できなかったり、qw//使いてぇーだったりと、

まあ色々あるんですけどそこは言語が違うんだから受け入れるしかないですよね。

と、ここまで書いてみて結局PHPが嫌いなのか?と思われるかもしれないが嫌いではない、ただ好きになれないだけってこと。

先にPerlを知っちゃったもんだからPHPにも同じものを求めてしまっているのかも。

逆にPHPPHPPerlには無い良い部分もあるし。

foreachの構文とかはPHPの方がキーと値をワンセットで取ってこれるのでいい感じ。

is_arrayとかもお気に入り。言語仕様でswitchがサポートされてるのも良い。

あぁ、なんか結局PHP嫌い的な文章になってしまったけどとりあえずPHP5では例外処理とかサポートされたんで、

今度はPHP6でstrictあたりをサポートしてくれたらたぶんそれなりに好きになりそうな予感。

PHP5PHP5 2006/05/24 18:33 >例外処理とかサポートされたんで

ご、誤解しないでよ。
だっ、だれもあんたなんかのために、サポートしたんじゃないんだからねッ!

fbisfbis 2006/05/24 19:13 そう、ツンツンなさらずに。
あとメソッドチェーンもサポートしてくれてありがとう。

odzodz 2006/05/24 23:38 > 変数のtypo
error_reporting(E_ALL)で有る程度防止できませんか?
Perlと違って実行時エラーなので、利便性はだいぶ落ちますが。

fbisfbis 2006/05/25 01:52 そうですね、必ずerror_reporting(E_ALL)使うようにしてます。
でも実行時エラーがでるのは右辺値として使った場合ですよね?
左辺値として使った場合、たとえば、

$hoge = 10;
if($flag){
//flagが真のときに$hogeを20にする
$hoga = 20;
}
print $hoge;

みたいな書き方の時に結局$hogaはエラーにならないですしね・・・。
あとやっぱりコンパイル時にチェックできないのが痛いです。

wtnabewtnabe 2006/05/25 08:11 未定義の変数がいきなり出てくればそれも警告されるはずですよ。

wtnabewtnabe 2006/05/25 08:12 あ、だめか。代入しちゃってますね、これ。うーん。このケースだと無理っぽい。テストしてしばし悩むって過程が必要な感じ。

dayflowerdayflower 2006/05/25 19:44 >foreachの構文とかは
perl でも each でキーと値をワンセットでとれますけど,見た目が気に入らないということでしょうか?

fbisfbis 2006/05/25 20:57 見た目というよりもeachに関してはいくつか問題があってあんまり使ってないですね。
eachを使ったwhileループ中に再度each,keys,valuesを使うと無限ループ、キーを動的に増やすと場合によっては無限ループ。
あとソートが出来ないんで使うケースが少ないです。
ただ処理速度的にはeachの方が早いので速度重視する場合はたまに使う程度ですね。

dayflowerdayflower 2006/05/26 09:35 >eachに関してはいくつか問題があって
なるほど。たしかにイテレータが共有されているので問題多いですね。私も単純にキーと値のセットだけ使う場合に each 使います。
foreach については PHP のほうがデフォルトで安全寄りなのでその点は好きです。Perl だとイテレータ書き換えると配列のほうも変わってしまうんで。

123123 2006/05/27 00:45 「好きになれない」じゃなくて「好きに使いこなせない」だな。

fbisfbis 2006/05/27 13:01 >「好きになれない」じゃなくて「好きに使いこなせない」だな。
どうしてもPerlベースに考えてしまうので
「PerlでできることがPHPでできない」=「好きになれない」
という結論になったわけです。
でも123さんの指摘だと、
「PerlでできることがPHPでもできるのに使いこなせてない」=「好きに使いこなせない」
という風にみえるのですがそうなのでしょうか?
もしそうなら僕が単純にPHP知識不足なのかと思います。
僕がダメだと思っている指摘事項に対してこうすれば解決できるよというのがあれば教えて頂きたいです。
PHPに関してあまり詳しくないのからこそこういう不満点を上げて誰かからもしフィードバックがあれば嬉しいなぁという思いで記事を書いたのでこういうツッコミは大歓迎です。

123123 2006/05/28 01:55 Perlベースの考えだから使いこなせないんであって
PHP使うんだからPHPベースで考えろよ、と。

fbisfbis 2006/05/28 11:25 >PHP使うんだからPHPベースで考えろよ、と。
PHPベースで考えた場合、これらの問題点はどう解決してますか?
それとも解決できないからそのままでやるしかないということでしょうか?

123123 2006/05/30 01:07 perlでできることをPHPに求めるから問題になるんであって、
PHPでできることの範囲でやってしまう。

たとえば微妙な表現を話したい場合、外国の言葉(1つの単語になっていることが多い)にたとえて話すことをたまに見かけますよね。その国にその言葉がないということはそういうことを表現する必要がなかったという歴史があるはず(当然求めてもいいし、作ってもいい)。外国で生活したり、外国の文化にふれて初めてその言葉の意味がわかって使いたくなる、そんな感じを言いたかった(たとえづらいのですがわかりますか?

fbisfbis 2006/05/30 10:15 >perlでできることをPHPに求めるから問題になるんであって、
>PHPでできることの範囲でやってしまう。
ですよね。それが好きになれない理由なんです。
もし今後PHPを使いこなせるようになったとしてもこれら実現できないのなら好きになれない。
例えばC言語とPerlを比べてPerlには型が無いから好きになれないという人がいたらその通りだと思いますし。
でもそれって言語の特性なんで文句を言っても始まらないわけで、PHPでできることの範囲で僕なりに模索してみた結果、
これができない、あれができないということになり、「PHPって好きになれねぇー」って結論に至ったわけです。
でもそれは僕がPHPについて勉強不足な所があってまだまだ「使いこなせていない」ので、
それはこういう方法で実現できるよ、みたいなのがあればいいなと思ってエントリー書いたわけですね。
123さん的に僕が上げたこれらの問題が問題と思わないとしたらそういうことを実現する際に、
Perlとは違った別の方法で実現していることになると思うんですが、その別の方法というのが単に僕的に好きになれないというだけなんですよね。
まぁもはや個人の感覚の問題もあるので微妙なとこなんですけどね。
ちなみに123さんはPHPに不満とかありますか?
僕はPHPもPerlも不満だらけだったりします。

123123 2006/06/01 02:37 うーん

BaysideBayside 2008/05/31 17:17 Java から入った自分は、PHP も Perl も最大公約数的な使い方で十分満足しているので、OOP の記述性だと PHP > Perl ですねぇ。リファレンス(ポインター)を使いこなすなら C / C++ 言語が一番ですね。C / C++ 言語に GC があればいいのに・・(D 言語にはありますがw)。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証