Как проверить дату без дня с помощью sfForm? - PullRequest
3 голосов
/ 18 апреля 2011

Я создаю форму оплаты с помощью symfony 1.4, и в моей форме определен виджет даты, подобный этому, так что пользователь может выбрать дату окончания срока действия своей кредитной карты:

new sfWidgetFormDate(array(
  'format' => '%month%/%year%',
  'years'  => array_combine(range(date('Y'), date('Y') + 5), range(date('Y'), date('Y') + 5))

Обратите внимание на отсутствие% day% в формате, как в большинстве платежных форм.

Теперь моя проблема в том, что sfValidatorDate требует, чтобы поле 'day' не было пустым. Чтобы обойти это, я создал собственный валидатор с помощью обратного вызова, который хорошо работает:

public function validateExpirationDate($validator, $value)
{
  $value['day'] = '15';
  $dateValidator = new sfValidatorDate(array(
    'date_format' => '#(?P<day>\d{2})(?P<month>\d{2})(?P<year>\d{2})#',
    'required'    => false,
    'min'         => strtotime('first day of this month')));
  $dateValidator->clean($value);
  return $value;
}

Я чувствую, что может быть более простой способ достичь этого. Как вы думаете? Вы уже решили эту проблему более чистым способом?

Ответы [ 4 ]

3 голосов
/ 18 апреля 2011

Как вы храните дату?Если вы просто храните месяц и год как целые числа или строки, то вы можете просто создать 2 виджета выбора.Но если вы храните его как datetime (timestamp), тогда вам все равно нужна действительная дата.Это означает, что вам нужно автоматически присваивать значения «день» (обычно первый или последний день месяца).

class YourForm extends BaseYourForm
{
  public function configure()
  {
    $this->widgetSchema['date'] = new sfWidgetFormDate(array(
      'format' => '%month%/%year%'
    ));
    $this->validatorSchema['date'] = new myValidatorDate(array(
      'day_default' => 1
    ));
  }
} 

class myValidatorDate extends sfValidatorDate
{
  protected function configure($options = array(), $messages = array())
  {
    $this->addOption('day_default', 1);
    parent::configure($options, $messages);
  }

  protected function doClean($value)
  {
    if (!isset($value['day']))
    {
      $value['day'] = $this->getOption('day_default');
    }
    return parent::doClean($value);
  }
}
1 голос
/ 22 марта 2013

Сначала я решаю это в классе формы

    $year = range(date('Y'), date('Y') - 50);

    $this->widgetSchema['date'] = new sfWidgetFormDate(array(
      'format' => '%year%',
      'years' => array_combine($year, $year),
      'can_be_empty' => false
    ));

Далее ...

    public function bind(array $taintedValues = null){
      $taintedValues['date']['day'] = '01';
      $taintedValues['date']['month'] = '01';

      parent::bind($taintedValues);
    }

Поле в базе данных имеет тип даты ДАТА.

1 голос
/ 05 июня 2012

Я использовал самый простой способ для подтверждения срока действия кредитной карты:

$post_data = $request->getParameter('my_form');
$post_data['card_exp']['day'] = 1; //sets the first day of the month
$this->form->bind($post_data);

Надеюсь, это кому-нибудь поможет.

1 голос
/ 09 июня 2011

Нет необходимости использовать пользовательский класс проверки: вы можете просто переопределить испорченные значения, передаваемые в ваш метод bind ():

  <?php
  // in your form class
  public function bind(array $taintedValues = null, array $taintedFiles = null)
  {
    $taintedValues['date']['day'] = 1;

    return parent::bind($taintedValues, $taintedFiles);
  }
...