1
1

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.

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

Posted at

はじめに

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

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

やりたいこと

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

//インスタンス
$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文の中でインスタンスを生成するとエラーが解消された

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

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

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

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

原因

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

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

$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);

反省

エラーメッセージを理解できていなかった!!
エラーメッセージを理解していればすぐに解決する不具合だったなと強く思いました。

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

参考

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.

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?