13 de abr. de 2012

Symfony - Validação de datas com sfForm

Esses dias precisei implementar uma validação de datas de início e fim com os validators de forms do Symfony, onde, obviamente, a data de fim tem que ser maior (ou igual, neste caso) a data de início. Neste caso, eu recebo as datas no formato "dd/mm/aaaa - HH:MM", portanto foi preciso configurar também o formato de datas de entrada para o validator. Validação com Symfony é muito simples, e ele já configura uma validação padrão, conforme o mapeamento das entidades, já validando por tipo entre outros.

No form de exemplo abaixo, pode ser notado os 2 campos de data início (dtini) e fim (dtfim), onde configuro inicialmente o validator de data e hora (sfValidatorDateTime) para ambos, informando nas opções que a data mínima (min) aceita é o dia atual, na primeira hora do dia, que deverá ser fornecido a hora (with_time), o formato de exibição da data inválida em caso de erro (date_format_range_error), o formato de saída da data pós validação para gravação no banco (datetime_output) e o formato de entrada de data (date_format).

Com isso já temos os 2 campos de datas sendo criticados de forma que o usuário não preencha uma data anterior a hoje, para fazer com que a data final seja validada como maior ou igual a data inicial, utilizei o método bind, já que na instanciação e configuração do form, não temos como ter acesso ao valor submetido. No bind, obtenho então o valor da data inicial, e configuro como sendo a data mínima do validator da data final, pronto!

Uma outra possível alternativa é utilizar o sfValidatorCallback ou talvez o hook de postValidator.

Caso visualizem formas melhores de fazer o mesmo, indiquem nos comentários.


class MyEntityForm extends MyEntityBaseForm {

    public function configure() {
         $dtInput = new sfWidgetFormInputText(array(), array(
            'size' => 14,
            'maxlength' => 10
        ));
        $this->setWidget('dtini', $dtInput);
        $this->setWidget('dtfim', $dtInput);

        // Validators
        // Recebo as datas no formato dd/mm/aaaa - hh:mm (d/m/Y - H:i)
         $options = array(
            'min' => date('Y-m-d') . ' 00:00:00',
            'with_time' => true,
            'date_format_range_error' => 'd/m/Y',
            'datetime_output' => 'Y-m-d H:i:s',
            'date_format' => '~(?P\d{2})/(?P\d{2})/(?P\d{4})\ \-\ (?P\d{2}):(?P\d{2})~'
        );
        $dtValidator = new sfValidatorDateTime($options);
        $this->setValidator('dtini', $dtValidator);
        $this->setValidator('dtfim', $dtValidator);

        $this->getWidgetSchema()->setLabels(array(
            'dtini' => 'Data Início',
            'dtini' => 'Data Fim'
        ));
    }

    /**
     * (non-PHPdoc)
     * @see lib/vendor/symfony/lib/form/sfForm#bind($taintedValues, $taintedFiles)
     */
    public function bind(array $taintedValues = null, array $taintedFiles = null) {
        $dtIni = isset($taintedValues['dtini'])?$taintedValues['dtini']:null;
        if ($dtIni) {
            $dt = DateTime::createFromFormat('d/m/Y - H:i', $dtIni);
            $this->getValidator('dtfim')->setOption('min',
               $dt->format('Y-m-d H:i:s'));
        }

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

29 de jan. de 2012

Enviar informações do controller para o layout no Symfony 1.x

Esses dias precisei enviar/configurar uma variável do controller para o layout, ao contrário de enviar do controller para a respectiva visão deste, que é o mais normal, após pesquisar vi que uma maneira de fazê-lo é usando os slots, como pode ser visto neste link, no exemplo da documentação, ele cita um exemplo de uso para áreas do site, o que também é interessante.

Para usar é simples, basta configurar a variável no controller conforme abaixo:

$this->getResponse()->setSlot('myKey', $myVar);

e recuperá-la no layout como abaixo:

$myVar = get_slot('myKey', 'myDefaultValue');

simples e funcional.

Fica a dica.

4 de jan. de 2012

Symfony: Problema com dados na view (escape)

Dica rápida: já havia usado isso algumas vezes, mas nunca catalogava como snippet ou algo semelhante, hoje precisei novamente e encontrei o link abaixo explicando como obter valores brutos na view.

Veja o post clicando aqui.