Illustration of a bird flying.

Zend Filter – Aprendendo criar filtros customizados


Se você já leu a minha sequência de posts sobre o Zend Form ou já sabe como trabalhar com forms, deve conhecer o Zend Filter, certo? Hoje mostrarei como criar seus próprios filtros e vinculá-los em seus forms.

Antes de qualquer coisa

Caso ainda não saiba trabalhar com o Zend Form, sugiro a leitura destes posts:

Zend Form – Trabalhando com formulários no Zend 2 e 3 e Zend Form – Injeção de dependências. Este último é apenas um plus, não é necessário o ler para entender o que será feito aqui.

O que é o Zend Filter?

É um componente do Zend Framework que possibilita muitos tipos de filtros para uso nas mais diversas situações. Ele pode ser utilizado em formulários, “hidratação” de dados para views, etc. É possível o utilizar no ZF, outros frameworks e até mesmo sem, apenas utilizando o Composer pra gerenciar tudo.

Por que usar Zend Filter?

Um dos benefícios é que você já tem diversos filtros prontos para utilizar, tais como StringTrim, StripTags, ToInt e muitos outros, veja a lista completa no GitHub. Além de tudo o que já está pronto, você pode criar outros filtros conforme sua necessidade. São exemplos de filtros que você pode criar: aplicar/remover máscara em CPF, CNPJ, telefone, placa de veículos, números de protocolos e apólices, etc.

Estrutura básica de um filtro

namespace Application\Filter;

use Zend\Filter\FilterInterface;

class MyFilter implements FilterInterface
{
    public function filter($value)
    {
        // perform some transformation upon $value to arrive on $valueFiltered

        return $valueFiltered;
    }
}

Bem simples, não? Veja no código acima que tudo o que precisamos fazer é implementar uma interface e pronto!

Vamos agora criar nosso filtro pra aplicar máscara em CPF?

CPFMaskFilter

namespace Application\Filter;

use Zend\Filter\FilterInterface;

class CPFMaskFilter implements FilterInterface
{
    /**
     * @inheritdoc
     */
    public function filter($value)
    {
        // removendo qualquer "poluição" da string e obtendo somente os dígitos
        $value = preg_replace("/\D/", '', $value);
        // Validando se o CPF possui a quantidade certa de caracteres
        if (strlen($value) !== 11) {
            return '';
        }

        // Definindo padrões: 3 sequências com 3 dígitos e uma com 2
        $pattern = "/(\d{3})(\d{3})(\d{3})(\d{2})/";

        // as duas primeiras sequências de 3 dígitos são separadas por um ponto, 
        // a última, por um hífen
        $replacement = "\$1.\$2.\$3-\$4";

        // aplicando a máscara e retornando o valor filtrado
        return preg_replace($pattern, $replacement, $value);
    }
}

Agora é só usar no seu form filter.

InputFilter

// module/Application/src/Form/ExampleFormFilter

$inputFilter->add([
    'name' => 'cpf',
    'required' => true,
    'filters' => [
        // ...
        ['name' => \Application\Filter\CPFMaskFilter::class],
    ],
    'validators' => [
        // ...
    ],
]);

Pronto! Agora pode criar filtros conforme sua necessidade.

Como usar fora do FormFilter

O mais legal é que esse filtro não é limitado somente ao uso em Form Filters, você pode o utilizar para qualquer finalidade. Veja um exemplo de como o utilizar na view para apresentar o CPF formatado corretamente.

Primeiro cria-se um ViewHelper.

namespace Application\View\Helper;

use Application\Filter\CPFMaskFilter;
use Zend\View\Helper\AbstractHelper;

class CPFMaskViewHelper extends AbstractHelper
{
    public function __invoke($cpf)
    {
        // Este ViewHelper que criamos apenas delega o trabalho ao filtro que criamos anteriormente
        return (new CPFMaskFilter())->filter($cpf);
    }
}

Em seguida um alias para o mesmo, para utilizarmos na view.

// module/Application/src/Module.php

public function getViewHelperConfig()
{
    return [
        'invokables' => [
            // ...
            'cpfMask' => \Application\View\Helper\CPFMaskViewHelper::class
        ]
    ];
}

Na view

E por fim, o utilizando na view.

Com .phtml (padrão do Zend)

<?php echo $this->cpfMask('12345678901'); ?>

Com Twig

{{ cpfMask('12345678901') }}

Em ambos os exemplos a saída é: 123.456.789-01

That’s all!

Lembre-se, filtro != validador.

Enquanto o validador tem o papel de criar asserções para uma determinada regra, o filtro apenas “hidrata” os dados recebidos. Desta forma, se por algum motivo o usuário informar um CPF como este 000…..000.000–00, somente pra testar uma possível vulnerabilidade, o filtro deixará o resultado assim: 000.000.000-00. Caso passe com um dígito a mais em qualquer posição, será feita a “limpeza” e, se o resultado for algo diferente de 11 caracteres, o retorno será uma string vazia.

Assim como já explicado nos posts anteriores sobre o Zend Form, o filtro é mais uma camada de segurança para sua aplicação. O usuário mal intencionado pode facilmente desativar o JavaScript e passar por toda e qualquer validação pelo lado do browser, mas não terá este mesmo poder com o server. Por isso é importante ter filtros e validações nas duas extremidades.