Как правильно обрабатывать повторяющиеся ошибки в БД - PullRequest
2 голосов
/ 06 октября 2011

Я реализую подписку в БД. Адрес электронной почты должен быть уникальным, поэтому у меня есть уникальный индекс в базе данных. У меня есть этот код на моей странице init:

$f = $p->add('MVCForm');
$f->setModel('Account',array('name','surname','email'));
$f->elements['Save']->setLabel('Subscribe');

if($f->isSubmitted())
{
    try
    {
         $f->update();

         //More useful code to execute when all is ok :)

    }
    catch(Exception_ValidityCheck $v)
    {
        //Handles validity constraint from the model
        $f->getElement($v->getField())->displayFieldError($v->getMessage());
    }
    catch(SQLException $se)
    {
        //If I'm here there is a problem with the db/query or a duplicate email
    }
}

Единственная информация в SQLException - это отформатированное HTML-сообщение. Является ли это единственным способом обнаружить ошибку в дублированной записи?

Ответы [ 3 ]

1 голос
/ 07 октября 2011

Вот один из способов сделать это:

https://github.com/atk4/atk4-web/blob/master/lib/Model/ATK/User.php#L95

Хотя, если вы хотите выполнить настраиваемое действие при дублировании, вы должны переместить getBy за пределы модели в логику страницы.

0 голосов
/ 07 октября 2011

Как и предполагал @Col, мы хотим использовать "insert ignore".

$ form-> update () опирается на Model-> update (), которая затем использует класс DSQL для построения запроса. DSQL поддерживает параметры , но модель создаст для вас новый SQL.

Model-> dsql () создает запрос для модели. Он может функционировать с несколькими «экземплярами», где каждый экземпляр имеет отдельный запрос. Мне не особенно нравится этот подход, и я мог бы добавить новый класс модели, но пока он работает.

Взгляните сюда: https://github.com/atk4/atk4-addons/blob/master/mvc/Model/MVCTable.php#L933

Функция insertRecord () вызывает dsql ('modify', false) несколько раз для построения запроса. Вероятно, самое простое, что вы можете сделать:

function insertRecord($data=array()){
    $this->dsql('modify',false)->option('IGNORE');
    return parent::insertRecord($data);
}

после вставки записи Agile Toolkit автоматически попытается загрузить вновь добавленную запись. Однако он будет использовать соответствующие условия. Я думаю, что если запись игнорируется, вы все равно получите исключение . Если возможно, избегайте исключений в вашем рабочем процессе. Исключения составляют интенсивную загрузку процессора, поскольку они фиксируют обратную трассировку.

Единственным способом может быть полное переопределение insertRecord. Это не идеально, но позволит вам выполнить один запрос так, как вы хотите.

Я предпочитаю вручную проверять условие с помощью loadBy (или getBy), потому что оно принимает условия модели и учитывает соединения. Например, у вас может быть мягкое удаление в вашей таблице, и, хотя ключ MySQL не позволит вам войти, модель и модель-путь имеют больше смысла для бизнес-логики.

0 голосов
/ 06 октября 2011

Почему вы не хотите запустить простой выбор, чтобы проверить, занята ли уже электронная почта?

Или сделайте INSERT IGNORE, а затем проверьте disabled_rows

...