[PHP] Call to a member function on array / インスタンスを定義しているのにメソッドを呼び出せない

はじめに
-------
リファクタリング中に本エラーに遭遇しました。
解消に関してはいくつか回答がありましたが、解消まで時間がかかってしまったので備忘録として残したいと思います。

:::note info
**エラーメッセージの意味**
Fatal error: Uncaught Error: Call to a member function getNewCardInfo() on array
「getNewCardInfo()メソッドをインスタンスではなくarrayで呼んでいますよ」って意味です。
:::


やりたいこと
-------

エラーを解消して、インスタンスのメソッドを実行したい
`$cardInfo->getNewCardInfo($playerNewCard);`

```php
//インスタンス
$cardInfo = new CardInfoGetter();

while (true) {
            if ($input === 'Y') {
                $playerNewCard = $player->drawOneCard($deck);
                //ここでインスタンスのメソッドを実行したいがエラーになる
                $playerNewCardsInfo = $cardInfo->getNewCardInfo($playerNewCard);
                
                echo 'あなたの引いたカードは' . $playerNewCardsInfo['suite'] . 'の' . $playerNewCardsInfo['number'] . 'です。' . PHP_EOL;

                $this->playerCardPoint += $playerNewCard[0]->getCardPoint();
                echo 'あなたの現在の得点は' . $this->playerCardPoint . 'です。';
                if ($this->playerCardPoint >= 22) {
                    echo 'あなたの手札が21点を超えたので、ディーラーの勝ちです！' . PHP_EOL;
                    return;
                }
                echo 'カードを引きますか？（Y/N）' . PHP_EOL;
                $input = trim(fgets(STDIN));
```

やったこと
-------
いくつかの記事にあたると、インスタンス生成されてないためにメソッドが実行できてないとあったので、if文の中でインスタンスを生成するとエラーが解消された

```php
//$cardInfo = new CardInfoGetter();
//もともと外に定義していたインスタンスをif文内のメソッド実行直前に定義

while (true) {
            if ($input === 'Y') {
                //インスタンス生成
                $cardInfo = new CardInfoGetter();
                $playerNewCard = $player->drawOneCard($deck);
                //ここでインスタンスのメソッドを実行　=> 今回はエラーにならなかった
                $playerNewCardsInfo = $cardInfo->getNewCardInfo($playerNewCard);
                
```

ここで、「なぜ、`$cardInfo = new CardInfoGetter();`をif文の外に定義するとエラーが発生するのか？」と考えましたが、問題の本質ではなかったです


<font color="red">実はインスタンス生成とインスタンスのメソッド実行の間にもコードがあり、そこに問題がありました。。
</font>

原因
------
<font color="red">インスタンスのメソッドを実行する前に`$cardInfo`を書き換えていた。</font>
`$cardinfo = ['suite' => 'ハート','number' => 'A']`の処理を行っていた。

なので、`['suite' => 'ハート','number' => 'A']のメソッドを実行する`とおかしなことになってた訳です。


```php
$cardInfo = new CardInfoGetter();

//　foreachで$cardInfoを使っていて、値を書き換えていた。
//　$cardinfo = ['suite' => 'ハート','number' => 'A']
foreach ($playerCardsInfo as $cardInfo) {
            echo 'あなたの引いたカードは' . $cardInfo['suite'] . 'の' . $CardInfo['number'] . 'です。' . PHP_EOL;
        }

        echo 'ディーラーの引いたカードは' . $dealerCardsInfo[0]['suite'] . 'の' . $dealerCardsInfo[0]['number'] . 'です。' . PHP_EOL;
        echo 'ディーラーの引いた2枚目のカードはわかりません。' . PHP_EOL;

        echo 'あなたの現在の得点は' . $this->playerCardPoint . 'です。';
        echo 'カードを引きますか？（Y/N）' . PHP_EOL;
        $input = trim(fgets(STDIN));

        while (true) {
            if ($input === 'Y') {
                $playerNewCard = $player->drawOneCard($deck);

                //['suite' => 'ハート','number' => 'A']のメソッドを実行 
                // => Fatal error: Uncaught Error: Call to a member function getNewCardInfo() on array 
                $playerNewCardsInfo = $cardInfo->getNewCardInfo($playerNewCard);

                echo 'あなたの引いたカードは' . $playerNewCardsInfo['suite'] . 'の' . $playerNewCardsInfo['number'] . 'です。' . PHP_EOL;

                $this->playerCardPoint += $playerNewCard[0]->getCardPoint();
                echo 'あなたの現在の得点は' . $this->playerCardPoint . 'です。';

                if ($this->playerCardPoint >= 22) {
                    echo 'あなたの手札が21点を超えたので、ディーラーの勝ちです！' . PHP_EOL;
                    return;
                }

                echo 'カードを引きますか？（Y/N）' . PHP_EOL;
                $input = trim(fgets(STDIN));
            }
```

解決策
------
**インスタンスの名前を変えてあげました。**
$playerCardsInfoの中は `[['suite' => 'ハート','number' => 'A'],['suite' => 'ハート','number' => 'A']]` となっていました。
なので `$playerCardsInfo as $cardInfo` はしっくりくるので、代わりにインスタンスの名前を`$cardInfoObj`に変更しました。
```変更後.php
$cardInfoObj = new CardInfoGetter();

foreach ($playerCardsInfo as $cardInfo) {
            echo 'あなたの引いたカードは' . $playerCardInfo['suite'] . 'の' . $playerCardInfo['number'] . 'です。' . PHP_EOL;
        }

$playerNewCardsInfo = $cardInfoObj->getNewCardInfo($playerNewCard);
```

反省
--------
<font color = 'red'>エラーメッセージを理解できていなかった！！</font>
エラーメッセージを理解していればすぐに解決する不具合だったなと強く思いました。

>Fatal error: Uncaught Error: Call to a member function getNewCardInfo() on array
「配列のfunctionを呼び出していますよ！」

参考
---------
[https://stackoverflow.com/questions/51263199/calling-member-function-on-array](https://stackoverflow.com/questions/51263199/calling-member-function-on-array)
この一文で原因に気づきました。。
>In PHP, strings (and other "basic types" like arrays) are not objects, so you can't call any methods on them.