PHP:代入文を使った配列末尾への追加について

最近、PHPでの代入を使った配列末尾への値追加で驚いたことがあるので、それを書きます。

 

通常、PHPで配列の末尾に値を追加する際に以下のようなコードで実現できます。

$array   = array();
$array[] = 値;

 

実は私、これがarray_push関数と同じ挙動をするものだと思っていました。

これが大間違いで、実はこれ代入なんですよ〜。

 

つまり

$array   = '';
$array[] = 値;

とするとstring型の$arrayは再定義されて、array型の$arrayとして生まれ変わるのです。

var_dumpで中身を見るとすると

string(0) ""
から
array(1) {
  [0] => 値
}

になっているということですね。

 

array型に対しては、

$array[] = 値;

とやっていくと配列の末尾に値が追加されていくことになります。

 

最初は、またPHPが意味不明なキャストしてると思いきや…

まあ代入なら仕方ない………んなわけあるか!

「オラにじぇじぇじぇなコードを書いてくんろ!」のやつ

エンジニア夏祭り2013「オラにじぇじぇじぇなコードを書いてくんろ!」解答編 #engineer #matsuri #hatena #zaim #夏祭り #夏の想い出 - CodeIQ Blog

とりあえず、Pythonで書いたので公開しときます。

 

 

spa = "gtgtsgipgttptinggipsppaigsesgpetgstpatetisiesagaeaigttetepitiatsegssieeeeatepaaiagtpieataatppiitgiapsteitatiiatpetetetttgpetpaasipttssstpeeeggtiagtttegtiipestsasgpsepaasapttgattgiatppegitiatpasgatgepttggapesaeetaeissttggieietgspagesiipestipggstttpateptitiaetottissgggtttaipappgstsptttgtpispattgegstltiappseisapgistaiagteeiptptpisaieisagstapeteietgteiisgtiptstgtstasspeatspptitttatteastsgtptgtasggpniaaeteaisett"
npo = list("neapolitan")

print "".join(["[%s]"%npo.pop(0) if len(npo) and c==npo[0] else c for c in spa])



npoから一文字づつ抜き出していって、抜き終わったらifがlen(npo)で判定を打ち切る。
それで生成された文字列リストをjoinで結合して出力。
とまあ汚いけど動きます。

PHPで整数値かどうかを調べる(糞コード)

知り合いからPHPってまともに整数値判定できないの?と質問された。

 

経緯は

知「PHPでフォームから取得した文字列を数値判定する関数調べたけど穴あるよね〜?」

私「いや、ctype_digit関数使うかpreg_match関数で正規表現使えばいいじゃん」

知「へ〜、正規表現使えないからctype_digit使ってみるわ。」

知「もちろんctype_digitって整数型も通すよね?」

私「えっ!?どうやったっけ!?」

Google検索でctype_digitのマニュアルを読むと

 

注意:

 

この関数を活用するには string を渡さなければなりません。 たとえば integer を渡すと、期待する結果にならない可能性があります。 HTML フォームに入力された整数値は、integer ではなく string 型で返されます。 マニュアルの  についての節を参照ください。

 

出典: http://php.net/manual/ja/function.ctype-digit.php

 

知「やっぱPHPってク○言○やな」

私「いや、まだ方法はある!!!」

 

 

と意地になった結果、整数型も文字列も10進数かどうかを判定してくれるコードが完成した。(糞コード)

 

まずは、PHPで登場する数値かどうかを判定する関数と欠点を紹介したい。

①is_int()

文字列を判定できない。

 

②is_numeric

小数点や16進数なども通す。

 

③ctype_digit

-128 から 255の整数値を入れるとFALSEを返す。

 

他にもあるかもしれないけど、私の知っている範囲で。。。

 

そこで私が書いたコードがこれだ。

(string)$num === (string)(int)$num

 

何をしているかと言うと

まず、(int)だが、文字列を整数値にキャストしれるものだ。

この型変換だが、少し癖がある。

というのも、"1a1"などの文字を含んだ数値をキャストすると、文字より手前の数値だけを返す。

 

例えば、"1a1"なら、1が返ってくる。

この癖を活かしている。

(string)$num === (string)(int)$num

この比較の右辺の値をまずキャストする、それを文字列に変換し直して

文字列にキャストした左辺の値と比べる。

 

$numが整数値の場合も、両辺とも文字列に変わるだけなのでTRUEが返る。

 

とまあ糞なコード書いてみました。

そして知人に完成したコードを見せたら、、、

知「正規表現コピペしたらいいし、このコードきもい」

と一蹴。

 

ふう、わけのわからんブログ書いてしまったなorz

ある夏のシステム開発のことだった…

納涼!ほんとにあった怖いコード(by CodeIQ×はてな)

 

ある夏、私はとあるプロジェクトでプログラマとしてアルバイトをしていた。

そこでは、PHPを使った管理ツールを作成していた。

しばらくして、社長から「私のコードをメンテナンスしといてくれ」との指示を受けた。

そのプログラムはとある店舗の売上などを表示するというものだ。

社長がどのようなコードを書くのか心踊らせた。

しかし、それは吐き気に変わった。

なんと、手続き型で記述されたHTMLと混ざったPHPコード、SQLコードが1000行近くも続いていたのだ。

さらに何やら怪しげな関数群をインポートしているので、一体何行分のコードになるのかわからない。

ソースコードを読んでいくと、$kinという変数が出てきた。

頭上に疑問符が浮かんだが、どうやら金額という単語を連想させたいのかなと解釈した。

次に$kin_gという謎の変数が登場した。

これはHTMLに差し込まれている変数部分から金額の合計だということがわかった。

さらにコードを読み進め、処理が一区切り終わったところでコメントアウトが登場した。

//こんな処理でいいんかな?ちょっと重いと思うねんな

//もっといい方法あると思うわ

なんとTwitterで呟きが如くコメントアウトに社長の心境が呟かれているではないか!?

そこに

//SQLのチューニング、変数名の最適化をしておきました。

とコメントアウトで返信しておいた。

 

そして次の処理部分を覗くと、なんと一区切り前のコードと酷似しているコードがずらずらと書かれていた。

区切り終わりには

//こんな処理でいいんかな?ちょっと重いと思うねんな

//もっといい方法あると思うわ

とコメントアウトが。

さっき編集したコードがまた登場したことで私は混乱し、時間を遡ったと錯覚した。

しかし、現在の行数を確認するとしっかりと読み進めていることを確信し、我に帰ることができた。

さらにコードを読み進めると、またも酷似したコードがいくつも続いた。

私は、錯乱し、コード自体をゴミ箱へと運んでやった。

その後、同じ挙動をするプログラムを一から開発し、プロジェクトが終わると同時にアルバイトを辞めた。

 

私が無限ループを感じたことはそれ以前、以降なかった。

あの夏の恐怖はエディタを開くたびによみがえる。