特集・コラム

メニュー

PHPer上級者になるために知っておきたいこと

vol.37 ‐ PHP 『関数仕様編 その2』

投稿日時:2014/06/12 01:06

カテゴリ: PHPer上級者になるために知っておきたいこと

今回も引数の話ですね。引数の型である「タイプヒンティング」について、少し学んでいきたいと思います。

PHPは所謂「動的型付け言語」になります。
「変数に明示的に型を指定せず、実行時に適切に型を推測してくれる」この型システムは大変に、
特に初学者にとっては便利なものではありますが。

「適切な推測」が、必ずしも本当に「プログラマの意図するところであるかどうか」については状況によるので、
場合によっては「困る」シチュエーションが、僅かながらに、存在します。
一つ、割と分かりやすい実例を。

$a = 2;
if (‘2a’ == $a) {
echo “equal\n”;
} else {
echo “not equal\n”;
}

2aと2の比較なので当然………equalになります。trueです。falseにはなりません…困った事に。
是非、お手持ちの実行環境で試してみて下さい。
筆者はこの問題を勝手に「2a問題」と呼称していますが。
これを始めに聞いた時は、なにげに度肝を抜かれたものでございます。
近しい実例として、以下のケースで実際に「割と深刻な」問題を引き起こします。

$find = ‘a';
if (false == strpos(‘abcdefg’, $find)) {
echo “{$find} is not find.\n”;
} else {
echo “{$find} is find!!.\n”;
}

比較演算子は「比較」なので、基本的には「両端が同じ型である」事がとても期待されます。
ただ、期待に反して「右辺と左辺で型が違う」場合には、予め定められたルールに従って「適切に型変換をしてから」
比較をします。

両辺のどちらかが数値でどちらかが文字の場合は「文字列を数値に変換してから」数値で比較を行います。
両辺のどちらかが真偽値の場合は「真偽値でないほうを真偽値に変換してから」真偽値で比較を行います。

かくして。

「2 == ‘2a’」は右辺が数値変換されて2となり、「2 == 2」の比較になるのでtrueとなり。
「false == 0」は(strposで「0番目に」探してる文字が見つかるのでintで0が返ってきてます)、0が真偽値変換されてfalseとなり「false == false」となるので、trueとなります。
ちなみに、switch構文が同じように「適切な型変換」を自動で行ってくれますので、同様の注意が必要です。

このように。
「適切な型変換」を十全に把握していればいいのですが、そうでない場合や不意の事故などで
若干面倒な事がおきるケースがあります。
故に「比較演算子は、原則として == ではなくて === を使い、!= ではなくて !== を使う」という原則が発生してくるのですが。
そうすると関数における引数なんかで「予め、型をちゃんと固定しておきたい」なんてケースは存在します。
「数値を期待している引数」なら、数値だけを入れて欲しいわけですね。

そんな時に「タイプヒンティング」を使います。
非常に残念な事に、現在、スカラー値には使えないのですが(…使えるようにして欲しいなぁ割と切実に思うのは筆者だけでしょうか?)。
配列やクラス、インタフェースなどは指定できるので、指定の仕方について把握をしておきましょう。
なお、インタフェースを指定した場合は「そのインタフェースを実装したクラス、またはその継承クラスのインスタンス」が、クラスを指定した場合は「そのクラス、またはそのクラスを継承したクラスのインスタンス」が、
利用可能です。
その辺りを、サンプルコードで確認していきましょう。

// — 下準備各種 —
interface test_interface {
public function i_hoge();
}
class hoge implements test_interface {
public function i_hoge() { echo ‘i_hoge'; }
}
class e_hoge extends hoge {
}
class foo {
}
// 呼び出される関数(タイプヒンティングテスト用)
function test_type_hinting(array $awk, test_interface $o1, hoge $o2, foo $o3) {
}
// call用下準備
$obj_hoge = new hoge();
$obj_e_hoge = new e_hoge();
$obj_foo = new foo();
// 呼んでみる
test_type_hinting(array(1,2,3), $obj_hoge, $obj_hoge, $obj_foo);
test_type_hinting(array(1,2,3), $obj_e_hoge, $obj_e_hoge, $obj_foo);
// 以下、NGなパターン
//test_type_hinting(10, $obj_e_hoge, $obj_e_hoge, $obj_foo);
//test_type_hinting(array(1,2,3), $obj_foo, $obj_e_hoge, $obj_foo);
//test_type_hinting(array(1,2,3), NULL, $obj_e_hoge, $obj_foo);

駄目なパターンは、配列の所にスカラー値入れたり、見当違いのインスタンス入れたり、NULL入れたりしています。
ちなみにNULLについては。関数宣言で「デフォルト引数」入れておくと、OKになるみたいです。

// — 下準備各種 —
interface test_interface {
public function i_hoge();
}
class hoge implements test_interface {
public function i_hoge() { echo ‘i_hoge'; }
}
class e_hoge extends hoge {
}
class foo {
}
// 呼び出される関数(タイプヒンティングテスト用)
function test_type_hinting(array $awk, test_interface $o1 = NULL, hoge $o2 = NULL, foo $o3 = NULL) {
}
// call用下準備
$obj_hoge = new hoge();
$obj_e_hoge = new e_hoge();
$obj_foo = new foo();
// 呼んでみる
test_type_hinting(array(), NULL, NULL, NULL);

若干癖があるので、細かく確認をしながら使っていきましょう
また。今回、もう一つのタイプである「callable」については説明をしていません。
こちらは後日説明をしていきますので、少々お待ち下さいませ。

さて引数の話はこのあたりでcloseいたしまして。
お次は…やっぱり引数の、最後のネタ「参照渡し」について、少し細かくやっていきたいと思います。
どちらかというと「PHPでは忌避される事の多い技」ではありますが。なればこそなおのこと「何故に忌避されるのか」については把握をしておいたほうがよいかと思いますので。

バックナンバーはこちら

IT系のお仕事特集

お仕事のご紹介には、まずヒューマンリソシアへの登録が必要です。
ヒューマンリソシア人材派遣サイトの便利な機能 ・お気に入りの派遣求人のブックマーク ・登録会への予約 ・有給休暇の管理 ・WEB給与明細の確認 ・お気に入りの情報をメール受信
登録会の入力手続きをあらかじめおこなえます。

ヒューマンリソシア派遣サービスに 登録する 無料

ページトップへ戻る
ヒューマンリソシア派遣サービスに 登録する 無料
ページトップへ戻る