おはようございます、こんにちは、こんばんわ。
フリーランスの薬剤師として生活収入を得ながら、プログラミング言語を勉強している”Yuya Matsuura”と申します。
その中で、【WordPress】などにも採用されている≪PHP≫について、改めて学び始めておりまして、
ブログ記事としてアウトプットすることで知識の定着を狙う
+同じような境遇の方の参考になればと思い、シリーズ化して記事にさせて頂きます。
個人的な目標は”Raravel”(フレームワーク)をサクサク使いこなせるようになりたい!です。
※なお、追々記事でまとめるかは決めかねていますが、ローカル環境構築については今のところ記事にするつもりはないので、ご容赦ください。
アウトプット方式なので、記事としては見難いかも知れませんが、ご参考になれば幸いです。
今回はPHPでも「型宣言」が出来るという事で、学習したことを記事にまとめさせて頂きます。
ご参考になれば幸いです。
そもそも「型」って何だろうか?
「動的型付け言語」と「静的型付け言語」
もともとPHPは「動的型付け言語」と言い、JavaScriptも同じく動的型付け言語に分類されますが、
処理の中で特に「変数」に対して「型」を定義する必要がありません。
細かい部分は徐々に覚えていけば良いと思うのですが、
ふんわりまとめると【型を定義しなくても(=または記述者が意図した型と違っていても)、上手く処理してくれる言語】
こんな感じでイメージ頂いておくと、良いかなと思います。
それに対して、「静的型付け言語」と言う概念があります。
PHPでもバージョンアップの末、PHP7から実施できるようになったとの事です。
①変数に値を代入する際に【型】を宣言することが可能になった。
②コード中で意図している【型】に合わない値が入るとエラーを起こすことが可能になった。
これを見て、ただ単に記述量や学ぶことが増えて、面倒なだけなのでは?と思って方。
それが、つまり私なのですが。
もちろん、そこに見合うメリットや意義があります。いや、あるみたいです。
<?php
$test = 1;
if ($test == 1) {
echo 'true';
} else {
echo 'false';
}
?>
上記のif文を用意してみました。
testと言う変数に「1」を入れておきます。
if文の中身は、もしtestが「1」なら「true」とechoし、そうでないなら「false」とechoします。
なので、上記コードではブラウザには『ture』と表示されますし、
仮に$test = 1; の「1」の部分を別の値にすると、『false』と表示されます。
PHPの基本の「型」を学ぶ
<?php
$test = '1';
if ($test == 1) {
echo 'true';
} else {
echo 'false';
}
?>
2行目の$test内の値が 「1」 ▶「’1’」に変わりました。
このコードの説明の前にPHPにおける基本的な『型』の種類を学んでいきましょう。
まず皆様もよく目にする「echo文」ですが
例えば echo こんにちは;
とPHPで記述すると、エラーを起こします。
これはなぜかというと、基本的にecho文は「文字列を出力する」ためにあるので、
値を「’」(シングルクォーテーション)または「”」(ダブルクォーテーション)で囲んで、パソコンに文字列として認識させる必要があります。
echo ‘こんにちは’; または echo “こんにちは”;
上記に書き換えるとエラー無く出力されます。
ここでいう「文字列」と言うのが『型』であります。
簡略に記述しますが、基本的な4つの型を紹介します。
(他にもたくさんあります!!)
①文字列型(string) : 「あいうえお」「Hello World!!」などの文字のこと 「’」または「”」で囲む必要がある
②整数型(int) : 「1」「200」「-30」などの整数値 以下のfloat型とは明確に区別する
③浮動小数点型(float) : 「1.2」「100.5」など少数や分数 整数では表すことが出来ない数値
④論理型(bool) : 「true」か「false」の2つのみ ブーリアン(boolean)と呼ぶ
ちなみに「’1’」と言うように「’」や「”」で囲むと「1」と言う文字列になります。
(この考え方が下記で大切になってきます!)
var_dump() 関数について
echo文の他にもブラウザに値を表示させる方法はいくつかありまして、
その中の1つに「var_dump()」と言うPHPでデフォルトで使うことが出来る関数があります。
ただし意味合い的には、値を出力させることが目的ではなく、値の中身を確認する際に使います。
<?php
$test = "こんにちは";
var_dump($test);
?>
使い方は簡単で、表示させる変数をvar_dump関数の引数として渡してあげます。
string(15) “こんにちは”
このように表示することが出来ます。
もちろん右側の “こんにちは” は$testの中身を表示させた結果であります。
対して左側の string(15) については、string(文字列)と言う型であり、「15」の大きさを持ってますよ~の意味です。
ちなみに「15」と言う数字に違和感があるかもしれません、半角英数字が1文字「1」に対して日本語文字は1文字「3」の大きさを持ちます。
なので “こんにちは” という5文字に対して、×3をして「15」と表示されています。
<?php
$test1 = 1;
$test2 = "1";
var_dump($test1);
var_dump($test2);
?>
test1には整数型(int)としての「1」、test2には文字列(string)としての「1」が格納されています。
int(1) string(1) “1”
var_dumpで出力すると上記のようになり、明らかに中身が異なることが分かるでしょう。
等価演算子(==)と厳密等価演算子(===)
1つ前の見出しで挙げたコード例を見てみましょう。
<?php
$test = '1';
if ($test == 1) {
echo 'true';
} else {
echo 'false';
}
?>
先に学んだ通り2行目の $test = ‘1’; の部分を見ると、ここの値は文字列型で定義されています。
対してif文の条件の中では($test == 1)としており、ここの値は整数型です。
以上からif文の$testには’1’が入ってくるため(if (‘1’ == 1) )、条件を満たさず、falseがechoされるのかなと予測できます。
ただし、結果としては「true」と言う文字をechoします。
これはPHPにおいては先に述べたように「動的型付け言語」になるので、
「’1’」という文字列型の値をif文に渡すときに上手く相違が無いように「整数型」に変換してしまうためで、
条件を満たしてますよ。という事でtrueをechoします。
JavaScriptも同じような補完機能がありまして、これは一見事前にエラーを防いでくれて、便利な概念かと思われるのですが、
コード量がもっと膨大に増えてくる現場の世界においては、逆にこの本来想定している型を入力してしまっても、エラー無く進んでしまうことが、致命傷になったりするようです。
要するに値の定義の段階で、きっちりと『型』を指定することは、面倒に感じるかもしれませんが、
そうすることで開発者の意図に反することなく処理を行うことができるので、必須という事みたいです。
↑の例文(if文)ではtureがechoされても、falseがechoされても致命傷にはなりませんが、
大きなプロジェクトになると、意図しないところに誤った型を記入することで大きなバグが生じたりすることがあるからですね。
厳密等価演算子(===)について
今回の上記の例文において、ifの条件式で用いている「==」は等価演算子と呼びます。
PHPにおいては両辺の値自体の真偽しか確認しないので、「’1’」も「1」も型は違えど『1』として認識されるため、
今回例ではtrueをechoしました。
対して「===」(厳密等価演算子)と言う記述方法があります。
厳密等価演算子は両辺の型についても真偽を比べるため、
<?php
$test = '1';
if ($test === 1) {
echo 'true';
} else {
echo 'false';
}
?>
と4行目のif条件文内に「=」を1つ加えると、falseをechoします。
このようにPHPでも型の概念を反映出来る事を覚えておきましょう。
strict_typesモードとは?
PHPの機能(構文)にdeclare文と言うものがあり、「ディレクティブ」を設定することが出来ます。
declare(ディレクティブ);
のように記載するのですが、その中の1つにstrict_typesを設定することが出来ます。
declare(strict_types=1);
この記述をコードのはじめに書くことで、PHPにおける補完の型変換を禁止することが出来ます。
上記で述べたようにコードの初めに書くので、その名の通り、「途中では無く」初めに書いてあげましょう。
<?php
declare(strict_types=1);
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>PHP test</title>
</head>
<body>
<?php
?>
</body>
</html>
1~3行目に別途<?php ?>を記載して、中にdeclare(strict_types=1);と書いてあげます。
この記述をすることで、厳密な型のチェックをすることができます。
下記例文です。
<body>
<?php
function double($num) {
return $num * 2;
}
echo double(2.01);
echo '</br>';
echo double('2');
?>
</body>
コードの下部のbody内のPHPタグ内に上記のコードを書いてみました。
簡単な関数ですね。
引数にnumと言う変数を渡して、returnで×2をして関数外に返します。
なお1つだけ新しい記述として、引数の$numの前に「int」を記述しています。
この「int」は整数型のintであり、このように引数の前や変数において記述することで『型』を指定できます。
一旦、declare(strict_types=1); をコメントアウトして、echo文を見てみます。
echo文には下記の図のように出力されます。
この結果は何となく予想が付くと思います。
それぞれ「2.01」は浮動小数点型、「’2’」は文字列型になりますが、
それぞれ動的型付け言語であるPHPが上手く保管して、それっぽい出力をしています。
次に1つだけ新しい記述として、引数の$numの前に「int」を記述します。
この「int」は整数型のintであり、このように引数の前や変数において記述することで『型』を指定できます。
<body>
<?php
function double(int $num) {
return $num * 2;
}
echo double(2.01);
echo '</br>';
echo double('2');
?>
</body>
結果的には下記の図のように出力されます。
おおむね結果としては同じようになりましたが、1行目のecho文だけ 4.02 ▶ 4 に変わっています。
これはどういうことかと言うと、先ほど追記した型指定が影響しています。
今回、引数の型を「int」で指定しているため、動的型付け言語であるPHPの補完機能により、
浮動小数点型である4.02が無理やり整数型(int)である「2」に変更されているのです。(で、さらに関数で×2して「4」が出力されてます。)
ただし、echo文としては上手く補完していたためエラーは起こさず実行されました。
この場合は、本来は「4.02」と表示したかったのに、予期せぬ補完機能のために「4」と表示されたことになります。
このような意図せぬ事は追々のバグに繋がります。
declare(strict_types=1); の記述でエラーを事前に見つけ出す
先ほどコメントアウトしたdeclare(strict_types=1);の部分を戻してみました。
再度、結果を出力させてみましょう。
上図のようにエラーが出力されました。
私は英語が大の苦手なので!!意味合い的に合ってるかどうかはおいておいて、
double(): Argument #1 ($num) must be of type int, float given
一行目のこのエラー文ですね。
double()という関数において
▶ Argument(引数)#1(一番目の)は「int」でなければならない
▶ でもfloat(浮動小数点型)が与えられてるよ
みたいなことをご指摘されています。
要するに引数にはきちんと『指定した型』(今回で言うとint)を入れてください。
そうしないとエラーは解決しませんよ!みたいなことを言われております。
まとめ
declare(strict_types=1);をはじめに記述することで、型の概念を取り入れ、かつそれに反した場合はエラーを起こすことが可能になります。
初めの等価演算子(==)と厳密等価演算子(===)を使った、型の使い分けも大切な概念の1つで、
開発者が予期しないバグを事前に防ぐことが出来るストッパーの1つになります。
初めは不要に思えるかもしれませんが、少しずつこの記述も理解して、取り入れるように出来ればなと思います。
コメント