web系エンジニアを目指し、MENTAを利用し、PHPを学習している初学者です。
日々学習していることの忘備録、モチベ維持、ちゃんとやってることの証明!の初投稿です。
#対象者
PHPを学びはじめた、初学者
#内容
class内で宣言した定数を参照した時、self::の有無で値がどう変化するか
#動作環境
PHP 7.1.32
#基本のおさらい
###class内で、共有する定数・変数を宣言する
class A {
//定数宣言(定数名は$不要、大文字がデフォ)
const TEISU = '絶対変わらない!';
//変数宣言(publicの他にprivate,protectedもあるが、ここではアンタッチャブル)
public $hensu = '代入されれば変わる';
}
###宣言した、定数・変数を使う
class A {
public function output {
echo '定数は' . self::TEISU; //定数は絶対変わらない!
echo '変数は' . $this->hensu; //変数は代入されれば変わる
$this->hensu = '簡単に変わる';
echo '変数は' . $this->hensu; //変数は簡単に変わる
}
このように、
定数はself::定数名
変数は$this->変数名
で使用できます。
「じゃあ定数使うなら、self::必須じゃん。」
と思いますよね。
ところが、定数はそのままでも使えるんです!
(プログラムは動いちゃうけど、)やっぱり原則使っちゃダメ!
と、訂正します。
#これが本題!(訂正前)
//前提:クラス内で宣言した定数を、同じクラスのメソッドで表示
const TEISU = '絶対変わらない!';
const ARRAY_TEISU = array(
1 => TEISU
);
//参照結果
echo self::ARRAY_TEISU[1]; //TEISU
echo self::TEISU; //絶対変わらない!
echo TEISU; //TEISU
つまり、
self::(配列の)定数名[キー]で、その中身
self::定数名で、その中身
定数名で、定数そのもの
が参照される!
以上!今回書きたかったのは、これです。
#これが本題!(訂正後)
//前提:クラス内で宣言した定数を、同じクラスのメソッドで表示
const TEISU = '絶対変わらない!';
const ARRAY_TEISU = array(
1 => self::TEISU
);
//参照結果
echo self::ARRAY_TEISU[1]; //絶対変わらない!
echo self::TEISU; //絶対変わらない!
つまり、
定義する時はselfいらないが、使用する時はself::必須!
###なぜ訂正前で良いと思ってしまったか
警告を表示させない環境(私の場合はvim)だった為
vimが悪い訳でなく、php.iniの設定の為です。
記事をご覧いただいた先輩よりご指摘いただきました。
ありがとうございました。
###解決方法
・php.iniの設定を変更する
もしくは、
・error_reporting(E_ALL);
を追記する
警告を表示する環境にすると、
const ARRAY_TEISU = array(
1 => TEISU
);
echo TEISU; //TEISU
この2箇所で、
Notice: Use of undefined constant TEISU(定義されてない定数があるよ)
という警告が表示され
「これじゃダメなんだ。」
と気付くことが出来ます。
「constの参照にはself::!!!!!」
と思い込み、長らくエラーに苦しみました。
「そんなバカな・・」
と思った方。これが初学者です!!
それでも信じられない方の為に、どう苦しんだのか実例を晒し、終了とします。
失敗実例は、削除するのも寂しいので、今回の知識をいかした内容に訂正しました。
##失敗実例(訂正後)
「メニュー番号を入力させ、機能を呼び出す」
というような課題で、クラスにたくさんの定数を宣言しました。
class Menu {
const MENU_MAGAZINE = '雑誌の一覧を見る';
const MENU_COMIC = '漫画の一覧を見る';
const MENU_NOVEL = '小説の一覧を見る';
const END_KEY = '終了';
const MENU_LIST = array(
1 => self::MENU_MAGAZINE,
2 => self::MENU_COMIC,
3 => self::MENU_NOVEL,
9 => self::END_KEY
);
$select_menu
には、厳密なバリデーションチェックの末、1〜3or9
が入ります。
public function main() {
//成功例
if (self::MENU_LIST[$select_menu] === self::MENU_MAGAZINE) {
//雑誌のメソッドを実行
}
//失敗例
if (self::MENU_LIST[$select_menu] === MENU_COMIC) {
//漫画のメソッドを実行
}
}
$select_menu=1
の時、成功例のif文に突入!
self::MENU_LIST[$select_menu] === self::MENU_MAGAZINE
が成立し(共に「雑誌の一覧を見る」)if文がtrue判定される
対して、$select_menu=2
の時、失敗例のif文に突入!
self::MENU_LIST[$select_menu] は、'漫画の一覧を見る'
MENU_COMIC は、 'MENU_COMIC'
(それ以前に、定数をself::〜として使ってないから警告対象)
となり、
if文がfalse判定される
漫画が見たくて「2」を何度押しても、エラーしか出ない悲しい事態になったとさ。
ちゃんちゃん。
#初投稿してみて
なかなか踏み出せなかった、Qiitaへの投稿。
「メモ帳に書いてるだけでは勿体無い!!」
と、思い切って投稿してみました!
良かったのは、**考えが整理される&間違いに気付ける(指摘していただける)**ことです。
投稿前は「self::の有無」ではなく、「配列かどうか」の違いだと勘違いしてた(今となっては謎)ですが、執筆している内に覚醒しました。
2時間近く掛かってしまいましたが、それだけでも儲けものです。