Javascript-форум (https://javascript.ru/forum/)
-   Элементы интерфейса (https://javascript.ru/forum/dom-window/)
-   -   Проблема получения объекта JSON (https://javascript.ru/forum/dom-window/61071-problema-polucheniya-obekta-json.html)

espltd 03.02.2016 08:33

Проблема получения объекта JSON
 
добрый день всем! Подскажите пожалуйста. Есть массив из базы данных в экшене. Я его возращаю так return json_encode($order); В аякс запросе пытаюсь по человечески его получить, а выходит следуюющее.

[{}, {}, {}, {}, {}, {}]
0: {}
1: {}
2: {}
3: {}
4: {}
5: {}

Если вывести в alert-е, то получаю [Object object, object object] и т.д. Не понимаю на каком этапе теряются мои данные.

Вот сам запрос

$('.order').click(function(){
                
                var number = $('#number').text();
                
                $.ajax({
                url: '/adm/record/order/',
                dataType: 'json',
                data: "card=" + number,
                                
                success: function(html){
                    
                    var res = eval("(" + html + ")");
                    
                    alert(res);
                    
                    //$('#result').text(data);
                }
                
               });                
            });

espltd 03.02.2016 11:06

Ребят, ну кто нибудь отзовитесь. Не допираю в чем трабла

laimas 03.02.2016 11:23

JSON, это не объект, это формат описания данных и представляет собой строку. А вот указание этого типа данных в запросе будет означать, что по окончании запроса эта строка уже будет преобразована в объект, и в связи с тем, что в JS нет ассоциативных массивов, этот массив переданный сервером, на клиенте будет являться массивом объектов, который и описывается в JS как:

[{свойство : значение, свойство : значение, ...}, {...}, {}, {}, {}, {}]

где свойство, это ключ ассоциативного массива. Теперь осталось произвести с объектом html некие операции по извлечению этих данных в цикле. А

var res = eval("(" + html + ")");

alert(res);

выбросить, и просмотреть на клиенте содержимое объекта html можно так - console.log(html)

espltd 03.02.2016 11:27

я раньше работал только с получением строки, а сейчас именно надо преобразование этой строки в объект. Не понимаю как мне сейчас к эти данным обратиться. Можно пример?

laimas 03.02.2016 11:31

Цитата:

Сообщение от espltd
а сейчас именно надо преобразование этой строки в объект.

Не надо ничего преобразовывать, jQuery уже это сделал. Далее что делать с этим объектом, это уже ваша забота.

Цитата:

Сообщение от espltd
Можно пример?

Можно, но нужно хотя бы писать, чего же вы хотите сделать с этими данными. Или вы, зная их структуру что получена из базы, передали их на клиента просто так, не зная что там и что с ними делать?

espltd 03.02.2016 11:39

разумеется я знаю структуру. Просто с json я ранее не работал. В пхп у меня бы получилось так:

foreach ($order as $item){
echo $item->name.'<br/>';
echo $item->lastname.'<br/>';
}

и т.д. А как сейчас их достать я не понимаю. Может дадите реально хорошую ссылку описывающую именно работу(получение данных) пошагово

laimas 03.02.2016 11:45

Ну если echo $item->name, то надеюсь понятно и то, что данные из базы будут выведены последовательно в длиииииинный столбик, что именно это и требуется сделать на клиенте?

espltd 03.02.2016 11:50

Мне просто нужно отобразить данные авторизованного юзера в его кабинете и все. Сейчас я просто хочу их получить. А то Object object клиенту ни о чем не скажут ;)

laimas 03.02.2016 11:56

Цитата:

Сообщение от espltd
Мне просто нужно отобразить данные авторизованного юзера в его кабинете и все.

Если так, то зачем же вы гребете из базы не одну запись, то есть данные одного пользователя, а кучу записей?

Если одного пользователя, то объект на клиенте должен быть примерно таким (имена свойств пишу условно):

{"name" : "значение", "birth" : "значение", etc....}

А то что вы привели, это массив объектов, то есть фактически:

[{"name" : "значение", "birth" : "значение", etc....},
{"name" : "значение", "birth" : "значение", etc....},
{"name" : "значение", "birth" : "значение", etc....},
..... etc]

Что-то не то вы делаете уже на сервере, либо не описываете свои данные так, чтобы можно было понять чего хотите.

espltd 03.02.2016 12:11

laimas. Смотрите давайте так:

Вот это я получаю на сервере.
<pre>Array
(
    [0] => app\models\LogBonus Object
        (
            [_attributes:yii\db\BaseActiveRecord:private] => Array
                (
                    [id_log_bonus] => 1913
                    [card] => 19034233
                    [operator] => 7
                    [operation] => inflow
                    [operator_cancel] => 0
                    [dat_oper] => 2012-09-26 13:20:00
                    [confirm] => 1
                    [oper] => Оплата по Заказ наряд 18930 (26.09.12) / 7079
                    [oper_summa] => 7079.00
                    [persent] => 3
                    [summ] => 212.00
                    [confirmed] => 2012-09-26 13:20:00
                    [project] => 4
                    [bad] => 0
                    [verify] => 3419
                )

            [_oldAttributes:yii\db\BaseActiveRecord:private] => Array
                (
                    [id_log_bonus] => 1913
                    [card] => 19034233
                    [operator] => 7
                    [operation] => inflow
                    [operator_cancel] => 0
                    [dat_oper] => 2012-09-26 13:20:00
                    [confirm] => 1
                    [oper] => Оплата по Заказ наряд 18930 (26.09.12) / 7079
                    [oper_summa] => 7079.00
                    [persent] => 3
                    [summ] => 212.00
                    [confirmed] => 2012-09-26 13:20:00
                    [project] => 4
                    [bad] => 0
                    [verify] => 3419
                )

            [_related:yii\db\BaseActiveRecord:private] => Array
                (
                )

            [_errors:yii\base\Model:private] => 
            [_validators:yii\base\Model:private] => 
            [_scenario:yii\base\Model:private] => default
            [_events:yii\base\Component:private] => Array
                (
                )

            [_behaviors:yii\base\Component:private] => Array
                (
                )

        )

    [1] => app\models\LogBonus Object
        (
            [_attributes:yii\db\BaseActiveRecord:private] => Array
                (
                    [id_log_bonus] => 24831
                    [card] => 19034233
                    [operator] => 7
                    [operation] => outflow
                    [operator_cancel] => 0
                    [dat_oper] => 2013-10-19 12:35:55
                    [confirm] => 1
                    [oper] => Оплата по Заказ наряд 27303 (19.10.13) / 6399
                    [oper_summa] => 210.00
                    [persent] => 0
                    [summ] => 210.00
                    [confirmed] => 2013-10-19 12:35:55
                    [project] => 4
                    [bad] => 0
                    [verify] => 
                )

            [_oldAttributes:yii\db\BaseActiveRecord:private] => Array
                (
                    [id_log_bonus] => 24831
                    [card] => 19034233
                    [operator] => 7
                    [operation] => outflow
                    [operator_cancel] => 0
                    [dat_oper] => 2013-10-19 12:35:55
                    [confirm] => 1
                    [oper] => Оплата по Заказ наряд 27303 (19.10.13) / 6399
                    [oper_summa] => 210.00
                    [persent] => 0
                    [summ] => 210.00
                    [confirmed] => 2013-10-19 12:35:55
                    [project] => 4
                    [bad] => 0
                    [verify] => 
                )

            [_related:yii\db\BaseActiveRecord:private] => Array
                (
                )

            [_errors:yii\base\Model:private] => 
            [_validators:yii\base\Model:private] => 
            [_scenario:yii\base\Model:private] => default
            [_events:yii\base\Component:private] => Array
                (
                )

            [_behaviors:yii\base\Component:private] => Array
                (
                )

        )

espltd 03.02.2016 12:12

Как мне пользователю теперь все это показать, но не с помощью пхп, а с помощью аякс запроса без перезагрузки страницы

laimas 03.02.2016 12:26

Цитата:

Сообщение от espltd
Смотрите давайте так

и что видим - кучу записей. А было пояснение, что нужно отобразить данные авторизованного юзера в его кабинете. Из кучи видим, что это что-то типа заказов. Вопрос - вам надо все данные каждой строки (или же только часть данных каждой строки?) отобразить на клиенте в html-таблице, или "столбиком", коли была ссылка "да я бы echo $name <br>".

Понимаете или нет что от вас хотят узнать? Ведь если говорить предметно, то хорошо бы отправлять клиенту данные в той структуре, с которой на клиенте не придется делать лишних телодвижений, а не поступать так - а есть вот так в базе, ну значит и бухнем клиенту так, пусть разбирается.

Опишите просто словами чего в конечном итоге вы хотите увидеть на клиенте.

espltd 03.02.2016 12:48

Все данные нужно и построить красивую табличку:)

laimas 03.02.2016 14:55

Красивые таблички, это уже не мое дело, а вот как построить на клиенте табличку из данных, это можно показать, хотя это действо на клиенте ничем по сути не будет отличаться от подобного на сервере. Разница может быть только в случае работы на клиенте с DOM, а не создания строки html кода таблицы, а потом помещения ее на страницу. Хотя и в случае работы с DOM получение данных из объекта ничем не будет отличаться и при формировании строки.

Но прежде чем строить "красивую табличку", нужно озаботиться чтобы данные для этой таблички были в удобном для клиента формате. А если посмотреть на массив данных на сервере, то видим в нем кроме полезного и кучу мусора (_related:yii\db\BaseActiveRecord:private, _errors:yii\base\Model:private и другие). Более того, каждый вложенный массив объекта app\models\LogBonus Object содержит два вложенных массива _attributes:yii\db\BaseActiveRecord:private дублирующих друг друга или вы этого не замечаете? И какие же в этом случае данные будет содержать "красивая табличка" на клиенте?

Опять предположим, что все эти проблемы предварительно решены на сервере и клиенту не передается в итоге мусора и дубликатов. Но еще один вопрос остался без ответа - все ли данные массива _attributes:yii\db\BaseActiveRecord:private нужно отображать на клиенте или же просто выдрано из базы все что есть и отправлено клиенту? А ведь если нужно не все, то придется на клиенте идентифицировать только те свойства объекта, которые нужно поместить в таблицу, а это бесполезная работа в таком случае будет.

Далее будет много слов, но коли хотите строить красивые таблички, читайте, думайте, и отправляйте клиенту данные осознанные, а не абы как.

Предположим, что из всех ключей вложенных массивов _attributes:yii\db\BaseActiveRecord:private на клиенте нужно отобразить лишь некоторые. Для этого правильнее всего определять в запросе к базе только эти поля. Если это является проблемой, то можно получить срез массива, можно получить пересечением массивов нужные ключи, а можно в цикле формировать новый массив только тех данных, которые и будут отправлены клиенту.

И опять предположим, что с этим все ОК и клиенту отправляются только необходимые данные, и пусть для примера возьмем эти:

Код:

Array
(
    [0] => Array
        (
            [oper] => Оплата по Заказ наряд 18930 (26.09.12) / 7079
            [oper_summa] => 7079.00
            [dat_oper] => 2012-09-26 13:20:00
        )

    [1] => Array
        (
            [oper] => Оплата по Заказ наряд 27303 (19.10.13) / 6399
            [oper_summa] => 210.00
            [dat_oper] => 2013-10-19 12:35:55
        )

)

Отдав эти данные клиенту как json, и вот так:

json_encode($array, JSON_UNESCAPED_UNICODE | JSON_NUMERIC_CHECK)


после их преобразования в объект, получим:

html = [
    {"oper" : "Оплата по Заказ наряд 18930 (26.09.12) / 7079", "oper_summa" : 7079, "dat_oper" : "2012-09-26 13:20:00"},
    {"oper" : "Оплата по Заказ наряд 27303 (19.10.13) / 6399", "oper_summa" : 210, "dat_oper" : "2013-10-19 12:35:55"}
];


Но прежде чем отдавать именно такую структуру данных полезно бы призадуматься. Нам нужно только построить таблицу из этих данных, то есть поместить значения свойств объектов этого массива в ячейки таблицы, имена самих свой не нужны. Можно конечно пробежать циклом по этому массиву/объектам, получить значения свойств и сформировать таблицу. Можно, но зачем, если можно обойтись без этого.

На сервере средствами РНР можно обрамить элементы массива тегами ячейки таблицы, сформировав код таблицы и делается это просто, вариант с циклом:

echo '<table>';
foreach($array as $v) echo '<tr><td>' . implode('</td><td>', $v) . '</td></tr>';
echo '</table>';


При этом не важно каким массивом является $v, ассоциативным или индексным, в любом случае implode() будет оперировать со значениями массива.

В JS функция аналогичная implode(), это join(). Но она применима только к массивам, а ассоциативный массив отданный клиенту будет представлять на нем как Объект, и нельзя будет так же просто в цикле получать объект, и применить к нему join:

'<tr><td>' . html[i].join('</td><td>') . '</td></tr>' - это ошибка, так как html[i] в массиве объектов, это объект.

Отсюда вывод, что для "просто вывести данные в таблице на клиенте" выгоднее отправлять ему только данные, то есть индексный массив, вот такой:

Код:

Array
(
    [0] => Array
        (
            [0] => Оплата по Заказ наряд 18930 (26.09.12) / 7079
            [1] => 7079.00
            [2] => 2012-09-26 13:20:00
        )

    [1] => Array
        (
            [0] => Оплата по Заказ наряд 27303 (19.10.13) / 6399
            [1] => 210.00
            [2] => 2013-10-19 12:35:55
        )

)

И на клиенте получим не массив объектов, а массив массивов, вот что будет содержать переменная html в ответе на запрос:

html = [
    ['Оплата по Заказ наряд 18930 (26.09.12) / 7079', '7079.00', '2012-09-26 13:20:00'],
    ['Оплата по Заказ наряд 27303 (19.10.13) / 6399', '210.00', '2013-10-19 12:35:55'] 
];


Теперь и на клиенте можно упростить задачу построения таблицы, получая в цикле каждый вложенный массив массива html и посредством join() формировать строку таблицы.

Но колонки таблицы еще и имеют заголовки поясняющие данные. Здесь опять неизвестно, то ли если фиксированные данные отдаются клиенту и одноразовые, то есть сценарий на клиенте строящий эту таблицу, строит только ее, а значит эти заголовки жестко прописаны в сценарии, а строки таблицы получаемые из данных нужно добавить в таблицу, то ли клиент может получать различные таблицы с различными данными. Во втором случае заголовки таблиц выгоднее не прописывать жестко в сценарии, а получать их также от сервера наряду с данными таблиц, и иметь один и тот же сценарий на клиенте строящий по ним таблицы.

При этом на сервере можно поступить по разному, как способ, иметь массив описывающий заголовки таблиц и отдавать те, что удовлетворяют параметру запроса. Но самое разумное, это источником заголовков является сам источник данных. Поля таблиц могут иметь комментарии описывающие их. Эти комментарии можно получить запросом к базе:

Код:

'SELECT COLUMN_NAME, COLUMN_COMMENT
FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = "base_name"
AND TABLE_NAME = "table_name"'

и по ключам запрашиваемых полей данных (COLUMN_NAME), получить из этого запроса комментарии этих полей (COLUMN_COMMENT), при этом данные клиенту можно передать так:

Код:

array = [
  'head' => [массив описывающий колонки таблицы],
  'data' => [
    [массив значений],
    [массив значений],
    [массив значений],
    ....
  ]
]

на клиенте из html.head массива строим строку заголовков таблицы (посредством того же join()), а обходом в цикле массива html.data строки таблицы с данными.

Примечание - если читаем это и не понимаем, то:

1) показать конкретное представление данных получаемых клиентом
2) данные не должны иметь дубликатов, мусора и ненужных данных (см. выше)
3) если п. 2 не выполняется, описать условия - какие именно данные должны быть помещены в таблицу на клиенте.

PS. Колобки с языком, это следствие ВВ, а не данные из базы, надеюсь понятно будет о каких именно речь.


Часовой пояс GMT +3, время: 16:49.