LoginSignup
derasado
@derasado (Sado)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

PHP 不正な文字列?エラー

Q&AClosed

解決したいこと

ここに解決したい内容を記載してください。

PHPでエラーがでてしまいます。
恐らく連想配列?あたりがうまくいってないかと思うのですが、まったくわかりませんでした。
教えて頂けると幸いです。

発生している問題・エラー

出ているエラーメッセージを入力
Warning: Illegal string offset 'memoTitle' in /var/www/html/memoapp.php on line 26
1. メモのタイトル:1
[24-Feb-2021 23:23:57 Asia/Tokyo] PHP Warning:  Illegal string offset 'memoBody' in /var/www/html/memoapp.php on line 27

または、問題・エラーが起きている画像をここにドラッグアンドドロップ

該当するソースコード

ソースコードを入力

例)

<?php

function topMenuChoice() {
    echo 'TOP MENU' . PHP_EOL;
    echo '1. メモを登録' . PHP_EOL;
    echo '2. メモリストを表示' . PHP_EOL;
    echo '9. アプリケーションを終了' . PHP_EOL;
    echo '番号を選択してください(1,2,9):';
    return trim(fgets(STDIN));
}

function registerMemo() {
        echo 'MEMOを登録してください。' . PHP_EOL;
        echo '1. メモのタイトル:';
        $memo['memoTitle'] = trim(fgets(STDIN));
        echo '2. メモの詳細:';
        $memo['memoBody'] = trim(fgets(STDIN));
        echo 'メモの登録が完了しました。' . PHP_EOL;
        return $memo;
}

function memoListDisplay($registerMemos) {
    foreach ($registerMemos as $registerMemo) {
        //メモのリスト表示
        echo '登録済みのMEMOを表示します:'. PHP_EOL;
        echo '1. メモのタイトル:' . $registerMemo['memoTitle'] . PHP_EOL; //ここが問題?
        echo '2. メモの詳細:' . $registerMemo['memoBody'] . PHP_EOL; //ここが問題?
        echo '----------' . PHP_EOL;   
    }
    return;
}

$registerMemos = [];

//MEMO MENUの分岐
while (true) {
    echo '1. メモを登録' . PHP_EOL;
    echo '2. メモを表示' . PHP_EOL;
    echo '9. アプリケーションを終了' . PHP_EOL;
    echo '番号を選択してください(1,2,9):';
    $topMenuChoice = trim(fgets(STDIN));

    if ('1' == $topMenuChoice || '1' == $topMenuChoice) {
        //メモを登録
            $registerMemos = registerMemo();
    } elseif ('2' == $topMenuChoice || '2' == $topMenuChoice) {
        //メモリストを表示
        memoListDisplay($registerMemos);
    } elseif ('9' == $topMenuChoice || '9' == $topMenuChoice) {
        //アプリケーションを終了
        break;
    }
}

自分で試したこと

ここに問題・エラーに対して試したことを記載してください。

0

3Answer

最小限度の修正で済ませるのであれば45行目を以下のように修正して下さい。
※ registerMemosは配列を要素に持つ配列になる。

修正前
        //メモを登録
        $registerMemos = registerMemo();
修正後
        //メモを登録
        $registerMemos[] = registerMemo();
1

Comments

  1. @derasado

    Questioner
    rshibasa様
    解決できました!!
    ありがとうございます。

    また、仕組みも理解することができました!
    上記のままだと、$registerMemosという配列の中に、memoキーの中の文字列?が同じmemoキーの中に'memoTitle'と'memoBody'が一緒に入ってしまっていて、foreachが上手く動作しなかった。

    それを、返り値の$registerMemos[]とすることで、それぞれを別の連想配列として配列の中に置いて、foreachで呼び出す。という認識で合っておりますでしょうか・・・?

  2. すでに@amiya-se氏が回答されているようですので(重複した内容となるため)回答は差し控えさせていただきます。なお、困った時にはvar_dump()で変数の中身を確認されるのが良いと思います。https://www.php.net/manual/ja/function.var-dump.php
  3. @derasado

    Questioner
    かしこまりました!
    var_dumpを今後活用したいと思います。
    この度はありがとうございました!

追記 この回答は参考にしないようにご注意下さい。
不十分な検証と中途半端な見識に基づくものであり、
勘違いと見落としも混ざっている為、あてになりません。
憶測で物事を話してはいけませんし、飛ばし読みもいけません。
お仕事の話が来たときはそちらに集中しましょうという悪い見本です。

※「関数の返り値を連想配列で格納できていないこと」が症状の原因です※

以下 参考になりません。
追記 foreach$registerMemosの中の$registerMemoというキーを探しているけど、無いから怒られてると考えられます。そもそも関数名はregisterMemo()だけど戻しているのは$memoなので、異なるという…

手元の環境でphpをコマンドラインで実行できるようにしていないので憶測になりますが、
$memoの宣言が無いのでエラー吐いている。
もしくは
$registerMemoという宣言が無いのでエラー吐いてる。

function registerMemo() {
       $ memo = [];
        処理
       $registerMemo = [];
       return  $registerMemo = [$memo['memoTitle'],$memo['memoBody']];
}

こう書いてみるか、

もしくは、

 foreach ($registerMemos as $memo) {

こう書いてみるかかな。

お仕事のお話が来てしまったので、検証せずに載せてしまいます。
お手数おかけしますがフィードバックしていただけると助かります。

0

Comments

  1. @derasado

    Questioner
    ご回答いただきましてありがとうございます。

    すみません、試してみたのですが、上手くいかなかったようです・・・
  2. すみません、お手数おかけしました。
    検証できていない回答をしてしまったことをお詫びいたします。

    今気づきましたが、下の書き方だと上書きになるかと思います。
    $registerMemos = registerMemo();

    以前配列のご質問があった際に下の三つの違い
    $registerMemos = [];
    $registerMemos[0]
    $registerMemos[]
    宣言、添え字、添え字が空だと上に積んでいく
    というのをお伝えさせていただいたと思います。
    変数や配列についてもういちど参考URLをご覧になることをおすすめいたします。

    しっかり検証したうえでお答え差し上げたいのですが、
    当方の環境だとコマンドプロンプトでphpのプログラムを実行することができません。

    WEBアプリに移行されるというお話でしたが、しばらくphpのみで続けられるようであれば
    今回のようなご迷惑をおかけしないために検証環境が整った上で、
    時間にゆとりがあるときのみ回答させていただくことにいたします。
    貴重なお時間を浪費させてしまい申し訳ございませんでした。
  3. @derasado

    Questioner
    amiyaさん

    こちらこそ何度もお時間を頂戴してご回答頂いていることに感謝です・・・!
    いつも励みになっております。ありがとうございます。

    配列や変数についてもう一度復習してみます!
    とんでもございません・・・
    こちらこそお忙しいところいつも、すみませんでした!

    DB導入→HTMLで表へいく段階に向かっているのでその際はまた
    お時間の許す限りでどうぞ宜しくお願い致します。
  4. @rshibasaさんが答えてくれるとは思いますが…

    連想配列は、「配列の中に配列」が入ることを言います。
    [ ['りんご','apple'] , ['ばなな','banana'] ]

    上にも書いたのですが、
    $registerMemos = registerMemo();
    この書き方だと上書きになるので連想配列として格納されないはずです。

    僕はフロントから覚えたので、
    その順番のロードマップのメリットはよくわからないのですが、
    WEBアプリが形になることを心待ちにしております。
  5. @derasado

    Questioner
    ありがとうございます。

    ちなみにですが途中で$registerMemos = [];
    で$registerMemosに空の配列を代入していると思うのですが、それでも上書きされているのでしょうか?

    空の配列に、連想配列がそれぞれ配列として入ってくれるかと思っていたのですが・・・

    空の配列が返り値の連想配列によって消されている。ということでしょうか?

    $registerMemos[] = registerMemo(); //代入された空の配列の中に返り値を入れる。
    $registerMemos = registerMemo(); //空の配列を上書き(無視)して、新しく返り値の変数を代入する。

    こちらの認識で合っておりますでしょうか?

  6. 直近のコメントに対するお返事ですが、

    >PHPの配列と関数・変数の関係についておしえてください。
    https://qiita.com/derasado/questions/341a8fe27bf18efb198a

    以前ご説明差し上げたこれと似たような質問をされていますよ。
    説明するよりコード実行した方が恐らく理解が進むかと。
    コードを実行し出力結果や変数等の挙動をご自身で確認した後で、
    もう一度、上に記した過去の質問の回答や他の方の回答を読み返してみてください。

    以下気合い入れて書いた検証用コード。※空宣言の検証コードも足しました。

    <?php
    // 0-0.これが空宣言変数の中身
    $kensho;
    var_dump($kensho). PHP_EOL;
    echo $kensho. PHP_EOL; //何もないように見える
    echo '0-0.これが空宣言変数の中身' . PHP_EOL;
    // 0-1.これが空宣言配列の中身
    $kensho = [];
    var_dump($kensho). PHP_EOL; //中身ゼロの配列がある
    echo $kensho. PHP_EOL; // Arrryが返る
    echo '0-1.これが空宣言配列の中身' . PHP_EOL;

    // 1.これが変数の上書き
    $kensho = [];
    $kensho = 'hoge';
    $kensho = 'fuga';
    $kensho = 'piyo';
    var_dump($kensho). PHP_EOL;
    echo $kensho. PHP_EOL;
    echo '1.これが変数の上書き' . PHP_EOL;

    // 2.これが配列と要素の取り出し(添え字)and 変数の上書き
    $kensho = [];
    $kensho = ['hoge','hoge-san'];
    $kensho = ['fuga','fuga-dono'];
    $kensho = ['piyo','piyo-rin'];
    var_dump($kensho). PHP_EOL;
    echo $kensho. PHP_EOL;
    echo $kensho[0]. PHP_EOL;
    echo $kensho[0][0]. PHP_EOL;
    echo '2.これが配列と要素の取り出し(添え字)and 変数の上書き' . PHP_EOL;

    // '3.これがキー付き配列と要素の取り出し(キー)and 配列の上書き
    $kensho = [];
    $kensho = ['id'=>'hoge','name'=>'hoge-san'];
    $kensho = ['id'=>'fuga','name'=>'fuga-dono'];
    $kensho = ['id'=>'piyo','name'=>'piyo-rin'];
    var_dump($kensho). PHP_EOL;
    echo $kensho. PHP_EOL;
    echo $kensho[0]. PHP_EOL; //表示されない
    echo $kensho['id']. PHP_EOL;
    echo '3.これがキー付き配列と要素の取り出し(キー)and 配列の上書き' . PHP_EOL;

    // 4.これが連想配列とキー付き配列の取り出し
    $kensho = [];
    $kensho[] = ['id'=>'hoge','name'=>'hoge-san'];
    $kensho[] = ['id'=>'fuga','name'=>'fuga-dono'];
    $kensho[] = ['id'=>'piyo','name'=>'piyo-rin'];
    var_dump($kensho). PHP_EOL;
    echo $kensho. PHP_EOL;
    echo $kensho['0']. PHP_EOL;
    echo $kensho['id']. PHP_EOL; //表示されない
    echo $kensho[0]['id']. PHP_EOL;
    echo '4.これが連想配列とキー付き配列の取り出し' . PHP_EOL;

    // foreachと連想配列の確認用関数
    function memoListDisplay($katamari) {
    var_dump($katamari). PHP_EOL;
    echo '連想配列で受け取っていることを確認' . PHP_EOL;
    foreach ($katamari as $komagire) {
    var_dump($komagire). PHP_EOL;
    echo '連想配列から配列を一つずつ取り出し' . PHP_EOL;
    echo '1. id:' . $komagire['id']. PHP_EOL;
    echo '2. name:' . $komagire['name']. PHP_EOL;
    }
    return;
    }

    // 5.ループさせた結果がこれ。関数の引数は名づけ自由、foreach as の後も名づけ自由
    memoListDisplay($kensho);
    echo '5.ループさせた結果がこれ。関数の引数は名づけ自由、foreach as の後も名づけ自由' . PHP_EOL;
    echo '関数の引数とforeachでループさせる連想配列の名称だけは一致させる' . PHP_EOL;
    echo '自由なんだけど、ある程度揃えておかないと分かりづらい' . PHP_EOL;
    var_dump($katamari). PHP_EOL;//
    var_dump($komagire). PHP_EOL;//
    echo '関数の外では参照できない。これがスコープの概念' . PHP_EOL;

    // 6.検証、連想配列にキーを付けられるか。いけるらしい
    $kensho = [];
    $kensho[] = ['wan'=> ['id'=>'hoge','name'=>'hoge-san']];
    $kensho[] = ['nyan'=> ['id'=>'fuga','name'=>'fuga-dono']];
    $kensho[] = ['koke'=> ['id'=>'piyo','name'=>'piyo-rin']];
    var_dump($kensho). PHP_EOL;
    echo $kensho. PHP_EOL;
    echo $kensho[0]. PHP_EOL;
    echo $kensho[0]['wan']. PHP_EOL;
    echo $kensho[0]['wan']['id']. PHP_EOL;
    echo '6.検証、連想配列にキーを付けられるか。いけるらしい' . PHP_EOL;

    // 7.まとめてかけるよっ、でも使うために関数を変える必要が…
    $kensho = [];
    $kensho[] = [
    'wan'=> ['id'=>'hoge','name'=>'hoge-san'],
    'nyan'=> ['id'=>'fuga','name'=>'fuga-dono'],
    'koke'=> ['id'=>'piyo','name'=>'piyo-rin'],
    ];
    var_dump($kensho). PHP_EOL;
    echo $kensho. PHP_EOL;
    echo $kensho[0]. PHP_EOL;
    echo $kensho[0]['wan']. PHP_EOL;
    echo $kensho[0]['wan']['id']. PHP_EOL;
    memoListDisplay($kensho);
    echo '7.まとめてかけるよっ、でも使うために関数を変える必要が…' . PHP_EOL;
    echo '変数、配列、連想配列、関数、どう動くか確認してね!' . PHP_EOL;


    以下 学習補助
    foreachが上手く動かなかった理由についてはここを見てみてください。php公式です。
    https://www.php.net/manual/ja/control-structures.foreach.php
  7. @derasado

    Questioner
    amiyaさん
    検証用コードありがとうございます!!
    ここまでして頂けて申し訳ございません。
    とても親切に助かります!!

    おかげさまで検証して理解を深めることができました。
    文章で理解するのではなく、やはり自分で検証することで理解はとても深まるのですね。

    1、変数の上書きで、空の配列を代入していても次の変数の代入が配列の中に入るわけではなく、上書きされてしまう点理解できました!

    2、取り出しの際に、配列はechoで呼び出しできない点、また配列は1つずつしか呼び出しできない点を知ることができました!

    3、連想配列と連想配列の取り出しについての理解

    4、配列の中に連想配列を順番に入れていく方法、そしてその連想配列を取り出す際は配列の中に順番に配列として入っているので、0の配列の値hogeを取り出したい場合は連想配列になっているので、0の配列のidキーを指定することでhogeを取り出せる。
    $kensho[ここに取り出したい配列][ここに取り出したい連想配列の値のキー]
    ※連想配列、配列の中身は「,」で区切って配列の中に複数入れられる。

    5、実引数の渡してからの動き、foreachの挙動の理解(受け取った配列の中の連想配列を0の配列から順にループする。)。また、var_dumpを使うことでいま変数の中身がどのようなものなのか確認して混乱せずに理解できることに気付けきました!

    6、配列の中に配列を入れて、その配列の中の配列にキーをつけて、おけるんですね!
    配列についてようやく理解ができるようになりました!
    ※$kensho[配列の中の番号orキー][連想配列の呼び出したい値のキー]

    7、より連想配列の使い方について深く知ることができました!

    この検証コードとてもわかりやすいので、これから迷った際は今後もしばらく使用させて頂きます!
    お時間奪ってしまい申し訳ありませんが本当にありがとうございます!
  8. お役に立てたなら何よりです。どうぞお使い下さいませ。
    上のコメントに0-0と0-1もこっそり足してあります。

    $kensho; //null
    $kensho = []; //Array

    おそらくこのような結果になりますが、
    ご自身でコードを実行してvar_dump(変数名)して確認してみてくださいね。

    こちらとしてもお伝えすることで何となく使っていたコードへの理解が深まりました。
    ありがとうございます。そろそろお暇させていただきますね。
    ではでは。
  9. @derasado

    Questioner
    追加もありがとうございますm(__)m
    null、Arrayとでました!
    色々とありがとうございました!

$registerMemosvar_dumpで出力してみるとわかりますが、$registerMemosは一次元の連想配列。

foreach ($registerMemos as $registerMemo) {
...
}

ここで一次元の連想配列の値を取り出しているため、$registerMemoの型は文字列。

$registerMemo['memoTitle']
$registerMemo['memoBody']

文字列に対して連想配列キーによる要素アクセスを行おうとしているため、WORNINGが発生している(文字列は数値インデックスによる要素アクセスしか認められていない)。

0

Comments

  1. @derasado

    Questioner
    ご回答いただきましてありがとうございます。

    すみません、ご指摘頂き考えたのですがよくわかりません。

    つまりどこが問題でしょうか?

Your answer might help someone💌