Как сделать привязку параметров (binding) при Update для Yii2?

Yii2, обновление нескольких строк:

    $sql = 'UPDATE category SET 
        parent = CASE id 
            WHEN 1 THEN 0 
            WHEN 2 THEN 1 
            ELSE parent 
        END, 
        title = CASE id 
            WHEN 1 THEN "строка 1" 
            WHEN 2 THEN "строка 2" 
            ELSE title 
        END
        WHERE id IN (1, 2)
        AND user_id = 15';

    Yii::$app->db->createCommand($sql)
        ->execute();

Задача - сделать binding параметров. Во множестве примеров документации вижу способы привязки для select-запросов, и ни одного способа/примера для update-запроса.

Данные от клиента приходят в виде массива JSON-объектов [{"id":1,"user_id":15,"parent":0,"title":"строка"},{"id":2,"user_id":15,"parent":1,"title":"строка 1"}], версия MySql - 8.0.18.0

Контроллер:

public function actionSaveCategory()
{
    if (Yii::$app->request->isAjax) {
        $request = Yii::$app->request->post('categories');           
        
        $categories = json_decode($request, true);
        $model = new Category;
        $rows = [];

        foreach ($categories as $category) {
            $model->load($category, '');
            $model->id = $category['id'];

            if (!$model->validate()) {
                return 'error';
            }

            $rows[] = $model->attributes;
    };
}

Знаю о существовании batchInsert ... ON DUPLICATE KEY UPDATE, но здесь данные поступают от клиента и мне нужно делать проверку: AND user_id = 15

Прошу совета, можно ли сделать binding для update, и как это сделать.


Ответы (1 шт):

Автор решения: Akina

версия 8.0.18

Это будет что-то вроде

UPDATE category,
       ( SELECT id, parent, title
         FROM JSON_TABLE(@parameter,
                         "$[*]" COLUMNS( id INT PATH "$.id",
                                         parent INT PATH "$.parent",
                                         title TEXT PATH "$.title" )
                        ) AS jsontable
       ) AS newdata
SET category.parent = newdata.parent,
    category.title = newdata.title
WHERE category.id = newdata.id;

fiddle

→ Ссылка