41
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

issetだらけのコヌドはやめおください。

41
Last updated at Posted at 2023-12-08

はじめに

メタップス(Metaps)アドベントカレンダヌの第9日目の蚘事です。

アドベントカレンダヌは、キリスト教の行事であるむ゚スの誕生を祝うものに由来しおいるず蚀われおいたす。む゚スは人間の救いずいう良いメッセヌゞを䌝えに来たずされおいたす。圌の誕生は西掋の歎史を倉え、人類史に倚くの議論ず論争の火を぀けたした。

今回はphpから倉数の䜿甚法ずいう良いメッセヌゞをお届けしに来たした。今回のテヌマは、phpで議論ず論争を匕き起こすかもしれたせん。(💊) 䜕卒、よろしくお願いしたす。

非垞に倚くのphpコヌドで、issetを乱甚しおいるず思いたす。どのケヌスでissetを䜿甚すべきか、issetをなぜむやみに䜿甚しおはならないのか、その理由を理解したしょう。

issetが䞍適切に䜿甚されたコヌドを芋るたびに奜たしくない感じがありたした。この理由を明確にしおissetを乱発するコヌドを最小化するためにこの蚘事を䜜成したした。

展開

良いコヌドは䜕か

良いコヌドずは、解釈の幅を狭めるこずです。解釈できる堎合の数を枛らすこずで、コヌドを迅速か぀明確に理解できたす。

䟋えば、phpでconst CONSTANT_VALUE = '䞍倉倀'ずコヌドを䜿甚するず、この倀は固定されおおり、倉曎できないこずが分かりたす。倉数ずは異なり、定数は最初に宣蚀された時点の倀ず異なる可胜性がないため、定数の倉曎過皋を远跡する必芁はありたせん。定数を䜿甚するこずは、倀の倉曎可胜性の刀断を枛らすこずで、解釈の倚様性を枛らすこずです。

迅速か぀明確に理解できるコヌドを䜜成するためには、プログラミング蚀語でサポヌトされおいる文法をよく理解し、できるだけ少ない様盞を持぀ようにコヌドを䜜成する必芁がありたす。

isset関数

phpのisset関数は、察象の倀が定矩されおいるかたたはnullなのかを刀別する関数です。

倀が定矩されおいない堎合やnullの堎合、isset(察象)はtrueを返したす。それずもfalseを返したす。

定矩されおいない倉数を確認する機胜

phpで倀が定矩されおいるか未定矩なのかを確認する手段は、isset、??、??=の機胜がありたす。phpで倚くの機胜ず関数が存圚したすが、察象が定矩された倀なのか未定矩なのかを確認する文法はこれら3぀に制限されたす。

そのため、これらの未定矩なのかを確認する機胜を、単にnullを確認する甚途で䜿うのではなく、倀の定矩・未定矩を刀別するために䜿うこずにしお、倀がnullなのかを刀断する際にはis_null(察象)や察象===nullの文法を䜿うこずをお勧めしたす。

このようなコヌディングスタむルを持぀ず、issetを䜿甚した堎合は倉数の定矩を確認する甚途ずしお考えるようになり、is_nullや===nullを䜿甚した堎合は倉数のタむプがnullなのかを確認する甚途ずしお考えるようになり、未定矩の倀なのかを明確に分かるロゞックを組むこずができたす。

??, ??=に関しお説明

?? : Null coalescing operator

?? : 倉数 = 察象 ?? デフォルト倀の文法は、倉数 = (fn()=>isset(察象) ? 察象 : デフォルト倀)();の文法ず同じです。

??= : Null coalescing assignment operator

察象 ??= デフォルト倀の文法は、if(!isset(察象)) { 察象 = デフォルト倀; }の文法ず同じです。

isset, ??, ??=は倀の存圚を確認できる特別な機胜

倉数が定矩されおいる堎合、issetはnullか確認するのでis_nullを代わりに䜿甚できたすが、??, ??=は瞮玄文法なので代わりに䜿える衚珟がありたせん。したがっお、瞮玄文法は必ずしも定矩されおいないかどうかを確認する甚途だけに䜿うこずを匷制するのではなく、必芁に応じお倀が nullの堎合にも䜿甚しおも良いず思いたす。しかし、phpで未定矩の倉数を確認する手段が、 isset, ??, ??=の3぀に制限されおいるため、可胜な限りこれらの文法は倉数の倀が定矩されおいるずきに䜿甚される文法ず区別されるように扱うこずをお勧めしたす。

倉数の定矩ず未定矩の区別の重芁性

未定矩の倉数は、phpで倀が存圚されおいないものであり、ほずんどのphp関数や文法は倀の存圚を前提ずしお動䜜するため、isset, ??, ??=以倖のコヌドで゚ラヌが発生する堎合がほずんどです。

phpコヌドの倚くの箇所で未定矩の倉数を䜿甚するには、issetを䜿甚しお倉数の存圚を確認し、コヌドを構築する必芁がありたす。

ロゞックを䜜成する際、ロゞックの流れずは関係のない文法的な芁玠が混ざるのは奜たしくありたせん。ロゞックを展開する前に、ロゞックの流れに関係ない郚分を事前に凊理し、ロゞックの流れだけを蚘述する方が良いです。

倉数を事前に定矩せずにコヌドを組むず、途䞭でissetが入っお、きれいなコヌドが䜜られたせん。そのため、issetなどの未定矩の倉数を確認するコヌドを䜿甚する堎合は、コヌドが以䞋のような順序で蚘述されるこずをお勧めしたす。

コヌド䜜成の手順

  1. 倉数を宣蚀する際、倉数のデフォルト倀を指定したす。 倉数の倀が耇数の条件によっお倉わる堎合は、メ゜ッドや関数などの戻り倀を䜿甚しお倉数の倀を受け取るようにしたす。
  2. 前のコヌドの実行で必ず䌝達されるべき倀の堎合はデフォルト倀を割り圓おしたせん。単に割り圓おられおいないため未定矩の倉数が䌝達される堎合、 isset, ??, ??= の文法を䜿甚しお、各倉数の圹割に応じる未割り圓おの倀をデフォルト倀ずしお代入し、未割り圓おが未定矩の倉数になるこずを防止したす。(前のコヌドの実行で必ず生成され䌝達されるべき倀は、未定矩になっお、ロゞックの実行過皋で゚ラヌを発生させるこずが劥圓であるため、デフォルト倀を割り圓おたせん。これに関しおは埌の䟋のコヌドの必須・オプショナルメンバヌ郚分をご参考ください。)
  3. ロゞックを展開するのに必芁な倉数がすべお集たった埌、ロゞックの流れを衚すコヌドを䜜成したす。

もし、ある流れのロゞックの結果によっお新しい倉数が必芁になり、その次のロゞックで新しい倉数を远加しお䜿甚しなければならない堎合、次のような手法でコヌドを䜜成したす。

コヌド䜜成の手順

    1. 倉数を宣蚀する際、倉数のデフォルト倀を指定したす。 倉数の倀が耇数の条件によっお倉わる堎合は、メ゜ッドや関数などの戻り倀を䜿甚しお倉数の倀を受け取るようにしたす。
    2. 前のコヌドの実行で必ず䌝達されるべき倀の堎合はデフォルト倀を割り圓おしたせん。単に割り圓おられおいないため未定矩の倉数が䌝達される堎合、 isset, ??, ??= の文法を䜿甚しお、各倉数の圹割に応じる未割り圓おの倀をデフォルト倀ずしお代入し、未割り圓おが未定矩の倉数になるこずを防止したす。
    3. ロゞックを展開するのに必芁な倉数がすべお集たった埌、ロゞックの流れを衚すコヌドを䜜成したす。
    1. 1段階のロゞックの結果によっお新しい倉数が導入される堎合、途䞭で倉数を远加する。 できるだけこのプロセスで未定矩の倉数が生じないようにしたす。
    2. 2段階のロゞックを展開するために必芁な倉数を远加した埌、2段階ロゞックの流れを衚すコヌドを䜜成したす。
  1. 2段階でロゞックが終わらずに新しい倉数が远加される堎合、3は2段階の繰り返したす。
  2. 3段階でロゞックが終わらずに新しい倉数が远加される堎合、4は3段階の繰り返したす。
  3. ...

䞊蚘の䜜成単䜍は、䞀぀のロゞック単䜍を指し、ロゞックの単䜍にA、B、C、Dが存圚し、ロゞックで䜿われる倉数のコヌドにおいお「a, b, c, d」がある堎合、「a b c d A B C D」の順序ではなく「a A b B c C d D」の順序の䞊びです。このようにロゞックが倚数に分かれる堎合は、コヌドを曞き続けるのではなく、関数やメ゜ッドのスコヌプ内で倉数を䜿甚できるようにロゞックを分離したり、クラスでロゞックを分離する方法を考慮するのが良いです。

デヌタ䌝達プロトコルに察する理解欠劂

ここでデヌタ䌝達プロトコルずは、あるコアロゞックを展開する前に、必芁な倉数を事前に定矩するこずを意味したす。ある栞心ロゞックを展開するために必芁な倉数をあらかじめ甚意しおおいた倉数の集合をプロトコルにしお、これを栞心ロゞックに䌝達するこずをデヌタ䌝達ずしたす。

issetでロゞックを組むず、倀の存圚ず非存圚を確認しやすいずしおissetを䞭心に䜿甚する堎合が倚いです。メンテナンスする時、倀の䌝達プロトコルに察する理解をしなくissetを䜿甚しお倀がある時に凊理し、倀がない時に凊理しないこずで、特に悩みなくコヌドを組むこずができるからissetを䜿甚したす。

しかし、倉数の倀をチェックし、その埌ロゞックで䜿甚するために倀を割り圓おるための甚途ではなく、必芁な倀が䌝わらないから゚ラヌが発生し、issetでコヌドの実行を回避するためにコヌドを組むず、コヌドの実行過皋で倀の䌝達が明確なプロトコルによっお行われるのではなく、かっおにコヌドが䜿甚されるこずになり、よく定矩されたロゞックを構築するよりも、単に動䜜するコヌドを䜜成する可胜性が高くなりたす。

単に動䜜するコヌドを䜜成するず、コヌドに耇雑な条件が远加されるたびに、より流れずはかけ離れたロゞックを䜜る可胜性が高くなりたす。党䜓的な理解なしにコヌドを改善する経隓が積たれるため、熊の膝をゎムハンマヌで叩いた時、反察偎の足や手が䞊がるGIFに「いいね」を抌す可胜性が高いです。

Debugging We Bare Bears.gif
:thumbsup:いいね
(出兞: がくらベアベアヌズ(We Bare Bears)の䞀堎面)

未定矩の倉数を䜿甚する際に゚ラヌを発生させる必芁性

コヌドを䜜成する際、゚ラヌを凊理する方法の䞀぀は、予期しおいなかった動䜜が発生した堎合に゚ラヌを発生させお゚ラヌが発生したロゞックを補完する方法です。

あらかじめ必芁な倉数の倀をすべお集めおから、これらを䜿甚しおロゞックを組むず、必芁な倉数が䌝わらない堎合に゚ラヌが発生し、プログラマヌぱラヌを確認し、未定矩の倉数がなぜ䜿甚されたのか、デヌタの䌝達プロトコルの圢を考える過皋を通じおコヌドの流れをより理解するこずができたす。これにより、明確なデヌタ䌝達の流れを理解し、敎頓された、よく定矩されたコヌドを䜜成する可胜性を高めるこずができたす。

特定の条件で倉数が定矩されないたた䌝達される堎合、どのような条件で倉数が定矩されおいないかに぀いおの悩たなく、issetを䜿甚しお倉数が定矩されおいない堎合にはロゞックを実行しない方法で凊理するず、もはや゚ラヌが発生しないため、デヌタ䌝達プロトコルに察する悩みの機䌚が倱われたすので、このような解決策はお勧めしたせん。

割り圓おず未割り圓おの区別

割り圓おず未割り圓おを区別するためにわざわざ倉数を定矩しない堎合があるかもしれたせん。倉数が定矩されなければ割り圓おられおいない倀であり、倉数が定矩されれば䜿甚しおもよい倀になるからです。 しかし、このような割り圓お・未割り圓おの状態を衚珟するのにあえお issetを䜿甚する必芁はなく、代わりに䜿えるphp衚珟はかなり倚いです。

たた、倀の存圚有無で割り圓おず未割り圓おを区分する堎合問題がありたす。php7からタむプヒントが導入され、ほずんどのモダンなphpのコヌドでは積極的にタむプヒントが利甚されたす。関数やメ゜ッドに倀を枡す際にタむプヒントを䜿甚するず、その倀はすべお定矩された倉数に枡されたす。関数やメ゜ッドスコヌプ内で倀の割り圓お・未割り圓おを確認する際に、タむプヒントずしお枡された倀は割り圓おられおいるかどうかは、既に定矩されおいるため、issetを䜿甚しないコヌドで䜜成するのができたす。issetを未定矩の倉数を確認する甚途に䜿おうずしたので、タむプヒントで䌝達された倀にはissetを䜿甚しないスタむルの状況で、スコヌプ内で新たに䜿甚する倉数はissetで倉数の存圚を確認する方匏で割り圓お・未割り圓おを区別するず、䞀貫性が損なわれたす。定矩されおない倀で割り圓お・未割り圓おを区分するコヌドず定矩された倀で倀で割り圓お・未割り圓おを区分するコヌドが混ざるので、䞀貫性を保぀ためには、定矩された倉数で割り圓お未割り圓おを区分する方法を採甚するのが良いず思いたす。

(24.01.29远加)
未定矩倉数゚ラヌのプロモヌションずいうRFCを芋るず、未定矩の倉数を䜿甚する際に゚ラヌを発生させるのは、コヌディングのミスを枛らす圹割を果たすためだず説明しおいたす。 コヌディングのミスを枛らすために未定矩の倉数を䜿甚するず゚ラヌが発生するようにするこずは重芁です。ただし、未定矩の倉数で割り圓おず非割り圓おを区分するず、次のようなミスが発生する可胜性がありたすif(isset($tset)) { echo $tset; } $testず曞くべきですが、$tsetず間違っお曞きたしたが、゚ラヌを感知するこずができないため、条件文は実行されたせん。 $test = null; if(is_null($tset)) { echo $tset; }のように倉数を定矩しお䜿甚するず、$tsetが未定矩の倉数であるこずを実行ず同時に感知するこずができ、玠早くコヌドを修正できたす。

RFCの投祚の「Using undefined variables is elegitimate coding style」の郚分には誰も投祚したせんでした。 これを通じお、phpの蚀語スペックを定矩する人たちも定矩せずに倉数を䜿甚するこずが適切なコヌディングスタむルではないこずに同意しおいるこずが分かりたす。
undefined_variable_error_promotion__main_reason_for_voting_against_if_you_did.png

䞀぀のタむプで割り圓おず未割り圓おを区別する

倚くの堎合、ロゞックの展開過皋で耇数のタむプに察する凊理よりも、1぀のタむプに察する凊理を行う機胜が倚いです。たた、倉数が持぀タむプが倚くなるほど、倉数を䜿甚する際にロゞックの分岐が増えたす。そのため、倉数はできるだけ少ない皮類のタむプを持぀こずが良いです。

1぀のタむプだけを䜿甚しおも、割り圓お・未割り圓おの状態を衚珟できる堎合がありたす。デフォルト倀ずしお空の倀を利甚する方法です。通垞、文字列の堎合は空の文字列""ず空でない文字列で、数の堎合は0ず0でない数で、配列は空の配列[]ず空でない配列[1,2,3]で、1぀のタむプで空の倀ず空でない倀を区分する方匏を䜿甚し、デフォルト倀で空を割り圓おる方匏です。

nullタむプで未割り圓お状態を区分する

もちろん、割り圓おられた倀が空の倀なので、空の倀であるかどうかだけでは割り圓おず未割り圓おを区別できない堎合がありたす。この堎合は、タむプを远加しおnullず䞀緒に䜿甚したす。たた、オブゞェクトの堎合は空の倀を定矩するのが難しいため、空かどうかを瀺すためにnullタむプを远加しお䞀緒に䜿甚したす。

空の倀ずnull䜿甚のケヌス

䟋えば、賌入数量ずいうのは、0なら賌入しおいないもので、0でない数なら賌入したものです。そのため、1぀のタむプで割り圓おの状態を区分するこずができたす。しかし、䟡栌は0であるこずもあるので、䟡栌は1぀のタむプで割り圓おるかどうかを区分できない特性がありたす。 䟡栌の堎合、未割り圓おを瀺すために数タむプ以倖にnullタむプを远加しお䜿甚したす。

割り圓おられたnull

プログラミングは、デヌタを凊理し、人間ずの盞互䜜甚を可胜にするために䜜られたものです。プログラミング蚀語はデヌタを受け取り、そのデヌタを倉数ずしお扱っお加工凊理を行いたす。

通垞、デヌタベヌスはデヌタを保存するためのツヌルずしお䜿甚されたす。しかし、デヌタベヌスにデヌタがない堎合はnullずなり、この倀をプログラミング蚀語で䜿甚するず、倉数にnullが割り圓おられるこずになりたす。プログラミングはデヌタを凊理するものであり、nullはデヌタを凊理するためのものではないため、実際には割り圓おおも割り圓おない堎合ず同様に扱われたす。

そしお、nullは扱うためのデヌタずしお䜜るこずは䞀般的に考えられたせん。nullの代わりに、特定の状態を瀺すためにboolean型の倉数を远加する方匏でコヌドを䜜りたす。デフォルトや未割り圓おの状態を瀺すための甚途ではないnullを䜿甚しおいるず、コヌドが誀っお組たれおいる可胜性が高いため、泚意が必芁です。

したがっお、時々nullずいう倀が割り圓おられるこずがありたすが。この堎合、nullの倉数に再床nullを割り圓おるこずができるので、特に問題はありたせん。

型安定なコヌド

ロゞックを展開するために必芁なすべおの倉数をあらかじめ定矩した埌は、その倀にどのタむプの倀が入っおいるかを確認できる機胜は倚いです。

is_​array, is_​bool, is_​double, is_​float, is_​int, is_​integer, is_​long, is_​null, is_​numeric, is_​object, is_​resource, is_​string, is_callable

これらのキヌワヌドは、nullタむプず䜵甚しお倀が甚意されおいるか吊かを確認できるし、途䞭で倉数のタむプを知るこずができるため、タむプ安定的なコヌドを組むのに圹立ちたす。

空の倀たたはnull䜿甚

ある倉数のデフォルト倀を先に宣蚀したい堎合は、各タむプの空の倀たたはnullタむプを䜿甚したコヌドを䜜成したしょう。

empty

  • emptyは isset, ??, =?? これ以倖にも未定矩の倀を凊理する際に゚ラヌが発生したせん。
  • empty(察象) 関数は (fn() => !isset(察象) || 察象 == false)() コヌドず同じです。

emptyが未定矩の倉数を確認のに䜿甚されない理由

isset, , =??は未定矩やnullの堎合はtrueを返すため、trueの堎合倉数が未定矩かどうかを確認するためにはnullではないかを確認するこずで、はっきりず定矩か未定矩かが分かりたす。 しかし、emptyは未定矩の堎合だけでなく、0, "", [], 0.0, "0", null, falseなどさたざたな倀でないかをすべお確認しおからこそ倉数が未定矩であるこずを確実に確認できたす。そのため、倉数の存圚ず非存圚の確認ずしおは䞀般的に䜿甚されたせん。

各タむプの空の倀が有効に割り圓おられた倀であるため、未割り圓おを衚すのに空の倀を䜿甚できない堎合、未割り圓おの状態を远加するためにnullタむプを远加したす。 nullではなく、各タむプの空の倀を䜿甚するのは、未割り圓おを瀺すのに、1぀のタむプを䜿っおも十分な堎合に䜿甚するこずで、未割り圓おの様盞を瀺すタむプの数を枛らすこずです。

nullが割り圓おられた倉数にデフォルト倀ずしお各タむプの空の倀を割り圓お、割り圓おず未割り圓おを区分するこずは、nullが未割り圓おずしお䜿甚される可胜性を枛らしたもので、䞀぀のタむプを䜜っお曖昧さを枛らしたす。しかし、emptyの堎合、通過できる倀が倚数あるため、未割り圓おの状態を衚す数を増やす堎合がありたす。

䟋えば、倉数で0ずいう倀を未割り圓おずしお䜿甚しおいたしたが、emptyがtrueを返すため、デフォルト倀ずしおnullを割り圓おるケヌスを考えお芋たしょう、未割り圓おを空の倀(0)ずnullの2぀を考慮しなければならない曖昧なものにしおしたう可胜性がありたす。それに察し、issetは定矩されおいる堎合はnullなのでnullを再床割り圓おるので、䜕の違いもありたせん。nullなので空の倀を割り圓おるこずで、未割り圓おタむプの数を枛らすこずができたす。

emptyの䜿甚をお勧めしない理由

emptyは空の倀を確認するために䜿甚できたすが、emptyは倀が存圚する堎合、各タむプの倀をブヌル型に型倉換しおfalseになった時、emptyはtrueを返したす。 phpのタむプゞャグリングによっお文字列0("0")は、ブヌルに倉換される堎合、falseずなるので、emptyは"0"を空ずみなしたす。 文字列の空の倀""だけを区別できたせん。数で構成された文字列を䜿甚する堎合は、ミスをする可胜性がありたす。 これは他の動的蚀語ずは異なり、phpの特殊な型倉換によっお発生するもので、emptyをよく知らずに䜿甚するずミスする可胜性が高くなるので、空の倀を確認する際は=== 0, === "", === []を䜿甚するこずをお勧めしたす。

emptyを䜿ったら

emptyを䜿甚した堎合、該圓倉数は単䞀タむプで䜿甚され、未割り圓おを空の倀ずする倉数ず仮定しおも䜕の問題もないように組たなければなりたせん。 そうでない堎合は、emptyが持぀倀がどのfalsyの倀かであるかを確認するために、コンテキスト把握およびデバッグを行う手間が䌎いたす。

もしくは、耇数のタむプを䜿甚する堎合、各タむプのデフォルト倀を確認するのではなく、あるタむプのデフォルト倀が䜿甚されおいるかをemptyで刀断できたす。䟋えば、倉数が文字列ず数倀のタむプで定矩されおいる堎合、$var === 0 | $var === ''を䜿甚するこずは明確ですが、コヌドが長くなるので、簡単にemptyを䜿うこずがありたす。フレヌムワヌクなどが利甚者の利䟿性のために耇数のタむプをサポヌトする堎合ではなく、䞀般的な開発領域ではnullを䜿甚するケヌスではなく、必ず耇数のタむプを䜿甚するケヌスはたれです。個人的には、叀いコヌドやラむブラリを䜿甚しない限り、あたり䜿甚しおいたせん。耇数のタむプを䜿甚する堎合は、各プロゞェクトや郚眲ごずにコヌディングスタむル決めるこずをお勧めしたす。

䟋のコヌド

class Conversation
{
    private readonly string $sayMessage;
    private readonly string $receiverName;

    public function setSayMessage(string $message): self
    {
        $this->sayMessage = $message;
        return $this;
    }

    public function withReceiverName(string $name): self
    {
        $this->receiverName = $name;
        return $this;
    }

    public function getConversation(): string
    {
        $this->fillUndefinedOptionalMember();
        $objectPhrase = $this->receiverName === "" ? "" : " to {$this->receiverName}";
        return "Jimmy said{$objectPhrase}, {$this->sayMessage}";
    }

    private function fillUndefinedOptionalMember(): void
    {
        $this->receiverName ??= "";
    }
}

echo (new Conversation)->setSayMessage("Nice to Meet You")->getConversation();
echo PHP_EOL;
echo (new Conversation)->withReceiverName("David")->setSayMessage("Nice to Meet You")->getConversation();
  • withReceiverName メ゜ッドず setSayMessage メ゜ッドを䜿甚しお undefinedのメンバヌに倀を定矩したした。
  • withReceiverName メ゜ッドを䜿甚しない堎合 fillUndefinedOptionalMember メ゜ッドによっお空の文字列が $receiverNameに割り圓おられたす。 したがっお、withReceiverNameはオプションのメ゜ッドです。
  • setSayMessage メ゜ッドを䜿甚しおいない堎合, fillUndefinedOptionalMemberによっおデフォルト倀が割り圓おられないため $sayMessageメンバヌを䜿甚する際に゚ラヌが発生すしたす。 これはわざず゚ラヌを発生させたものであり、setSayMessageは必須メ゜ッドです。
  • private string $receiverName = "";で最初にメンバヌ倉数を宣蚀する際にデフォルト倀を割り圓おおもよいですが、readonlyを䜿甚する堎合は倉数を䞀床だけ割り圓おるこずができたす。そのため、setterで倀を受け取る堎合はデフォルト倀をメンバヌ宣蚀ず同時に割り圓おたせんでした。
  • 名前が䌝わらない堎合は空の文字列であるため、$this->receiverName === ""ずしお、名前が割り圓おられおいるかどうかを確認したした。
  • 䞊蚘のプロセスは、setter メ゜ッドを介しお1に該圓する「倉数のデフォルト倀指定」 → fillUndefinedOptionalMemberメ゜ッドを䜿甚しお、2に該圓する「定矩されおいない堎合、デフォルト倀指定」 → getConversationのリタヌン倀から3に該圓する「ロゞックを展開するのに必芁な倉数がすべお集たった埌、ロゞックの流れを衚すコヌドを実行」の段階に分かれおいたす。
  • php8では、未定矩の倉数はほずんどのphp組み蟌み関数やタむプヒントで゚ラヌを匕き起こし、䞀郚の構文ではWarningレベルのログが生成されたす。Warningは、その構文を無芖しお以降のコヌドを実行したすが、問題が発生する際の凊理を止めないので、未定矩の倉数凊理時にWarningが発生するロゞックを䜜らないようにするず良いでしょう。php9では、未定矩の倉数を䜿甚するず必ず゚ラヌが発生するため、コヌドの実行を確実に停止させるこずができたす。
  • ゚ラヌの原因をより明確にするために、未定矩の倉数が䌝播した堎合には、䟋倖を甚いお「Required Method Not Defined」などのメッセヌゞを投げるコヌドを远加するこずも良いです。

issetの曖昧さ

isset()の括匧内には、倀ぞのアクセスによる゚ラヌは無芖されたす。䟋えば、$ten = 10; var_dump($ten[1]);のようなコヌドを実行するず、$ten[1]がisset関数の匕数でない堎合、数に[キヌ]でアクセスした衚珟で゚ラヌが発生たす。䞀方、isset関数の匕数ずしお$ten = 100; var_dump(isset($ten[1]));のように䜿甚するず、倀のアクセスに関する゚ラヌではなく、単にfalseが返りたす。このようなissetの特性のため、isset内郚に倉な衚珟の倀が入っおも゚ラヌが発生せず、単にfalseを返すこずがありたす。

どの皋床曖昧なのか考えおみたしょう。 配列の特定の芁玠にissetを䜿甚する堎合、isset(倉数[キヌ])の圢になりたす。しかし、この圢態は倉数が存圚しないか、倉数が配列ではないためアクセスできないか、倉数は存圚するのに倉数のキヌに割り圓おられた倀が存圚しないか、いずれの堎合も単に false を返すため、区別が難しい曖昧な衚珟です。trueの堎合は倀が存圚するため倉数[キヌ]は䜿甚できる察象になりたすが、falseの堎合は䜕が誀っおいるのかがこの衚珟だけでは分かりたせん。具䜓的な問題が分かるたでデバッグが必芁です。たた、配列の倀がnullであるためにもfalseを返される可胜性も考えられたす。先ほどissetを倀の存圚を確認する甚途で䜿甚するこずにしたので、この堎合は排陀しお考えおもissetは匕数ずしお受け取る倀の衚珟匏が少しでも耇雑になるず、䜕が間違っおfalseを返したのか分かりにくいずいう問題がありたす。

issetのこのような曖昧さから、これを解決できる代替できるより明確な衚珟があれば、代わりにその機胜を䜿甚するこずをお勧めしたす。

配列の曖昧さを解決

配列の堎合、issetに代わる衚珟ずしお、array_key_existsずいう関数がありたす。この関数の䜿甚方法は、array_key_exists(string|int $key, array $array): boolです。この関数は、配列ずキヌを受け取り、そのキヌが配列内に存圚するかどうかを確認するものです。

最初の匕数が文字列や敎数でない堎合ぱラヌが発生し、2番目の匕数が配列でない堎合も゚ラヌが発生するため、゚ラヌなしでこの関数を実行するず、配列にキヌが存圚するのか配列にキヌが存圚しないのか以倖の様盞がないので、䜕が問題なのか明確に分かりたす。

phpでは、配列が元玠の倀が定矩されおいない堎合、そのキヌも存圚しない構造です。キヌがなければ倀がないのこずで、キヌがあれば倀が䜕でもあるこずです。したがっお、配列においお倀の存圚ではなく、特定のキヌが存圚しないだけでも、「undefined」かどうかを区別できたす。

埓っお、配列内の特定の芁玠の倀の存圚を確認する際には、issetではなく、array_key_existsを䜿甚するこずをお勧めしたす。

倚次元配列の堎合

array_key_existsは配列䞭の䞀次元の元玠に察しおのみ適甚できたす。 倚次元の配列の堎合、array_key_exists(n次元キヌ, 配列[1次元キヌ][2次元キヌ][3次元キヌ]···[n-1次元鍵]の圢匏になりたす。 isset([1次元キヌ][2次元キヌ][3次元キヌ]···[n次元キヌ]) ず異なり、array_key_existsはn次元のキヌにアクセスする前にn-1次元キヌにアクセスできないず゚ラヌが発生したす。issetはアクセスできないか、たたはn次元の配列倀が存圚しないか、nullであればfalseで、倀が存圚するずtrueずなりたす。配列にアクセスできるかどうかは無芖しおもいいですし、最終的に倀の存圚だけ確認すればよい時は、アクセスする過皋での゚ラヌをある皋床無芖できるissetを䜿甚でできたす。䞀方、アクセスできない堎合を明確に確認したい堎合はarray_key_existsを䜿甚したす。

倖郚から䌝達されるデヌタによっお、どのような圢匏の配列が生成されるか分からない堎合、特定の倀の存圚だけを確認したい堎合は、アクセス過皋での゚ラヌをある皋床無芖できるissetを䜿っおもよいず思いたす。ただし、アプリケヌションでプログラマの定矩によっお生成される配列の堎合は、誀ったアクセスであっおも゚ラヌを発生させないissetの代わりに、array_key_existsを䜿甚するこずで、倀の接近過皋で䜕が間違っおいるのか、より分かりやすいから、もっず明確なコヌドを䜜成するこずができたす。もし、array_key_existsではなくissetを必ず䜿わなければならない堎合は、圢態を予枬しにくい配列を䜜るこずで、自分が曞いたコヌドが生成する結果に察するコントロヌルが䞍足しおいる可胜性が高いため、コヌドを間違っお組んでいるか悩んでみたほうがいいです。

倚次元配列においおも、issetよりはarray_key_existsを䜿甚するこずをお勧めしたす。 ただし、時にはプログラマヌの統制以倖の領域で生成される配列であるため、倀の配列の構造ず圢態に察する確信が持おない比范的䟋倖的な堎合にはissetを䜿甚するこずもできたす。

結論

isset

  • issetをnullを確認するのに䜿うのではなく、できる限り倉数が定矩されおいないかどうかを確認するこず䞭心に䜿うようにしたしょう。
  • issetを䜿甚する際は、未定矩の堎合ロゞックを実行しなく、定矩の堎合ロゞックを実行する方匏で䜿わなく、ただ定矩されおいないずきに倀を定矩するために倉数を確認する甚途や、未定矩が未割り圓おを意味する堎合、存圚する倀の未割り圓お倀を蚭定する甚途で䜿甚したしょう。
  • このようにissetを䜿うスタむルを採甚するず、issetを䜿ったコヌドを読む時、nullを確認で解釈する堎合の数を枛らしおより速く明確に理解できるコヌドを䜜るこずができたす。

割り圓おず未割り圓お

  • 割り圓おず未割り圓おを分ける際は、定矩・未定矩で区切るのではなく、空の倀たたはたたNull等デフォルト倀を䜿いたしょう。

配列

  • 怜蚌察象が配列のように倀にアクセスする圢が少しでも耇雑になったら、䜕が問題なのか明確に分かるarray_key_existsような機胜をissetの代わりに䜿いたしょう。
41
18
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
41
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?