LoginSignup
2
0
お題は不問!Qiita Engineer Festa 2023で記事投稿!

PHPとJavaScriptで未定義の配列のキーにアクセスしたときのエラーを防ぐ

Last updated at Posted at 2023-07-07

未定義の配列のキーにアクセスしたときの判定処理です。
nullやundeined判定の記事はたくさんありますが、phpとjsの未定義の配列キーに関してまとめます。

PHP:undefined array key

未定義の配列のキーにアクセスしようとしたとき。

array.php
$array = array('key1' => 'value1', 'key2' => 'value2');

echo $array['key1'];  // 出力: value1
echo $array['key3'];  // 警告: Undefined array key: key3

このときKey3は未定義なので、

Warning: Undefined array key: key3 in array.php on line ~
Warning: Trying to access array offset on value of type null in ~

というようなエラーがphpのログに出るかと思います。
処理は継続されますが、その後の動作に影響を与える可能性があります。
PHP8から、このエラーはNoticeレベルからWarningとなりました。

判定処理

isset()やarray_key_exsit()を使います。

array_judge.php
$array = array('key1' => 'value1', 'key2' => 'value2');

if (isset($array['key3'])) {
    echo $array['key3'];
} else {
    echo 'キーが存在しません';
}

// または

if (array_key_exists('key3', $array)) {
    echo $array['key3'];
} else {
    echo 'キーが存在しません';
}

null判定→これはNG

後述するJSでの処理と混同しがちですが、null判定ではこのエラーは防げません。

array_NG.php
if ($array['key3'] === null) {
    echo 'キーが存在しません';
} else {
    echo 'キーが存在します';
}

これはキーにアクセスしているのでエラーとなりますが、判定処理は可能です。
ちなみに、phpに === undefined という判定はありません。

NG.php
if (!$array['key3']) {
    echo '偽です';
} else {
    echo '真です';
}

これもだめです。要素がfalseの時はいいですが、未定義の場合、エラーが発生します。

JavaScript:undefined

JSでは未定義の配列キーにアクセスするとundefinedとなります。処理は止まりません。
その後の処理に影響を与えるので、手前でエラー処理しておくのがいいでしょう。

array1.js
var array = ['value1', 'value2'];

console.log(array[0]);  // 出力: value1
console.log(array[2]);  // 出力: undefined

// strictモードが有効な場合
'use strict';
console.log(array[0]);  // 出力: value1
console.log(array[2]);  // ReferenceError: array is not defined

Strictモード(厳格モード)は、JavaScriptの実行コンテキスト内でコードをより厳密に解釈するためのモードです。Strictモードを有効にすると、いくつかの既存のJavaScriptの不具合や意図しない動作をエラーとして検出することができます。
by ChatGPT

判定処理

judge.js
var array = ['value1', 'value2'];

if (array[2] === undefined) {
  console.log('要素は未定義です');
} 

//または
if (2 in array) {
  console.log(array[2]);
} else {
  console.log('要素が存在しません');
}

// または
if (array.hasOwnProperty(2)) {
  console.log(array[2]);
}else {
  console.log('要素が存在しません');
}

未定義の配列キーはundefinedなので、

judge.js
if(array[2] == null ) {
    console.log('要素はnullまたはundefinedです');
}

==(等価演算子)は型の変換を行うため、nullもundefinedも判定は同じ。
これでも判定は可能だが、
配列の要素がfalseなどの偽の値である場合にも条件が真となってしまいます。

コメントにてご指摘いただきました

オブジェクトの場合

object.js
var response = { name: 'Taro' };

if ('age' in response) {
  console.log(response.age);
} else {
  console.log('プロパティが存在しません');
}

// または

if (response.hasOwnProperty('age')) {
  console.log(response.age);
} else {
  console.log('プロパティが存在しません');
}

nullとundefinedの判定(等価演算子と厳密等価演算子)

コメントに投稿いただいたこちらの記事がわかりやすいです。

結果がnullの場合と、何もない(未定義)場合では、nullとundefinedの判定にどのような違いがあるのか、
==と===を比較。

array.js
//要素がnull
var response1 = { result: null };
console.log(response1.result === null);  // 出力: true
console.log(response1.result === undefined);  // 出力: false

//未定義の場合
var response2 = { };
console.log(response2.result === null);  // 出力: false
console.log(response2.result === undefined);  // 出力: true

nullとundefinedでは型が違うので、===を使うときは、nullとundefinedの判定をわけるべき。

型判定しない場合↓

array2.js
var response1 = { result: null };
console.log(response1.result == null);  // 出力: true
console.log(response1.result == undefined);  // 出力: true

var response2 = {};
console.log(response2.result == null);  // 出力: true
console.log(response2.result == undefined);  // 出力: true

どちらも同じ結果になりました。
上にも書いたように値がfalseの場合も、trueとなってしまうので、厳密比較したほうがいいでしょう。

おまけ

以下の場合どうなるでしょう?

NG.js
var array = ['value1', 'value2'];
if (!array[3]) {
    console.log('偽です');
} else {
    console.log('真です');
}

未定義なので、「偽です」とでます。
key3がnull の場合も[偽です]となります。
falseのときも「偽です」となるので、あいまい比較== と同じですね。
0のときも「偽です」となるので、注意が必要ですが、これのほうが便利ですね。
でもちゃんと厳密比較しましょう。

2
0
6

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
2
0