Mecitan
@Mecitan
Уверенный пользователь клавиатуры

Как оптимизировать код php во избежании дублирования, при добавление данных в БД?

Здравствуйте! Есть вот такой код (указан ниже). На данный момент у меня есть ещё один JSON, в котором есть все те же массивы, плюс один новый ads. У которого те же самые ключи. Решил для ads создать отдельную таблицу. С такими же полями, как и таблицы finance.seo. Получается индиетичный SQL-запрос в котором меняется только название таблицы. По факту, получается, я делаю ещё foreach для добавления данных ads. Есть ли другой вариант, чтобы не дублировать те же действия?
$file = file_get_contents("May-12_17-57-28.json");
$file = file_get_contents("ads.json");
$data = json_decode($file, true);

$db = new PDO('mysql:host=localhost;dbname=test', 'root', '');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);

$stmt = $db->prepare('INSERT INTO finance.seo(snippet, amp, date, anchor, link) VALUES (:snippet,:amp,:date,
 :anchor, :link)');


foreach ($data['p1']['serp'] as $values) {
    $stmt->bindParam(':snippet', $values['snippet']);
    $stmt->bindParam(':amp', $values['amp']);
    $stmt->bindParam(':date', $values['date']);
    $stmt->bindParam(':anchor', $values['anchor']);
    $stmt->bindParam(':link', $values['link']);
    $stmt->execute();
}


Структура JSON:
6467e4b6058a9553252564.png
6467e4f2a2d89630976859.png
  • Вопрос задан
  • 115 просмотров
Решения вопроса 1
ipatiev
@ipatiev Куратор тега PHP
Потомок старинного рода Ипатьевых-Колотитьевых
Для того, чтобы не повторять программный код, специально были придуманы подпрограммы.
Когда один и тот же код может выполняться для разных наборов данных.
В РНР есть несколько способов сделать подпрограмму, но самый удобный - это написать функцию.
Важно только соблюдать чувство меры и принцип единственной ответственности - функция должна делать что-то одно. К примеру, если она должна что-то писать в базу данных, то не должна при этом с базой соединяться.
function save_data($pdo, $data, $type) {
    $stmt = $db->prepare('INSERT INTO ads (snippet, amp, date, anchor, link,type) 
                          VALUES (:snippet,:amp,:date,:anchor, :link, :type)');
    $pdo->beginTransaction();
    foreach ($data as $values) {
        $values['type'] = $type;
        $stmt->execute($values);
    }
    $pdo->commit();
}

Как я уже писал ранее, для скорости и консистентности множественные вставки желательно заключить в транзакцию.

И вызывать примерно так

$db = new PDO('mysql:host=localhost;dbname=test', 'root', '');
// ТОЛЬКО EXCEPTION! c warning-ами в детский сад ходите детей пугать
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$file = file_get_contents("ads.json");
$data = json_decode($file, true);
save_data($db, $data['p1']['ads'], 'ads');

$file = file_get_contents("May-12_17-57-28.json");
$data = json_decode($file, true);
save_data($db, $data['p1']['serp'], 'serp');


На этом этапе, посмотрев на повторяющийся код, можно сделать еще одну итерацию
function import_data($filename, $type, $pdo) {
    $file = file_get_contents($filename);
    $data = json_decode($file, true);
    save_data($pdo, $data['p1'][$type], $type);    
}

Но можно уже и не частить
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
Stalker_RED
@Stalker_RED
Можно дублировать таблицу вместе с данными средствами СУБД.
Или не делать две одинаковы таблицы, а хранить все в одной.
Ответ написан
@alexalexes
Вам нужно проработать архитектуру таблиц.
Чтобы удобно хранить свойства ads и serp в одной таблице, которые представленные в виде массива. Вам нужно не только выделить тип записи - ads или serp, но нужно как-то связать все записи, которые входят в одно событие свойства p1.
Допустим, для событий мы создаем таблицу Event со свойствами:
Event_Id - код события,
info - строка или JSON-тип,
success - число,
query - строка или JSON-тип,
total_count - число
...
Не все свойства p1 перечисляю, так как, например, paa - тоже массив, и нужно понять, будете ли под него выделять отдельную таблицу или приспособите какую-нибудь существующую, добавив новый тип - paa.
-----
А для хранения элементов массивов ads, serp (и, возможно еще каких-либо свойств-массивов, которые появятся непосредственно в p1 не во вложенных свойствах) вы создадите отдельную таблицу event_prop_array:
prop_arr_Id - код элемента свойства события
prop_id - тип свойства из таблицы-справочника типов свойств (внешний ключ)
event_id - событие, к которому относится запись, внешний ключ к таблице event
link - строка
snippet - строка
...
дальше идут другие скалярные свойства, которые можно найти в одном элементе ads или serp
------
Добавляем таблицу справочник, чтобы закодировать внешний ключ prop_id
Таблица event_prop
prop_id - код свойства
prop_name - имя свойства
----------------------------
Теперь, чтобы залогировать один элемент p1 нужно сделать так:
1. Вставить в таблицу event запись из простых свойств (info, success, query, total_count, ... )
2. Получить event_id вставленной записи (гуглите last_insert_id для PDO или дополнительную клаузу для insert - "returning event_id into :event_id", если вы используете, например, oracle, а не mySQL)
3. Получить prop_id из справочника (тут обычный select)
4. В цикле вставляете записи в таблицу event_prop_array, используя известные event_id, prop_id и текущие свойства элемента ads.
5. Тоже самое как 4, но используете свойства serp.
-------------------
Когда сформируете лог в базе, то типичный запрос для выборки чего-либо будет иметь вид:
select e.*, ep.*, epa.*
from event_prop_array epa
join event_prop ep on ep.prop_id = epa.prop_id
join event e on e.event_id = epa.event_id
-- какие-то условия для поиска
where e.event_id = 1
 and ep.prop_name = 'ads'
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы