LoginSignup
0
0

More than 3 years have passed since last update.

php・可変変数に配列を渡す

Posted at

環境
初書:2020/09/27
PC:macOS 10.15.7
php 7.4.10

前置き

PHPで可変変数を扱う時があったのだが、その時にかなり手こずったのでメモ。

前提

可変変数の知識

コード(失敗例)

index.php
class cls {
    public string $str1;
    public string $str2;
    public function __construct(){
        $this->str1 = "aa";
        $this->str2 = "bb";
    }
}

$ouc = new cls();

とりあえずクラスを用意して、インスタンスした。
そしてこの後、str変数にアクセスしたいのだが、この時に少し変わったことをする。

index.php
$arr[] = "str1";
$arr[] = "str2";

$ouc->$arr[0] = "cc";

何をしたいかというと、$arr[0] = "str1"、つまり$ouc->str1 = "cc";を行おうとした。
一見問題なく実行できそうだが、実はnoticeが発生する。

PHP Notice: Array to string conversion in php

これは配列を文字列として扱おうとした際に起こるエラーである。
だが、パッと見では特に不具合がある場所はない。

エラーの原因

原因自体は単純で、構文の解析方法が思っているのと違うということ。
PHP7以降の構文解析は、

$ouc->$arr[0] = "cc";
      ¯¯¯¯           // 1
¯¯¯¯¯¯¯¯¯¯¯¯¯        // 2

という順番になる。
つまり、$arr (=Array。配列なので)を先に返し、
$ouc->Array[0]ccを代入しようとしたのである。(そして実際に代入した)
そのため、var_dump($ouc)を行うと、

object(cls)#1 (3) {
  ["str1"]=>
  string(2) "aa"
  ["str2"]=>
  string(2) "bb"
  ["Array"]=>
  array(1) {
    [0]=>
    string(2) "cc"
  }
}

という形になる。

対処法

可変変数の別の記述方法である

$ouc->{$arr[0]} = "cc";

という風に、全体を{}で括って正しい順番で解析してもらうか、一旦別の変数に置く。

終わりに

このバグに遭遇した場合、(構文解析の順番を知らない場合は)エラー文をみてもこれが原因だということに気付けない上に、エラー箇所より前の時点でログを出しても特に見つからない1ので(もちろん、あとでvar_dumpするとすぐにわかるのだが)、頭の片隅に入れておいてもいいかもしれない。

参考サイト


  1. $arr[0]単体でechoしても、clsをvar_dumpしても気付かないし、issetしても…falseになるから気付くかもしれない。自分はエラーに気を取られて戻り値が来ている事に気付いてなかった。 

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