Литий и проверка сложных форм ввода - как? - PullRequest
8 голосов
/ 29 марта 2012

Я сделал довольно много уроков по литиуму (ссылки ниже на случай, если они помогут кому-то еще, а также чтобы показать, что я сделал свою домашнюю работу :), и я понимаю самые основные части создания моделей, видов, контроллеров и использованияMVC для создания записи БД на основе ввода формы.

Однако я новичок в MVC для веб-приложений и Lithium, и я не уверен, как мне писать свой код в более сложных ситуациях.Это общий вопрос, но у меня есть два конкретных вопроса проверки:

  • Как проверить данные даты, отправленные из формы?
  • Как проверить, что два пользователяполя электронной почты имеют одинаковое значение?

Я был бы очень признателен за любую помощь с этими вопросами, и конкретные примеры, подобные этому, также действительно помогут мне понять, как делать хорошее кодирование MVC в других ситуациях.!

Ввод даты - проверка данных, разбитых по нескольким входам формы

По причинам, связанным с пользовательским интерфейсом, в форме регистрации пользователям предлагается ввести свой DOB в трех полях:

<?=$this->form->field('birthday', array('type' => 'select', 'list' => array(/*...*/))); ?>
<?=$this->form->field('birthmonth', array('type' => 'select', 'list' => array(/*...*/))); ?>
<?=$this->form->field('birthyear', array('type' => 'select', 'list' => array(/*...*/))); ?>

Каков наилучший способ проверки этой серверной части?Я думаю, что я должен воспользоваться преимуществами автоматической проверки, но я не уверен, что лучший способ сделать это для набора переменных, которые на самом деле не являются частью Модели.Например:

  • Должен ли я постобработать $this->request->data в UsersController?Например, измените $this->request->data внутри UsersController перед передачей его в Users::create.
  • Должен ли я извлечь поля формы из $this->request->data и использовать статический вызов Validator::isDate внутри UsersController?
  • Есть ли способ написать правило проверки в модели для комбинаций переменных формы, которые не являются частью модели?
  • следует переопределить Users::create и выполнить всю дополнительную проверку и опубликовать-обрабатывать там?

Все они кажутся работающими, хотя некоторые кажутся немного уродливыми, и я не знаю, какие из них могут вызвать у меня серьезные проблемы в будущем.

[РЕДАКТИРОВАТЬ: тесно связана с этим проблема объединения трех полей формы в одно поле, которое будет сохранено в модели]

Запись по электронной почте - проверка двух полей формы идентичны, но сохраняется только одно

В соответствии со здравым смыслом и обычной практикой, форма регистрации просит пользователей указать свой адрес электронной почты дважды:

<?=$this->form->field('email_address'); ?>
<?=$this->form->field('verify_email_address'); ?>

Как мне написать правило автоматической проверки, которое проверяет эти два поля формыимеют то же значение, но сохраняют только email_адрес в базе данных?

Такое чувство, что это почти тот же вопрос, что и выше, потому что список возможных ответов, о которых я могу думать, тот же - поэтому я 'Я представляю это как один вопрос, но я был бы очень признателен за вашу помощь с обеими частями, так как я думаю, что решение этого вопроса будет тонким, различным и одинаково поучительным!

[РЕДАКТИРОВАТЬ: тесно связано спроблема заключается в том, чтобы не сохранять в моей модели и базе данных verify_email_address]

Некоторые фоновые чтения на Lithium

Я читал другие, но эти три урока помогли мне добраться туда, где я нахожусь с пользователями изарегистрироваться сейчас ...

Некоторые другие вопросы StackOverflow по тесно связанным темам (но не отвечая на них и не относящиеся к литию)

  • Один ответ на этот вопросuestion предлагает создать отдельный контроллер (и модель, и ...?) - мне он не кажется «литиевым», и я боюсь, что он также может быть хрупким / легко глючить
  • Эта замечательная история убедила меня, что я был прав, что беспокоился о том, чтобы поместить его в контроллер, но я не уверен, что будет хорошим решением
  • Это на взглядах заставляет меня думать, что я должен каким-то образом поместить его в модель, но я не знаю, как лучше это сделать в Lithium (см. Мой маркированный список в разделе «Ввод даты» выше)
  • И эта Презентация Scribd задала вопрос, на который я надеюсь ответить на последней странице ... после чего он остановился, не ответив на него!

Примечание: ответы в стиле CakePHP тоже хороши. Я не знаю, но это похоже, и я уверен, что могу перевести с него, если мне нужно!

1 Ответ

4 голосов
/ 04 апреля 2012

Я бы порекомендовал сделать это в Model, а не Controller - таким образом, это происходит независимо от того, где вы сохраняете.

Для проблемы с полем даты в вашей модели,переопределите метод save() и обработайте преобразование нескольких полей в данных в одно поле даты перед вызовом parent::save для фактического сохранения.Там могут произойти любые продвинутые манипуляции.

Техника, описанная в вашем комментарии, об использовании скрытого поля формы для получения сообщений об ошибках для отображения звуков довольно хорошо.

Для сравнения, что два поля электронной почты равны,Я бы порекомендовал определить пользовательский валидатор.Вы можете сделать это в своей начальной загрузке, используя Validator :: add .

use lithium\util\Validator;
use InvalidArgumentException;

Validator::add('match', function($value, $format = null, array $options = array()) {
    $options += array(
        'against' => '',
        'values' => array()
    );
    extract($options);
    if (array_key_exists($against, $values)) {
        return $values[$against] == $value;
    }
    return false;
});

Затем в вашей модели:

public $validates = array(
    "email" => array(
        "match",
        "message" => "Please re-type your email address.",
        "against" => "email2"
    )
);

Редактировать :Согласно комментариям, вот способ выполнить пользовательскую проверку правил в контроллере:

public function save() {
    $entity = MyModel::create($this->request->data);
    $rules = array(
        "email" => array(
            "match",
            "message" => "Please re-type your email address.",
            "against" => "email2"
        )
    );

    if (!$entity->validates($rules)) {
        return compact('entity');
    }

    // if your model defines a `$_schema` and sets `$_meta = array('locked' => true)`
    // then any fields not in the schema will not be saved to the db

    // here's another way using the `'whitelist'` param
    $blacklist = array('email2', 'some', 'other', 'fields');
    $whitelist = array_keys($entity->data());
    $whitelist = array_diff($whitelist, $blacklist);

    if ($entity->save(null, compact('whitelist'))) {
        $this->redirect(
            array("Controller::view", "args" => array($entity->_id)),
            array('exit' => true)
        );
    }

    return compact('entity');
}

Преимущество задания данных для сущности состоит в том, что они будут автоматически предварительно заполнены в вашей форме, если будет ошибка проверки.

...