Hatena::ブログ(Diary)

A Small, Good Thing - diary このページをアンテナに追加 RSSフィード

A Small, Good Thing

2012-04-05

【追記あり】第3回関西PHP勉強会直前案内

当日利用するソースコードが公開されました【4/6 14:30 追記】

https://github.com/phpmentors-jp/kphpug-questionnaire

上記が当日利用するソースコードとなります。参加される皆さんは確認しておいてください。

この記事は、2012/4/7(土)に開催する、第3回関西PHP勉強会Symfony2マスターが直接手ほどき!アプリケーション開発実況観戦」に参加される方への直前案内です。

キャンセル待ちの方はご自身の状況をご確認ください

あっという間に定員の40名が埋まってしまったため、キャンセル待ちの方がたくさんおられます。既にキャンセルが10名ほど出ていますので、キャンセル待ちの方は、再度、ATNDページから状況をご確認ください。

第3回 関西PHP勉強会 : ATND

実践編の時間を拡充し、LTは懇親会にて行います

先週の土曜日にスタッフ数名で事前勉強会を行ったのですが、実践編がかなりのボリュームになりそうなので、急遽、時間を30分拡充します。それに伴い、LTは懇親会で飛び入り形式で行うこととします。

懇親会はオオサカンスペースにてそのままピザパーティです

懇親会は、勉強会終了後そのままオオサカンスペース(勉強会会場です)にて開催します(会費は1500円〜2000円程度)。ピザと飲み物(お酒・ソフトドリンク)を用意します。場所の移動もありませんので、都合のつく方はぜひご参加ください。

その場でLTもやりますので、皆さん、LTネタを用意しておいてくださいね。

懇親会は別申込となっています

ややこしくて申し訳ないのですが、人数把握のため、懇親会は別申込となっています。懇親会に参加される方は、下記のATNDページからも申込みをお願いします。

第3回 関西PHP勉強会 懇親会 : ATND【懇親会専用ページです】

できれば事前予習を

勉強会では実際にアプリケーションを開発することを主眼におきますので、Symfony2 の環境の準備などについて詳しい解説は行いません。事前に以下の Symfony2 公式日本語ドキュメントなどに目を通されておくことをお勧めします。

Symfony2 クイックツアー

http://docs.symfony.gr.jp/symfony2/quick_tour/index.html

Symfony2ブログチュートリアル

http://docs.symfony.gr.jp/sf2-blog-tutorial/


事前勉強会では、かなり濃い内容となることが分かりました。みなさん、前日は良く寝て、冴えた頭でお越しください。きっとたくさん得るものがあると思います。

それでは、当日お会いしましょう!

2011-12-17

isset() 関数にご用心! ( #phpadvent2011 Day 17 )

PHP Advent Calendar 2011 の 17 日目です。昨日はhajikamiさんの「no title」でした。

みなさんこんにちは。17 日目担当の omoon です。普段は大阪WEB アプリケーションを作ったりしている会社におりまして、PHP は触り始めて 10 年ぐらいです。

本当はもっと早く記事を上げる予定だったんですが、急遽下のような仕事が入りまして遅くなりました。ごめんなさい。

訳あってこうなっている

さて、みなさんは配列の要素の存在確認ってどうされてますか?

僕は、PHP を始めてからずっと無条件で isset() 関数 を使っていたのですが、ついこの間、えー、うそん!的なハマりを体験いたしましたので、もうご存知の方には面白くともなんともない話だとは思いつつ、恥を晒す覚悟でまとめてみたいと思います。

isset() 関数はその配列要素が存在しても値が null なら false

null でも false なんです!知らなかった。僕は単純に知らなかった。マニュアルの一番最初に書いてあるのに。。

isset ― 変数がセットされていること、そして NULL でないことを検査する

PHP: isset - Manual

<?php
$noodles = array(
    'udon'   => 'white',
    'soba'   => 'gray',
    'pasta'  => 'yellow',
    'malony' => null,
);
isset($noodles['udon']); // true (知ってた)
isset($noodles['malony']); // false (えー、知らんかった!)
isset($noodles['somen']); // false (知ってた)

つまり、単純に配列要素の存在だけを確認するために、isset() を使っていると、要素自体は存在するのに false が返ってくることがあるということです。つい先日、これでバグ出しました。ごめんなさい。

ということで、配列要素の存在の確認には、array_key_exists() が良いみたい。

<?php
$noodles = array(
    'udon'   => 'white',
    'soba'   => 'gray',
    'pasta'  => 'yellow',
    'malony' => null,
);
array_key_exists('udon', $noodles); // true
array_key_exists('malony', $noodles); // true
array_key_exists('somen', $noodles); // false

お恥ずかしい限りですが、またひとつ賢くなりました。

配列の要素の要素などに isset() 関数を使うときの注意

で、ついでにもうひとつ。

配列の要素の存在確認に isset() を使う癖が付いているとこういう勘違いもしてしまいがち、という例をお話しします。そして、これでもバグを出しました。ごめんなさい。

配列の要素の要素の存在を調べたいと思ってやってしまったこんな例です。

<?php
$noodles = array(
    'udon'  => 'white',
    'soba'  => 'gray',
    'pasta' => 'yellow',
    'malony' => null,
);

isset($noodles['udon']['color']); // true (えー、うそん!)
echo $noodles['udon']['color']; // 'w' が出力される (なにそれ?)

これはさっきの話よりは少し複雑ですので、詳しく見ていくことにします。今から説明する2つのことが関係します。

(1) 文字列へは、[] を使って文字単位でアクセスできる

これ、意外と知られていないと言うか、最初知ったときは、何それー、と思うと思うんですが、つまり、

<?php
$name = "Santa Claus";
echo $name[0];  // S
echo $name[1];  // a
echo $name[2];  // n
echo $name[3];  // t
echo $name[4];  // a
echo $name[5];  // ' ' 
echo $name[6];  // C 
echo $name[7];  // l
echo $name[8];  // a
echo $name[9];  // u
echo $name[10]; // s

ということ。

ちなみにこんな風に書き換えることも可能。

<?php
$name = "Santa Claus";
$name[0] = 'P';
$name[3] = 'd';
echo $name; // Panda Claus(誰?)

まずこれが関係することの 1 つ目です。

(2) 型の相互変換

PHP: 型の相互変換 - Manual のページには、

PHP は、変数定義時に明示的な型定義を必要と(または、サポート) しません。ある変数の型は、その変数が使用される文により定義されます。 これは、ある文字列変数 var に代入した場合には、 var は文字列になることを意味しています。 ある整数値を var に代入した場合には、 その変数整数になります。

とあります。要は、時と場合によって文字列が勝手に数値になることがあるよ、ってことですね。

で、その時と場合のひとつが文字列変数に続く[] 内の文字列の場合で、

<?php
$name = "Santa Claus";
echo $name['firstName']; // これは'S'と出力される

となります。

つまり、文字列変数 $name に続く [] 内の文字列「firstName」が数値「0」に変換されるため、$name[0] と同義となり、$name の 1 文字目の「S」が出力されることになります。

でも、なぜ「0」なのか。

実はこの挙動、PHPマニュアルこのページの「文字列の数値への変換」セクションにきちんと書いてあります。

数値として文字列が評価された時、結果の値と型は次のように定義されます。

文字列の中に '.' や 'e'、'E' といった文字が含まれず、 数値が integer 型の範囲内 (PHP_INT_MAX で定義されています) におさまる場合は integer として評価されます。それ以外の場合は、すべて float として評価されます。

文字列の最初の部分により値が決まります。文字列が、 有効な数値データから始まる場合、この値が使用されます。その他の場合、 値は 0 (ゼロ) となります。有効な数値データは符号(オプション)の後に、 1 つ以上の数字 (オプションとして小数点を 1 つ含む)、 オプションとして指数部が続きます。指数部は 'e' または 'E' の後に 1 つ以上の数字が続く形式です。

見落としがちですが、

文字列が、 有効な数値データから始まる場合、この値が使用されます。

とありますので確かめてみます。

<?php
$name = "Santa Claus";
echo $name['1stName']; // これは'a'と出力される

となるんですね。

ここでも文字列が数値に変換されるのは同じですが、今度は [] 内の文字列「1stName」が有効な数値データ「1」から始まっているため、$name[1] と同義となり、$name の 2 文字目「a」が出力されるというわけです。

これが、関係することの 2 つ目です。

で話をもどして、配列の要素の要素の存在確認は、、

さて、この 2 つのことを頭に入れて、先ほどの

<?php
$noodles = array(
    'udon'  => 'white',
    'soba'  => 'gray',
    'pasta' => 'yellow',
    'malony' => null,
);

isset($noodles['udon']['color']); // true (えー、うそん!)
echo $noodles['udon']['color']; // w (なにそれ?)

を順に説明してみると、

となります。

ということで、配列の要素の要素の存在確認は、

<?php
$noodles = array(
    'udon'  => 'white',
    'soba'  => 'gray',
    'pasta' => 'yellow',
    'malony' => null,
);

if (is_array($noodles['udon'])) {
    array_key_exists('color', $noodles['udon']);
}

のように、

  • 配列であるかどうかを確認した上で
  • array_key_exists() を使って確認

するのが良いようです。

と、色々話してきましたが、実はこのあたりの内容については、PHPマニュアルにも幾つかコメントがついています。

困ったら PHP マニュアルに帰れ!(コメント欄も含めてね)、という素晴らしい定説を確認できたところで、僕の話しを終わりたいと思います。

みなさん、良いクリスマスを!

明日は、@DaiMotoh さんです。

最近のコメント
プロフィール

omoon

omoon

30代、男、縄文系

日記の検索