Получение данных от API в формате JSON


Я получаю данные от API в формате JSON. Это становится ЧСС пользователя и вставить его в мою базу данных. Он получает текущую дату, а также пару дней в прошлое и обновляет базу данных соответственно. Приведенный ниже код работает (хотя это вставка пустой строки по какой-то причине). На мой вопрос, есть ли лучше/более эффективный способ написания этого кода?

Вот такие:

[activities-heart] => Array (
[0] => Array (
    [dateTime] => 2018-03-22
    [value] => Array (
        [customHeartRateZones] => Array ( )
        [heartRateZones] => Array (
            [0] => Array (
                [caloriesOut] => 1135.7736
                [max] => 85
                [min] => 30
                [minutes] => 814
                [name] => Out of Range
                )
            [1] => Array (
                [caloriesOut] => 1260.7179
                [max] => 119
                [min] => 85
                [minutes] => 289
                [name] => Fat Burn
                )
            [2] => Array (
                [caloriesOut] => 690.64515
                [max] => 145
                [min] => 119
                [minutes] => 90
                [name] => Cardio
                )
            [3] => Array (
                [caloriesOut] => 0
                [max] => 220
                [min] => 145
                [minutes] => 0
                [name] => Peak
                )
            )
        [restingHeartRate] => 65
        )
    )
[1] => Array (
    [dateTime] => 2018-03-23
    [value] => Array (
        [customHeartRateZones] => Array ( )
        [heartRateZones] => Array (
            [0] => Array (
                [caloriesOut] => 1512.00346
                [max] => 85
                [min] => 30
                [minutes] => 1113
                [name] => Out of Range
                )
            [1] => Array (
                [caloriesOut] => 1315.59604
                [max] => 119
                [min] => 85
                [minutes] => 280
                [name] => Fat Burn
                )
            [2] => Array (
                [caloriesOut] => 98.14618
                [max] => 145
                [min] => 119
                [minutes] => 13
                [name] => Cardio
                )
            [3] => Array (
                [caloriesOut] => 0
                [max] => 220
                [min] => 145
                [minutes] => 0
                [name] => Peak
                )
            )
        [restingHeartRate] => 64
        )
    )
)

А вот соответствующий код, чтобы обработать его:

$obj = new RecursiveIteratorIterator( new RecursiveArrayIterator( json_decode( $return, TRUE ) ), RecursiveIteratorIterator::SELF_FIRST );

foreach ( $obj as $key => $val ) {
    $$key = $val;

    $stmt = $connection->prepare( "INSERT INTO heartrate SET `encodedid` = ?, activitydate = ?, rhr = ? ON DUPLICATE KEY UPDATE rhr= ?" );
    $stmt->bind_param( 'ssii', $studentencodedid, $dateTime, $restingHeartRate, $restingHeartRate );
    $stmt->execute();

    if ( $stmt->affected_rows < 1 ) {
        header( "Location: " . $url . "/index.php?errormessage=Failed to updated the resting heart rate value." );
    }

    $stmt->close();
}


183
1
задан 29 марта 2018 в 12:03 Источник Поделиться
Комментарии
1 ответ

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

1)

Ты сейчас назвал prepare() внутри тела ваш цикл foreach. Это лишнее, вам нужно только подготовить вашего запроса. Вы можете повторно использовать PDOStatement что prepare() возвращается неоднократно в каждой итерации вашего цикла. Это на самом деле очень эффективны, так как запрос придется только один раз оценивали. Когда вы будете готовы, подготовка завершена, нет необходимости повторно готовить для каждой итерации цикла, если структура запроса такая же.

(Для справки, подготовить действительно правильный метод для использования в пакетных операций, как это. В будущем, если вам нужно только выполнить один запрос, вы могли бы альтернативное использование PDO:query() (Если вам нужен результат) или PDO:exec() (если вам не нужны результаты из запроса-он просто возвращает количество строк, затронутых запросом, как целое.))

То же самое касается bindParam(). Вам не нужно повторно привязать параметры каждой итерации цикла-как только связаны, они связаны. bindParam() персонализация по ссылке, фактическая оценка параметра происходит каждый раз execute() называется.

Так давайте сделаем этот незначительный рефакторинг. Мы готовим заявление и привязать параметры перед циклом начинается, Мы execute() заявление на каждой итерации цикла, и мы будем двигаться close()-ную использования pdostatement быть после цикла. Ваш пример теперь выглядит так, и будет немного более производительным:

$obj = new RecursiveIteratorIterator( new RecursiveArrayIterator( json_decode( $return, TRUE ) ), RecursiveIteratorIterator::SELF_FIRST );

$stmt = $connection->prepare( "INSERT INTO heartrate SET `encodedid` = ?, activitydate = ?, rhr = ? ON DUPLICATE KEY UPDATE rhr= ?" );
$stmt->bind_param( 'ssii', $studentencodedid, $dateTime, $restingHeartRate, $restingHeartRate );

foreach ( $obj as $key => $val ) {
$$key = $val;
$stmt->execute();

if ( $stmt->affected_rows < 1 ) {
header( "Location: " . $url . "/index.php?errormessage=Failed to updated the resting heart rate value." );
}
}

$stmt->close();

2)

$$key = $val;

Я бы рекомендовал не использовать переменные. Они, как правило, считается порча на язык, и люди имеют очень сильные мнения о них.

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

2.5)

На самом деле, глядя на ваш пример массива данных, ваши данные не быть произвольной глубины. Это выглядит фиксированной глубине. Да, есть n количество heartRateZones в день, но структура повторяющихся. Это выглядит по ключу в день, каждый день имеет несколько уникальных ключей/наборы значений. Единственное, что в массиве значение кажется, что вас волнует-это в день даты и пульс покоя. Вы не используете их, но я также могу себе представить, может быть, вы хотите, чтобы heartRateZones, вы можете просто взять эти напрямую без перебора всех ключей в массиве "стоимость".

Я не вижу необходимости рекурсии вообще.

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

Вы не представляется, в настоящее время, используя любой из heartRateZones. Если вы хотели вставить запись в зоне, можно запускать execute() в этом внутреннем цикле foreach. В противном случае просто удалите этот цикл и запустить execute() в дни цикла.

Я не видел $studentencodeid определенными в примере кода Вы дали, или в JSON данных. Я предполагаю, что вы уже определили, что повсюду в ваш сценарий.

$obj = json_decode($return, TRUE);

$stmt = $connection->prepare( "INSERT INTO heartrate SET `encodedid` = ?, activitydate = ?, rhr = ? ON DUPLICATE KEY UPDATE rhr= ?" );
$stmt->bind_param( 'ssii', $studentencodedid, $dateTime, $restingHeartRate, $restingHeartRate );

// Iterate through days
foreach ($obj as $key => $value) {

// Grab data unique to a whole day that you care about
$dateTime = $value['dateTime'];
$restingHeartRate = $value['restingHeartRate'];

// Iterate through heartRateZones (Or remove this loop if you don't need them)
foreach($value['value'] as $zoneKey => $zoneValue) {
// If you want to insert records based on individual heart rate records, do that here and remove the execute() below. You'd insert a record per-heartrate with the same dateTime and restingHeartRate values as all the other heartrates on that day.
// $stmt->execute();
}

$stmt->execute();

if ($stmt->affected_rows < 1 ) {
header( "Location: " . $url . "/index.php?errormessage=Failed to updated the resting heart rate value." );
}
}

$stmt->close();

1
ответ дан 30 марта 2018 в 06:03 Источник Поделиться