Страница 1 из 1

Запрет создания дублей

Добавлено: 2019.02.14, 13:40
Brainfuck
Есть действие которое создает статью с заданным именем. На модели висит валидатор unique для этого поля и все хорошо работает. Но мне сказали что если два раза быстро засабмитить форму то таки создаются две одинаковых статьи. Как не допустить этого? Mutex? Или есть способ попроще?

Кроме того, я сейчас пытался сделать с мутексом, но мне непонятна одна вещь. Вот есть два действия: форма создания статьи и форма редактирования статьи. После создания должен быть редирект на форму редактирования. Я поставил валидацию сразу после освобождения мутекса, но если она не проходит я не знаю куда редиректить, т.к. у меня нет id созданной статьи.

Если непонятно - вот пример:

Код: Выделить всё

/**
 * @property int $id
 * @property string $name
 */
class Article extends ActiveRecord
{
    public function rules() {
        return [
            ['name', 'required'],
            ['name', 'unique'],
        ];
    }
}

public function actionCreate() {
	$model = new Article();
	$model->load(Yii::$app->request->post();

	if (Yii::$app->request->isAjax) { // тут еще аяксовая валидация у меня
		Yii::$app->response->format = Response::FORMAT_JSON;
		return ActiveForm::validate($model);
	}

	$mutex = new Mutex();

	while (!$mutex->acquire($this->action->id))
		sleep(1);

	if (!$model->validate())
		return $this->redirect(['article/update', 'id' => ???]); // как тут правильнее сделать??? я же даже не знаю - может валидация не из-за имени не прошла (там есть и другие поля в реале)

	$model->save();
	$mutex->release($this->action->id);
	return $this->redirect(['article/update', 'id' => $model->id]);
}
P.S. Была идея тупо задизейблить кнопку отправки при клике, но это не решение, т.к. можно же и Enter-ом форму отправлять

Re: Запрет создания дублей

Добавлено: 2019.02.14, 14:08
someweb
Уникальный индекс на поле name.
Не надо делать редирект, показывайте форму заново с ошибками.

Re: Запрет создания дублей

Добавлено: 2019.02.14, 14:19
chesar

Код: Выделить всё

public function actionCreate()
  {
    $model = new Article();

    $mutex = new Mutex();
    
    $mutexName = Article::class . $model->name;

    if ($mutex->acuire($mutexName) && $model->load() && $model->save()) {
      $mutex->release($mutexName);
      return $this->redirect('update', ['id' => $model->id]);
    }

    $mutex->release($mutexName);
    return $this->render('create', ['model' => $model]);    
  }

Re: Запрет создания дублей

Добавлено: 2019.02.14, 15:09
Brainfuck
someweb писал(а): 2019.02.14, 14:08 Уникальный индекс на поле name.
Во первых так юзер увидит ошибку вместо редиректа на созданную форму. Во вторых уникальный индекс нельзя делать, т.к. имя не уникальное допускается в пределах одной таблицы (там от одного поля еще зависит уникальность).
someweb писал(а): 2019.02.14, 14:08 Не надо делать редирект, показывайте форму заново с ошибками.
Не получится так. Форма модальная

Re: Запрет создания дублей

Добавлено: 2019.02.14, 15:15
Brainfuck
chesar писал(а): 2019.02.14, 14:19

Код: Выделить всё

public function actionCreate()
  {
    $model = new Article();

    $mutex = new Mutex();
    
    $mutexName = Article::class . $model->name;

    if ($mutex->acuire($mutexName) && $model->load() && $model->save()) {
      $mutex->release($mutexName);
      return $this->redirect('update', ['id' => $model->id]);
    }

    $mutex->release($mutexName);
    return $this->render('create', ['model' => $model]);    
  }
Не подходит. Форма создания модальная

Re: Запрет создания дублей

Добавлено: 2019.02.14, 15:24
someweb
Уникальный индекс можно по двум полям сделать.
А чем модальность мешает?
Если есть ошибки, открываете модальное окно сразу и все.

Re: Запрет создания дублей

Добавлено: 2019.02.14, 15:53
Brainfuck
Ладно не важно. Добавил лишний запрос на id вставленной записи для редиректа