Как отформатировать данные JSON с помощью PHP

У меня есть ниже метод, чтобы рассчитать каждый месяц доходы и расходы.

$query = Transaction::whereYear('date', $year)
                ->groupBy([DB::raw('MONTH(date)'),'type'])->get([DB::raw('MONTH(date) as month'), DB::raw('SUM(amount) as value'), 'type'])
                ->toJSON();

После получения данных JSON я хочу добавить их в диаграмму Морриса.

Ниже приведен формат JSON,

[{"month":11,"value":102.23,"type":"In"},{"month":11,"value":133.9,"type":"Out"}]

Однако, это не соответствует формату данных Морриса. Как я могу повернуть JSON ниже?

[{ "Месяц": 11, "В":102.23,"Выход":133,9}]

$(function() {
  var chart = Morris.Bar({
    element: 'morris-bar-chart',
    data: [0, 0], 
    xkey: 'Month',
    ykeys: ['In', 'Out'], 
    labels: ['In','Out'], 
    hideHover: 'auto',
    resize: true
  });
  $.ajax({
      type: "GET",
      dataType: 'json',
      url: "./getMonthlyOverview"
    })
    .done(function( data ) {
      chart.setData(data);
    })
    .fail(function() {
      alert( "error occured" );
    });
});

Я попытался изменить свой запрос ниже:

$stats = DB::select("select month,  SUM(IF( type = 'In', amount, 0)) as Income,  SUM(IF( type = 'Out', amount, 0)) as Expense from "
                . "(SELECT MONTH(date) as month, type, SUM(amount) as amount FROM Transactions WHERE YEAR(date) = " . $year . " group by MONTH(date), type) as c "
                . "group by month");

Не уверен, что это хорошее решение.

2 ответа

Решение

Если вы имеете дело только с данными за один месяц, вам не нужно вызывать какие-либо умные функции, потому что ваша структура данных предсказуема. Просто вручную перестроить.

Код: ( Демо)

$json = '[{"month":11,"value":102.23,"type":"In"},{"month":11,"value":133.9,"type":"Out"}]';

$array = json_decode($json, true);

echo json_encode(['month' => $array[0]['month'], $array[0]['type'] => $array[0]['value'], $array[1]['type'] => $array[1]['value']]);

Выход:

{"month":11,"In":102.23,"Out":133.9}

Если вы имеете дело с несколькими месяцами в одном наборе, вам просто нужно будет повторить набор результатов, заменив жестко закодированный [0] а также [1] приведенные выше ключи для парных переменных: 0 и 1 вместе, 2 и 3 и т. д.


ОБНОВЛЕНИЕ: Если вы счастливы написать собственный запрос MySQL, то это должно сделать:

$stats = DB::select("
    SELECT `month`,
           SUM(IF(`type` = 'In', amount, 0)) AS Income,
           SUM(IF(`type` = 'Out', amount, 0)) AS Expense
    FROM Transactions
    WHERE YEAR(`date`) = " . (int)$year . "
    GROUP BY MONTH(`date`)
");

Используя json_decode, вы можете декодировать свой JSON, и если вы передадите true в качестве второго параметра у вас будет ассоциативный массив. Теперь создайте $resultarray который будет пустым в начале, и вы будете заполнять результат (ы) там. Теперь, переберите декодированный JSON, проанализируйте результаты и заполните $result с ними. Когда это закончится, конвертировать $result в JSON, используя json_encode, и это должно решить проблему.

Другие вопросы по тегам