#symfony #updates #query-builder
#симфония #Обновления #конструктор запросов #symfony
Вопрос:
Я хочу иметь общий метод обновления, который получает json с {field1:value1,.. field4:value4} и обновляет их все. Где field — это имя поля из таблицы в БД. Это может быть только одно поле для обновления, но также и несколько.
В моем контроллере symfony :
/**
* @Route("/update", name="template_update", methods={"POST"})
*/
public function update(Request $request, TemplateRepository $templateRepository): Response
{
$data = json_decode($request->getContent(), true);
$fields = $data["data"];
$qb = $templateRepository->createQueryBuilder('t');
foreach ($fields as $field => $value) {
dump($field);
dump($value);
$q = $qb->update(Template::class,'t')
->set("t." . $field . "", '?1')
->where('t.id = ?2')
->setParameter(1, $value)
->setParameter(2, $data["id"])
->getQuery();
dump($q);
$p = $q->execute();
}
return new JsonResponse(["response" => $p]);
}
В первом цикле все в порядке :
Но во втором цикле предыдущий параметр сохраняется и перезаписывается этим последним запросом :
Что я делаю не так? И есть ли лучший способ избежать нескольких запросов и сделать это в одном уникальном запросе?
Комментарии:
1. Я думаю, вам нужен новый конструктор запросов для каждого запроса на обновление.
2. Вот и все, я этого не вижу
3. Спасибо @IwanWijaya!
4. Я имею в виду, что вам нужно запускать createQueryBuilder() для каждого цикла. это может сработать, но написание такого кода на самом деле небезопасно и неэффективно.
Ответ №1:
Ок ответ был я объявляю только один раз мой querybuilder за пределами foreach. Поместите его внутрь foreach, и больше ошибок не будет.
Я также выясняю, как это сделать в одном запросе :
$qb = $templateRepository->createQueryBuilder('t');
$qb->update(Template::class, 't');
$count = 0;
foreach ($fields as $field => $value) {
$qb->set("t." . $field . "", '?' . $count . '')
->setParameter($count, $value);
$count ;
};
$q = $qb->where('t.id = ?' . $count . '')
->setParameter($count, $data["id"])
->getQuery();
$p = $q->execute();
Комментарии:
1. Просто имейте в виду, что, поскольку $field поступает из внешнего источника, вы уязвимы для sql-инъекций. В отличие от полей данных, обработка имен столбцов не выполняется. По крайней мере, вам нужно проверить $field .
2. Это хороший момент, вы имеете в виду просто strip_tags и тому подобное в $field / $value ?
3. Я бы просто получил массив допустимых имен полей и проверил, что $field является одним из них.
4. Интересно, могли бы вы просто извлечь шаблон из базы данных и вызвать соответствующие установщики, а затем сбросить в БД и получить только один запрос, и он будет правильно экранирован по умолчанию… очевидно, работает только в том случае, если у вас есть нормальное сопоставление между свойствами и именами столбцов
5. или даже больше, используйте десериализатор для заполнения объекта данными … ; o)