1

in my current project I want to fill a bar chart with summed data for each day of a month. I get the required values from the database, but I can't get the array created in the right format. So far, the individual values are just lined up and I can't read them out in the JS.

I have tried to build the array in the right structure, but then I only get the last day of the month.

How do I get all the values in one output with the right syntax?

If do it like in the code below i got this output. Here I got all the values but i cant use them in my JS code:

[0,0,0,0,0,5,10,7,0,0,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]

If I do it with the typed out code (on the end of the code) the output looks like. Here i only got the last date of the month:

{"training_date":"2021-08-31","distance":10}

The output that i want looks like:

[
    {
        "training_date":"01.08.2021",
        "distance": "15"
    },
    {
        "training_date":"02.08.2021",
        "distance": "0"
    }
    ,
    {
        "training_date":"03.08.2021",
        "distance": "25"
    }
    ,
    {
        "training_date":"04.08.2021",
        "distance": "15"
    }
    ,
    .....
]

My PHP code:

<?php 
    header('Content-Type: application/json');

    include "../../../includes/db.php";

    if(isset($_GET['user_id'])) {
        $user_id = $_GET['user_id'];
    }

    $month = date("m");
    $year = date("Y");

    $daysInMonth = cal_days_in_month(CAL_GREGORIAN, $month, $year);

    $free = 6; $injury = 7;

    $data = array();

    for($i = 1; $i < $daysInMonth + 1; $i++) {
        
        $training_date = $year.'-'.$month.'-'.$i; 
        
        $get_user_trainings = $connection->prepare("SELECT * FROM training 
                                                    INNER JOIN training_content ON training.training_id = training_content.training_id
                                                    WHERE training.user_id = ?
                                                    AND training.training_date = ?
                                                    AND training.training_art_id != ?
                                                    AND training.training_art_id != ?
                                                   ");
        $get_user_trainings->bind_param("ssss", $user_id, $training_date, $free, $injury);
        $get_user_trainings->execute();
        $trainings = $get_user_trainings->get_result();
        $total_trainings = $trainings->num_rows;

        if($total_trainings >= 1) {

            $total_distance = 0;
            foreach($trainings as $row) {
                $training_art_id = $row['training_art_id'];
                $training_content_id = $row['training_content_id'];

                if($training_art_id == 1) {
                    ....

                    $total_distance += $training_intervall_length;
                    $total_distance += $training_intervall_pause_length;
                    $total_distance += $training_warmup_length;
                    $total_distance += $training_cooldown_length;                    
                } else if($training_art_id == 2) {
                    ....
                } else if($training_art_id == 3) {
                    ....

                    $total_distance += $training_speedwork_length;
                    $total_distance += $training_warmup_length; 
                    $total_distance += $training_cooldown_length;
                } else if($training_art_id == 5) {
                    ....

                    $total_distance += $training_competition_length;
                    $total_distance += $training_warmup_length; 
                    $total_distance += $training_cooldown_length;
                }
            }

            $total_distance = $total_distance / 1000;

            // $data["training_date"] = $training_date;
            // $data["distance"] = $total_distance;

            $data[] = $total_distance;
        } else {
            
            // $data["training_date"] = $training_date;
            // $data["distance"] = $total_distance;

            $data[] = $total_trainings;
        }
    }

    echo json_encode($data);
?>
6
  • 2
    Hi, please read about How to Ask and the value of a minimal reproducible example - there is far too much code here to expect anyone to read through, and most of it is not related to your question at all.
    – IMSoP
    Aug 12, 2021 at 19:56
  • 1
    If you want summed data, use SELECT training_date, SUM(...) FROM ... GROUP BY training_date in the query.
    – Barmar
    Aug 12, 2021 at 20:06
  • I don't think you need the loop at all. Just use 'json_encode($trainings)'. If the database returns an associative array then 'json_encode' is all you need.
    – CharlesEF
    Aug 12, 2021 at 20:26
  • @CharlesEF OP builds a sum over distance in the loop.
    – Kaii
    Aug 12, 2021 at 20:30
  • @Kaii It looked like he was doing the sum on the PHP side. It was suggested in a comment to let MySQL do the sum part. I think that is better than doing it on the PHP side. MySQL can return a json if requested.
    – CharlesEF
    Aug 12, 2021 at 20:39

1 Answer 1

2

Add a new associative array to the data list instead of only adding the values to your flat array:

$data = [];
for (..) {
    // minimal example - more code to populate $date and $distance here
    $data[] = [
        'training_date' => $date,
        'distance' => $total_distance
    ];
}
echo json_encode($data);

Also, as already suggested in the comments, SQL can summarize the distances for you by using GROUP BY and SUM() in your query:

SELECT user_id, training_date, training_art_id, SUM(distance) AS total_distance
FROM training 
    INNER JOIN training_content 
        ON training.training_id = training_content.training_id
WHERE training.user_id = ?
    AND training.training_art_id != ?
    AND training.training_date BETWEEN ? AND (? - INTERVAL 1 MONTH)
GROUP BY user_id, training_date, training_art_id

Note that i also changed the training_date condition to a 1 month range, because your desired example output contains more than a single date.

You can also build a SUM over multiple fields:

SELECT ..., (SUM(warmup) + SUM(cooldown) + SUM(..)) AS total_distance

When you query the database like above, the resulting recordset already has the form you want to output, so it could be as easy as:

$trainings = $get_user_trainings->get_result();
echo json_encode($trainings);
1
  • 1
    Hi, thanks for the answer, that helped me a lot. The array now outputs the data correctly, and my code has also become much smaller :D Aug 13, 2021 at 6:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.