PHPはちょろっと書いて動かすことが可能です。言語の基本的なことはあまり意識せずとも書けてしまいます。そんなこんなで、実践的にPHPとお付き合いして20年来の私。
そんな関係につき「言語構造」なるキーワードは知ってはいましたが、何となくの理解です。人に説明できるほどの知識もありません。
今回とあるきっかけで、言語構造について調べる機会がありました。結果、もっと早く興味を持っておくべきだったなと後悔しました。empty()
って言語構造だったんだ!などです。
本ページでは、せっかく調べたので記事に残しておきたいと思い書きました。「言語構造」というキーワードを知っても即効性はありませんが、PHPerなら知って損はないと思います。
言語構造の概要
言語構造とは!?
PHP言語の基本的な部品やルールを指します。
具体的には、変数、演算子、データ型、制御フロー構造(if-else文、ループなど)、関数やメソッド、エラー処理、クラスとオブジェクトなどが含まれます。
PHPを構成するベース部分、使わないとプログラミングできない部分と言って良いでしょう。
言語構想の一覧
執筆時点のPHPのマニュアルを読むと、以下のようなキーワードがリストされています。これらは(言語構想とは明記していませんが)PHPの言語構造一覧と言えると考えられます。
- __halt_compiler()
- abstract
- and
- array()
- as
- break
- callable
- case
- catch
- class
- clone
- const
- continue
- declare
- default
- die()
- do
- echo
- else
- elseif
- empty()
- enddeclare
- endfor
- endforeach
- endif
- endswitch
- endwhile
- eval()
- exit()
- extends
- final
- finally
- fn (PHP 7.4 以降)
- for
- foreach
- function
- global
- goto
- if
- implements
- include
- include_once
- instanceof
- insteadof
- interface
- isset()
- list()
- match (PHP 8.0 以降)
- namespace
- new
- or
- private
- protected
- public
- readonly (PHP 8.1.0 以降)
- require
- require_once
- return
- static
- switch
- throw
- trait
- try
- unset()
- use
- var
- while
- xor
- yield
公式では、「特別な意味を持つキーワード」という表現で紹介されています。
覚える必要、ある!?
言語の根本的なキーワードなので、重要と言えば重要です。しかしテストに出るわけでもないので、「言語構想」の一覧として覚える必要はないと思います。
もちろんそれぞれの意味を理解することや、バージョンアップ毎に目を通しておくことは重要だとは思いますけどね。久しぶりに見ると「?」なキーワードが追加されていることもありますし。
ちなみにPHP歴20年~の私でも、先ほどの一覧中で1度も使ったことが無いキーワードはたくさんあります。逆に毎日の様に使っているものもありますね。
スキルアップのため、余裕がある時に知らないキーワードを調査してみるというのは良いかもです。私も先ほど、__halt_compiler()
ってなんじゃ!?と思い、調べてみたら新たな発見がありました。
まあ、それで「実務に使えるな!」というのはあまりないかもしれませんが。
私の実践的な理解
実践的なPHPプログラミングをする上で、言語構造ということを考える機会はそれほど多くないはずです。
ここでは私の言語構造の捉え方についてご紹介します。これは私が「言語構造」を知った上でプログラミングする際に影響を与えた要素。つまり正解とは言えませんので参考までに。
定数、クラス名、 関数名に使わない
言語構造は、定数、クラス名、 関数名として使えません(クラスやインターフェイス、そしてトレイトの内部では、 プロパティ、定数、メソッドの名前として使えます)。
普通にプログラミングをしていて、言語構造と名称がかぶってエラーになった……というのは記憶にありません。ですが、一応頭に入れておく必要はありそうです。
関数っぽく使える言語構造を意識する
if
, foreach
, function
等はもう言語構造そのもの。誰でも一目瞭然です。
対してempty()のように、カッコをつけて関数のように呼びだせる言語構造があります。
例を挙げましょう。
- array()
- die()
- empty()
- eval()
- exit()
- isset()
- list()
- unset()
- require(), require_once()
- include(), include_once()
これらはempty($var)
のように、パラメータをつけて実行することが可能です。
ただの関数と思っていた!そんなの気にしたことなかった!という初心者さんもいると思います。
しかし関数ではなく厳密には言語構造と認識していると、コードを書いている時の思考や書き方も時に変わってくるように思います。
isset, emptyの例
関数のように呼び出せる代表例として、isset()
やempty()
等があります。
PHPを使用していると、ある変数が存在するかどうかを確認する必要が度々出てきますよね。例えば以下です。
<?php
if (isset($var)) {
echo '$var is set';
} else {
echo '$var is not set';
}
?>
なんら問題の無いコードですが、$var
が初期化されていてもいなくても動きます。
isset()
が、そもそも変数が定義されているか確認する用途なのでおかしくはないはず……。しかしこれはisset()
が言語構造だからこそできる技です。
通常の関数であれば、$var
が存在しない時点でNotice: Undefined variable
エラーが出てしまいます。言語構造であるisset()
は通常の関数ではなく「そのために使うもの」として作られているので可能なのです。
関数と区別を付けずに使えはします。ですがより正しく認識してコードを書くことに、デメリットはないでしょう。
require_onceの例
関数っぽく使える言語構造の中には、カッコをつけて呼び出せるものもあります。
例えばrequire
, include
系です。以下はいずれでもファイルを読み込めます。
<?php
require_once 'file.php';
require_once('file2.php');
?>
どちらでも動作はしますが、個人的には2行目の方が言語構造を表しているようで、個人的にはよく使います。
私が初心者の頃は、何も考えずにファイルを読み込む関数として(カッコありで)使っていました。分からないで使うのと、分かっていて使うのとではやはり違うように思うのです。
どちらの方法が良いかは、チームやプロジェクトの規約に準ずるのが一番となります。私のようにフリーランスだと自分で決められます。いずれにしてもプロジェクトでは一貫性をもって使用するのがこのましいです。
まとめ
正直、言語構造というものを知ったからといって、コードが改善するような大きな影響はないと思います。
例えば私はempty()
など何も気にもとめず使っていましたが、今後もコード上の使い方は同じです(頭の中では言語構造なんだとは思い浮かぶでしょうけれど)。
ですがPHPという言語を正しく理解すること。そしてそれを人に教えるなどの立場にある人は、知っておく必要がある概念なのだなと思いました。
本ページが言語構造に気をとめるきっかけになれば幸いです。
コメント