@rodion11
php dev

Как правильно обработать строки из бд?

Задача получить строки из большой таблицы, изменить каждую строку согласно определенным правилам и вставить в другую таблицу.
Например на входе строка:
id = 17
name = victor
role = admin
Мы ее меняем согласно правилам, например id = id + 1000; name переводим на русский, role нужно чтобы начиналось с большой буквы.
В другую таблицу мы должны добавить
1017, Виктор, Admin

Хочется решить задачу максимально правильно.

Есть класс Database, паттерн singleton.
В нем создается подключение к бд и имеются методы для вставки, обновления и получения строк. Например:
function getRecords() {
    $info= array();
    $res = $this->connection->query("SELECT * FROM `table`");
    while ($row = $res->fetch_assoc()) {
       $info[] = $row;
    }
    return $info; 
}

Данный подход для большого числа строк не подойдет, можно ли переписать так?
public function getRecords() {
    $info= array();
    return $this->connection->query("SELECT * FROM `table`"); 
}


А дальше не совсем понятно как быть, на ум приходит такое решение, но мне кажется оно плоховато.
$db = new Database();
foreach ($db->getRecords() as $arr) {
    //класс Row тут не знаю, нужен или нет. 
    //если делать в нем public переменные id, role, name, то это аналог массива получается. 
    //создаем класс на основе строки из бд
    $row = new Row($arr);

    //передаем его классу, который будет улучшать поля
    $improve = new Improve($row);

    $improve->translateName();
    $improve->fixId();
    $improve->fixRole();

    //передаем массив функции, которая добавит в бд обработанную строку
    $db->addRow($row->returnArray());
}


Если кратко:
1) Правильно ли переписан метод getRecords()? Если нет, то как такое решается
2) Как правильно спроектировать обработку строки? Мне кажется текущий вариант плох.

Спасибо!
  • Вопрос задан
  • 243 просмотра
Пригласить эксперта
Ответы на вопрос 2
Сделав
return $this->connection->query("SELECT * FROM `table`");

, вы вернули из метода getRecords() не массив, а... не уверен, как это называется, но цикл
foreach ($db->getRecords() as $arr)
точно работать не будет.
Можете вместо этого цикла делать как-то так:
$results = $db->getRecords();
while ($row = $results->fetch_assoc())
{
    // Здесь $row - массив с индексами id, name, role
    // Изменяете его и заносите в новую таблицу сразу
}
Ответ написан
DmitriyEntelis
@DmitriyEntelis
Думаю за деньги
Самое главное что нужно учесть в это задаче - если это живые обновляемые данные, то получение и обновление должны находиться в рамках одной транзакции.
Делая SELECT * FROM `table`, а потом обновляя записи в цикле - вы имеете огромные шансы что за это время другой поток как-то обновит таблицу, и ваш код вставит старое значение.

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

Советовать что-то еще сложно, не зная реальных условий (сколько данных, как они обновляются, дополняются, какие требования к доступности на время обновления) - это всё тонкая тема, хаков много разных можно придумать.
Ответ написан
Ваш ответ на вопрос

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

Войти через TM ID
Похожие вопросы