Блог хеллоуворлдщика

SELECT FOR UPDATE в Yii2


Недавно пришлось тряхнуть стариной и вспомнить, как работать с Yii... Задача предельно проста: добавить SELECT FOR UPDATE. Но, задача не проста для Yii2, особенно, если уже долгое время работаешь с Doctrine...

Оф. репозиторий фреймворка нам сообщает, что из коробки такой возможности нет и, что решать данную проблему нужно самому.

Так же, есть расширение, которое не имеет какого-то смысла вообще, т.к. суть работы SELECT FOR UPDATE не реализована.

Еще, есть вот такое, но я его особо не смотрел, вроде рабочее. Если кто-то тестил и юзал - пишите в комменты.

Дак что же делать для тех, кто хочет просто применить SELECT FOR UPDATE? Решение очень простое! Нужно всего лишь...

использовать yii\db\ActiveRecord::findBySql()!

Пишем метод в модели:

public static function findOneForUpdate(int $id): ?ActiveRecord
{
    $sql = self::find()
        ->where(['id' => $id])
        ->createCommand()
        ->getRawSql();
 
    return self::findBySql($sql . ' FOR UPDATE')->one();
}

И все!

share via vkontakte share via facebook share via mailru share via odnoklassniki share via twitter

Комментарии [7]

[Александр] 26 сент. 2018 г., 18:12:37

Здравствуйте, а можно более детально установку? На примере...

Администратор [IAMRUSTY] 26 сент. 2018 г., 18:27:38

Нет установки. Просто добавляете метод в свой абстрактный класс унаследованный от класс yii\db\ActiveRecord из ядра фреймворка.

[Александр] 26 сент. 2018 г., 19:16:38

Это для меня набор букв, на примере можете показать?

Администратор [IAMRUSTY] 26 сент. 2018 г., 19:20:24
abstract class YourActiveRecord extends \yii\db\ActiveRecord
{
    public static function findOneForUpdate(int $id): ?YourActiveRecord
    {
        $sql = self::find()
            ->where(['id' => $id])
            ->createCommand()
            ->getRawSql();
 
        return self::findBySql($sql . ' FOR UPDATE')->one();
    }
}
 
/**
 * @param int $id
 * @param int $counter
 */
class YourModel extends YourActiveRecord
{
 
}
 
$yourModel = YourModel::findOneForUpdate(14);
++$yourModel->counter;
$yourModel->save();
[Александр] 26 сент. 2018 г., 20:08:28

Я так и делал но выдает ошибку: syntax error, unexpected ':', expecting ';' or '{' На строку: public static function findOneForUpdate(int $id): ?YourActiveRecord

Администратор [IAMRUSTY] 26 сент. 2018 г., 20:10:53

Пример рассчитан на PHP 7.1 и выше. Если у Вас версия ниже - уберите type hinting из кода.

Администратор [IAMRUSTY] 26 сент. 2018 г., 20:11:57
abstract class YourActiveRecord extends \yii\db\ActiveRecord
{
    public static function findOneForUpdate($id)
    {
        $sql = self::find()
            ->where(['id' => $id])
            ->createCommand()
            ->getRawSql();
 
        return self::findBySql($sql . ' FOR UPDATE')->one();
    }
}
 
/**
 * @param int $id
 * @param int $counter
 */
class YourModel extends YourActiveRecord
{
 
}
 
$yourModel = YourModel::findOneForUpdate(14);
++$yourModel->counter;
$yourModel->save();