За последние 24 часа нас посетили 17115 программистов и 1596 роботов. Сейчас ищет 1271 программист ...

Illegal string offset

Тема в разделе "PHP для новичков", создана пользователем abutan, 25 мар 2019.

Метки:
  1. abutan

    abutan Новичок

    С нами с:
    25 мар 2019
    Сообщения:
    10
    Симпатии:
    0
    Доброго времени суток всем.
    Проблема вот какая - есть вот такой массив
    PHP:
    1. (
    2.     [1] => Array
    3.         (
    4.             [name] => Желаемая высота забора (м)
    5.             [answers] =>
    6.             [multiple_ans] => 2
    7.         )
    8.  
    9.     [2] => Array
    10.         (
    11.             [name] => вопрос2
    12.             [answers] => ответ 2|ответ 2.2
    13.             [multiple_ans] => 0
    14.         )
    15.  
    16. )
    начинаю его обрабатывать
    PHP:
    1. foreach ($calc as $item => $value) {
    2.     // и тут выполняю разные действия  ...
    3.    $mas_answers = explode('|', $value['answers']);
    4. }
    И всюду где использую $value['name'] или 'answers' или 'multiple_ans' получаю Illegal string offset 'name' или 'answers' и тд
    Сам смысл ошибки я понимаю. Вместо массива оказалась строка, но , блин $value имеет вот такой вид
    PHP:
    1. (
    2.     [name] => Желаемая высота забора (м)
    3.     [answers] =>
    4.     [multiple_ans] => 2
    5. )
    6.  
    7. (
    8.     [name] => вопрос2
    9.     [answers] => ответ 2|ответ 2.2
    10.     [multiple_ans] => 0
    11. )
    Как же мне тогда к ним обращаться ?
    Подскажите в чем я неправ.
    Заранее благодарен.
     
  2. Artur_hopf

    Artur_hopf Активный пользователь

    С нами с:
    7 май 2018
    Сообщения:
    2.264
    Симпатии:
    405
    Покажи массив свой $calc.

    Что то ты долго, не массив у тебя то что ты там написал, вот так можно:
    PHP:
    1. $calc = array(
    2.   1 => array(
    3.       'name' => 'Желаемая высота забора (м)',
    4.       'answers' => '',
    5.       'multiple_ans' => 2,
    6.   ),
    7.   2 => array(
    8.       'name' => 'вопрос2',
    9.       'answers' => 'ответ 2|ответ 2.2',
    10.       'multiple_ans' => 0,
    11.   )
    12. );
    13. foreach ($calc as $item => $value) {
    14.   // и тут выполняю разные действия  ...
    15.     var_dump(explode('|', $value['answers']));
    16. }
     
    #2 Artur_hopf, 25 мар 2019
    Последнее редактирование: 25 мар 2019
  3. abutan

    abutan Новичок

    С нами с:
    25 мар 2019
    Сообщения:
    10
    Симпатии:
    0
    PHP:
    1. (
    2.     [1] => Array
    3.         (
    4.             [name] => Желаемая высота забора (м)
    5.             [answers] =>
    6.             [multiple_ans] => 2
    7.         )
    8.     [2] => Array
    9.         (
    10.             [name] => вопрос2
    11.             [answers] => ответ 2|ответ 2.2
    12.             [multiple_ans] => 0
    13.         )
    14. )
     
  4. Babka_Gadalka

    Babka_Gadalka Активный пользователь

    С нами с:
    16 фев 2019
    Сообщения:
    162
    Симпатии:
    23
    Адрес:
    Москва, Пушкина, Избушкина, 2й этаж душечка.
    Тс, не смущает тот факт, что ты в конце концов, в каждой своей залитой данными переменные, результат получишь по ласт проходу массива?
    --- Добавлено ---
    PHP:
    1. $a = [1,2,3,4];
    2.  
    3. foreach ( $a AS $b ) { $c = $b; }
    4.  
    5. print_r ( $c );
    --- Добавлено ---
    Что получим ? 1 ? 2 3 ?
     
  5. abutan

    abutan Новичок

    С нами с:
    25 мар 2019
    Сообщения:
    10
    Симпатии:
    0
    В данный момент меня смущает ошибка
    Illegal string offset
     
  6. Artur_hopf

    Artur_hopf Активный пользователь

    С нами с:
    7 май 2018
    Сообщения:
    2.264
    Симпатии:
    405
    @abutan ну не массив у тебя это потому что.
     
  7. abutan

    abutan Новичок

    С нами с:
    25 мар 2019
    Сообщения:
    10
    Симпатии:
    0
    А можно как то поразвернутей )))
    Как мне к этому "не массиву" обращаться
     
  8. sobachnik

    sobachnik Старожил

    С нами с:
    20 апр 2007
    Сообщения:
    3.380
    Симпатии:
    13
    Адрес:
    Дмитров, МО
    Сложно угадать, не видя всей картины. Ну, например, возможно вы обращаетесь к переменным не внутри цикла { ... } а где-то вообще в другом месте. Мы же не знаем :)

    После того, как вы написали
    Код (Text):
    1. $mas_answers = explode('|', $value['answers']);
    Массив ответов появился в переменной $mas_answers, а в $value['answers'] - там как была строка текста, так и осталась.

    И да, а что будет, если пользователь в комментарии поставит символ вертикальной черты | ? :))) В PHP есть штатные функции для преобразования массива в строку (для сохранения в базе данных или в файле) и для обратного преобразования строки в массив. При этом, PHP позаботится о том, чтобы не зависимо от пользовательского ввода у вас элементы массива остались такими, какими должны быть. Например, посмотрите функции
    https://www.php.net/manual/ru/function.serialize.php
    https://www.php.net/manual/ru/function.unserialize.php
     
  9. abutan

    abutan Новичок

    С нами с:
    25 мар 2019
    Сообщения:
    10
    Симпатии:
    0
    PHP:
    1. <form action="#" method="post">
    2.             <?php
    3.             foreach($calc as $index => $value){
    4.                 $mas_answers = explode('|', $value['answers']);
    5.                 echo '<div class="tabs_block" tabid="'.$index.'"';
    6.                 if($index!=1){
    7.                     echo ' style="display:none;"';
    8.                 }
    9.                 echo '>
    10.                  <div class="input_form">
    11.                      <p>Вопрос:</p>
    12.                      <div class="input_form">
    13.                          <input class="form-control" name="question" type="text" id="response_options" placeholder="" value="'.addslashes($value['name']).'" autocomplete="off"><br>
    14.                          <span class=podkomment >Например: "Выберите тип материала"</span>
    15.                      </div>
    16.                  </div>
    17.                <hr>
    18.                <h2>Варианты ответов:</h2>';
    19.                 if(count($mas_answers)==0){
    20.                     echo '<div class="input_form answer_input" attr="1" quest="'.$index.'">
    21.                  <p>1.</p><a href="javascript:void(0);" class="answer_remove"></a>
    22.                  <div class="input_form">
    23.                      <input class="form-control" type="text" name="answer" autocomplete="off" placeholder="Вариант ответа #1" value="">
    24.                  </div>
    25.              </div>';
    26.                 }
    27.                 else{
    28.                     foreach($mas_answers as $nom=>$answers){
    29.                         $nom_real=$nom+1;
    30.                         echo '<div class="input_form answer_input" attr="'.($nom_real).'" quest="'.($nom_real).'">
    31.                      <p>'.($nom_real).'.</p><a href="javascript:void(0);" class="answer_remove"></a>
    32.                      <div class="input_form">
    33.                          <input class="form-control" type="text" name="answer" autocomplete="off" placeholder="Вариант ответа #'.($nom_real).'" value="'.$answers.'">
    34.                      </div>
    35.                  </div>';
    36.                     }
    37.                 }
    38.  
    39.  
    40.                 echo '<a href="javascript:void(0);" class="right_add_content">Добавить ещё</a>
    41.              <hr>
    42.              <h2>Возможность выбора:</h2>
    43.              <input type="radio" name="multiple_ans" id="one'.$index.'" autocomplete="off" value="0"';
    44.                 if($value['multiple_ans']==0) echo ' checked="checked"';
    45.                 echo '><label for="one'.$index.'">Можно выбрать только один ответ (radiobutton)</label><br>
    46.              <input type="radio" name="multiple_ans" id="two'.$index.'" autocomplete="off" value="1"';
    47.                 if($value['multiple_ans']==1) echo ' checked="checked"';
    48.                 echo '><label for="two'.$index.'">Можно выбрать несколько вариантов (checkbox)</label><br>
    49.              <input type="radio" name="multiple_ans" id="thr'.$index.'" autocomplete="off" value="2"';
    50.                 if($value['multiple_ans']==2) echo ' checked="checked"';
    51.                 echo '><label for="thr'.$index.'">Нужно вводить данные (input)</label>
    52.              <hr>
    53.            </form>
    54.        </div>';
    55.             }
     
  10. sobachnik

    sobachnik Старожил

    С нами с:
    20 апр 2007
    Сообщения:
    3.380
    Симпатии:
    13
    Адрес:
    Дмитров, МО
    Чтобы совсем всё понятно было - после <?php и перед foreach добавьте ещё строку
    PHP:
    1. var_dump($calc); exit;
    и опубликуйте здесь, что оно выведет
     
  11. abutan

    abutan Новичок

    С нами с:
    25 мар 2019
    Сообщения:
    10
    Симпатии:
    0
    PHP:
    1. array(2) { [1]=> array(3) { ["name"]=> string(47) "Желаемая высота забора (м)" ["answers"]=> string(0) "" ["multiple_ans"]=> string(1) "2" } [2]=> array(3) { ["name"]=> string(13) "вопрос2" ["answers"]=> string(27) "ответ 2|ответ 2.2" ["multiple_ans"]=> string(1) "0" } }
     
  12. Babka_Gadalka

    Babka_Gadalka Активный пользователь

    С нами с:
    16 фев 2019
    Сообщения:
    162
    Симпатии:
    23
    Адрес:
    Москва, Пушкина, Избушкина, 2й этаж душечка.
    Хотите прикол ?
    начало все норм кроме
    после string перебираем в foreach
    PHP:
    1. foreach($mas_answers as $nom=>$answers){
     
  13. sobachnik

    sobachnik Старожил

    С нами с:
    20 апр 2007
    Сообщения:
    3.380
    Симпатии:
    13
    Адрес:
    Дмитров, МО
    @abutan Этот код с такими исходными данными (таким массивом $calc) - должен работать без ошибок. Для эксперимента, запустил его у себя, создав массив перед перебором в цикле. У меня этот код из этого массива успешно сгенерировал html.
    Посмотрите внимательно на текст сообщения об ошибке, которую выдаёт PHP - там указывается файл и номер строки, на которой произошла ошибка. Возможно, она происходит где-то в другом месте?

    У вас есть ошибка в вёрстке - в самом начале вы открываете <form> за пределами цикла, а закрываете </form> внутри цикла (то есть открывающий тег будет один, а закрывающих будет столько же, сколько элементов в массиве $calc). Но ошибка вёрстки никак не влияет на появление сообщения "Illegal string offset"
     
  14. Babka_Gadalka

    Babka_Gadalka Активный пользователь

    С нами с:
    16 фев 2019
    Сообщения:
    162
    Симпатии:
    23
    Адрес:
    Москва, Пушкина, Избушкина, 2й этаж душечка.
    @sobachnik
    PHP:
    1. $a = [1,2,3,4];
    2. foreach ( $a AS $b ) { $c = $b; }
    3.  
    4. foreach ( $c AS $d )
    5. { echo 1; }
    --- Добавлено ---
    пусть покажет полностью ошибку
     
  15. abutan

    abutan Новичок

    С нами с:
    25 мар 2019
    Сообщения:
    10
    Симпатии:
    0
    Там все немного сложнее. Эта форма вложена во вторую форму. И этот весь код работает. Вполне корректно, я получаю в ответе то что мне надо. Проблема появляется когда я пытаюсь отправить результаты в контролер по ajax.
    Код (Javascript):
    1. form.submit(function(e) {
    2.   e.preventDefault();
    3.   let post_data = {};
    4.         let user_id = $('input[name="user_id"]').val();
    5.         let url = form.attr('action');
    6.    
    7.         $('.tabs_content_block .tabs_block').each(function(a,obj){
    8.             let name = $(obj).find('input[name="question"]').val();
    9.             let answers = $(obj).find('input[name="answer"]').map( function(){ if ( $(this).val()!='' ) return $(this).val().replace(/\|/g,' ');} ).get().join('|');
    10.             let multiple_ans = $(obj).find('input[name="multiple_ans"]:checked').val();
    11.             a++;
    12.    
    13.             post_data[a] = { 'name':name, 'answers':answers,'multiple_ans':multiple_ans };
    14.         });
    15.         post_data = {'calc':post_data, 'user_id': user_id};
    16.    
    17.         $.post({
    18.             url: url,
    19.             dataType: "json",
    20.             data: post_data,
    21.             done: function (response) {
    22.                     console.log(response)
    23.                     alert('YES');
    24.                 } ,
    25.             error: function(result) {
    26.               console.log(post_data);
    27.                 alert('Error: '+result['status']+': '+result['responseText']);
    28.             }
    29.         });
    30. });
    Вот в этот момент и вылетает
    HTML:
    1. Error: 500: <pre>PHP Warning &#039;yii\base\ErrorException&#039; with message &#039;Illegal string offset &#039;answers&#039;&#039;
    2.  
    3. in /var/www/html/frontend/views/widgetuser/calc.php:53
    4.  
    5. Stack trace:
    6. #0 /var/www/html/frontend/views/widgetuser/calc.php(53): yii\base\ErrorHandler-&gt;handleError(2, &#039;Illegal string ...&#039;, &#039;/var/www/html/f...&#039;, 53, Array)
    7. #1 /var/www/html/vendor/yiisoft/yii2/base/View.php(348): require(&#039;/var/www/html/f...&#039;)
    8. #2 /var/www/html/vendor/yiisoft/yii2/base/View.php(257): yii\base\View-&gt;renderPhpFile(&#039;/var/www/html/f...&#039;, Array)
    9. #3 /var/www/html/vendor/yiisoft/yii2/base/View.php(156): yii\base\View-&gt;renderFile(&#039;/var/www/html/f...&#039;, Array, Object(frontend\controllers\WidgetuserController))
    10. #4 /var/www/html/vendor/yiisoft/yii2/base/Controller.php(384): yii\base\View-&gt;render(&#039;calc&#039;, Array, Object(frontend\controllers\WidgetuserController))
    11. #5 /var/www/html/frontend/controllers/WidgetuserController.php(150): yii\base\Controller-&gt;render(&#039;calc&#039;, Array)
    12. #6 [internal function]: frontend\controllers\WidgetuserController-&gt;actionCalc()
    13. #7 /var/www/html/vendor/yiisoft/yii2/base/InlineAction.php(57): call_user_func_array(Array, Array)
    14. #8 /var/www/html/vendor/yiisoft/yii2/base/Controller.php(157): yii\base\InlineAction-&gt;runWithParams(Array)
    15. #9 /var/www/html/vendor/yiisoft/yii2/base/Module.php(528): yii\base\Controller-&gt;runAction(&#039;calc&#039;, Array)
    16. #10 /var/www/html/vendor/yiisoft/yii2/web/Application.php(103): yii\base\Module-&gt;runAction(&#039;widgetuser/calc&#039;, Array)
    17. #11 /var/www/html/vendor/yiisoft/yii2/base/Application.php(386): yii\web\Application-&gt;handleRequest(Object(yii\web\Request))
    18. #12 /var/www/html/frontend/web/index1.php(36): yii\base\Application-&gt;run()
    19. #13 {main}</pre>
     
  16. sobachnik

    sobachnik Старожил

    С нами с:
    20 апр 2007
    Сообщения:
    3.380
    Симпатии:
    13
    Адрес:
    Дмитров, МО
    @Babka_Gadalka
    Я не понимаю, что вы хотите этим сказать или показать.

    Приведённый вами код приводит к ошибке
    Warning: Invalid argument supplied for foreach()
    поскольку в первом цикле, после его завершения, переменной $c присваивается значение 4 (число), а цикл foreach не может "перебрать" число.

    Если вы намекаете, что автор сперва в одном цикле создаёт переменную $mas_answers, а потом где-то в другом месте (после завершения первого цикла) пытается её использовать - то это не так. В приведённом автором коде видно, что массивы вложены друг в друга, а не расположены отдельно независимо друг от друга. То есть если комбинировать код автора и ваш - получится что-то типа
    PHP:
    1. $a = [1, 2, 3, 4];
    2. foreach ($a as $b) {
    3.     $c = explode('|', $b);
    4.     foreach ($c as $d) {
    5.         echo $d;
    6.     }
    7. }
     
  17. Babka_Gadalka

    Babka_Gadalka Активный пользователь

    С нами с:
    16 фев 2019
    Сообщения:
    162
    Симпатии:
    23
    Адрес:
    Москва, Пушкина, Избушкина, 2й этаж душечка.
    Ой, вижу :D
     
  18. sobachnik

    sobachnik Старожил

    С нами с:
    20 апр 2007
    Сообщения:
    3.380
    Симпатии:
    13
    Адрес:
    Дмитров, МО
    Интересный способ передачи user_id :) А что, если я элементарно открою в браузере "инструменты разработчика" и поменяю этому инпуту значение на id другого пользователя? :)

    А что касается сообщения об ошибке - нужно смотреть, что происходит в файле
    /var/www/html/frontend/views/widgetuser/calc.php
    Ошибка возникает в нём на строке 53.
     
  19. abutan

    abutan Новичок

    С нами с:
    25 мар 2019
    Сообщения:
    10
    Симпатии:
    0
    Ага.
    Вот именно с этого я и начал
    PHP:
    1. $mas_answers = explode('|', $value['answers']);
     
  20. sobachnik

    sobachnik Старожил

    С нами с:
    20 апр 2007
    Сообщения:
    3.380
    Симпатии:
    13
    Адрес:
    Дмитров, МО
    Далее постепенно подниматься по коду вверх и смотреть, как и где создаются переменные, откуда берутся их значения.

    Если это тот самый код, который вы публиковали выше, значит в массив $calc попадают другие данные именно когда вы
    То есть вам нужно загрузить в браузере страницу с этой формой, после чего (пока страница открыта, но форма ещё не отправлена) вставить в код перед foreach строку
    PHP:
    1. var_dump($calc); exit;
    После этого отправляйте форму и смотрите, что выведет var_dump().
    То есть суть в том, что нужно посмотреть содержимое массива именно в момент ошибки, а не тогда, когда генерация страницы проходит успешно.
     
  21. abutan

    abutan Новичок

    С нами с:
    25 мар 2019
    Сообщения:
    10
    Симпатии:
    0
    Все переменные пришли из контролера, выбранные из бд. Так что ничего не меняется в var_dum. Возможно к сожалению.
     
  22. sobachnik

    sobachnik Старожил

    С нами с:
    20 апр 2007
    Сообщения:
    3.380
    Симпатии:
    13
    Адрес:
    Дмитров, МО
    Ошибка происходит в PHP коде, при обработке вашего ajax-запроса. Нужно, чтобы этот var_dump отработал именно тогда, когда происходит ошибка, а не тогда, когда страница нормально загружается. То есть нужно смотреть var_dump именно при обработке вашего ajax-запроса. И я выше написал, как это сделать, прочитайте, пожалуйста, внимательно.
    --- Добавлено ---
    Если при открытии страницы ошибки нет, а при ответе на ajax-запрос ошибка происходит - значит что-то меняется 100% :) Либо там выполняется другой код, либо в него приходят другие данные. А как иначе-то?
     
    #22 sobachnik, 25 мар 2019
    Последнее редактирование: 25 мар 2019
  23. abutan

    abutan Новичок

    С нами с:
    25 мар 2019
    Сообщения:
    10
    Симпатии:
    0
    Огромное спасибо.
    Нашел таким образом опечатку в контролере.
    Еще раз спасибо.