Zend framework 2 filters - zend-framework2

When I use InputFilter required is not considered in int filters
$inputFilter->add($factory->createInput(array(
'name' => 'id',
'required' => true,
'filters' => array(
array('name' => 'Int'),
),
)));

You need to use allowEmpty attribute in order to force your InputFilter component to reject empty values.
$inputFilter->add($factory->createInput(array(
'name' => 'id',
'required' => true,
'allowEmpty' => false, // <--- Look ma
'filters' => array(
array('name' => 'Int'),
),
)));

Are you sure you want to use the Int InputFilter? Its function is to convert a scalar value to an Integer. Its code is just:
public function filter($value)
{
return (int) ((string) $value);
}
Which transforms the value to a string. If your value is an empty string, it'll convert it to 0, the reason why afterwards, in the validator's execution process, the required is not working (it checks a 0).
It seems to me, because of the name id of your input, that you just want to force users to enter something that must be a numeric. You can do it this way:
$inputFilter->add( $factory->createInput( array(
'name' => 'id',
'required' => true,
'validators' => array(
array( 'name' => 'Digits' ),
)
) );

Related

How to validate empty input in Zend Framework 2

I'm doing a registration form in ZF2, but I don't get how to validate. Validation seems not working.
I'm adding the validators array, but it doesn't work anyways. I don't know how can I fix that.
This is my code of controller:
namespace Application\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use Application\Form\Formularios;
use Zend\Db\Adapter\Adapter;
use Application\Modelo\Entity\Usuarios;
class FormularioController extends AbstractActionController
{
public $dbAdapter;
public function indexAction()
{
return new ViewModel();
}
public function registroAction()
{
if($this->getRequest()->isPost())
{
$this->dbAdapter=$this->getServiceLocator()->get('Zend\Db\Adapter');
$u=new Usuarios($this->dbAdapter);
//echo "se recibiĆ³ el post";exit;
$data = $this->request->getPost();
$u->addUsuario($data);
return $this->redirect()->toUrl($this->getRequest()->getBaseUrl().'/application/formulario/registro/1');
}else
{
//zona del formulario
$form=new Formularios("form");
$id = (int) $this->params()->fromRoute('id', 0);
$valores=array
(
"titulo"=>"Registro de Usuario",
"form"=>$form,
'url'=>$this->getRequest()->getBaseUrl(),
'id'=>$id
);
return new ViewModel($valores);
}
}
}
this is my form code with validator
class Formularios extends Form
{
public function __construct($name = null)
{
parent::__construct($name);
$this->add(array(
'name' => 'name',
'required' => true,
'allow_empty' => false,
'options' => array(
'label' => 'Nombre Completo',
),
'attributes' => array(
'type' => 'text',
'class' => 'input'
),
'filters' => [ ['name' => 'StringTrim'], ],
'validators' => array(
array(
'name' => 'NotEmpty',
'options' => array(
'messages' => array(
\Zend\Validator\NotEmpty::IS_EMPTY => 'Ingrese Nombres.',
))))
));
$this->add(array(
'name' => 'lastname',
'required' => true,
'options' => array(
'label' => 'Apellido',
),
'attributes' => array(
'type' => 'text',
'class' => 'input'
),
'validators' => array(
array(
'name' => 'NotEmpty',
'options' => array(
'messages' => array(
\Zend\Validator\NotEmpty::IS_EMPTY => 'Ingrese Apellidos.',
))))
));
Thanks in advance
First problem.
$data = $this->request->getPost(); should be $data = $this->getRequest()->getPost();
Second problem is that you call your validators direclty when you build your form in the view, which is wrong. The right way to do is via an inputFilter. Now, there are many ways to to this, for example: with or without a factory called from your model or via the for class with a form element manager
I will show you the model way with a factory since it's easier for new comers.
namespace MyModule\Model;
use Zend\InputFilter\InputFilter;
use Zend\InputFilter\Factory as InputFactory;
use Zend\InputFilter\InputFilterAwareInterface;
use Zend\InputFilter\InputFilterInterface;
class MyModel implements InputFilterAwareInterface
{
/**
* #var null $_inputFilter inputFilter
*/
private $_inputFilter = null;
// some more code like exhnageArray get/set method
public function setInputFilter(InputFilterInterface $inputFilter)
{
throw new \Exception("Not used");
}
public function getInputFilter()
{
if (!$this->inputFilter) {
$inputFilter = new InputFilter();
$factory = new InputFactory();
$inputFilter->add(
$factory->createInput([
'name' => 'id',
'required' => false,
'filters' => [
['name' => 'Int'],
],
])
);
$inputFilter->add(
$factory->createInput([
"name"=>"title",
"required" => true,
'filters' => [
['name' => 'StripTags'],
['name' => 'StringTrim'],
],
'validators' => [
['name' => 'NotEmpty'],
[
'name' => 'StringLength',
'options' => [
'encoding' => 'UTF-8',
'min' => 1,
'max' => 200,
],
],
],
])
);
$inputFilter->add(
$factory->createInput([
"name"=>"text",
"required" => true,
'filters' => [
['name' => 'StripTags'],
['name' => 'StringTrim'],
],
'validators' => [
['name' => 'NotEmpty'],
[
'name' => 'StringLength',
'options' => [
'encoding' => 'UTF-8',
'min' => 1,
],
],
],
])
);
$this->inputFilter = $inputFilter;
}
return $this->inputFilter;
}
}
Third proble. DO NOT EVER use serviceManager in controller. It's a really really really bad practice. Instead use a factory.

Zend Framework 2 Form With Password

I'm using zend framework 2, how can I force the user has set a password of 8 characters min, but both letters and numbers?
This is my code:
$this->add(array(
'name' => 'password',
'attributes' => array(
'type' => 'password',
'id' => 'password',
'class' => 'span12 noradius',
'placeholder' => 'Password'
),
'options' => array(
'label' => 'Password :'
)
));
You can write a custom validator, check this out: http://framework.zend.com/manual/2.0/en/modules/zend.validator.writing-validators.html
class MyValid\PasswordStrength extends Zend\Validator\AbstractValidator
{
const LENGTH = 'length';
const UPPER = 'upper';
const LOWER = 'lower';
const DIGIT = 'digit';
protected $messageTemplates = array(
self::LENGTH => "'%value%' must be at least 8 characters in length",
self::UPPER => "'%value%' must contain at least one uppercase letter",
self::LOWER => "'%value%' must contain at least one lowercase letter",
self::DIGIT => "'%value%' must contain at least one digit character"
);
public function isValid($value)
{
$this->setValue($value);
$isValid = true;
if (strlen($value) < 8) {
$this->error(self::LENGTH);
$isValid = false;
}
if (!preg_match('/[A-Z]/', $value)) {
$this->error(self::UPPER);
$isValid = false;
}
if (!preg_match('/[a-z]/', $value)) {
$this->error(self::LOWER);
$isValid = false;
}
if (!preg_match('/\d/', $value)) {
$this->error(self::DIGIT);
$isValid = false;
}
return $isValid;
}
}
You then select the custom validator:
$inputFilter->add($factory->createInput(array(
'name' => 'password',
'required' => true,
'validators' => array(
array(
// What ever your namespace is etc determines this..
'name' => 'My\Validator\PasswordStrength',
),
),
)));

Chaining Dependency Injection in ZF2

I am trying to create a simple email templating test in ZF2, I am using Dependency injection in order to create an instance of the PhpRenderer class, with all the dependencies set.
It appears that I may be struggling with chaining the injections as the path 'email' is not present in the AggregateResolver.
inside module.config.php
'di' => array(
'instance' => array(
'Zend\View\Resolver\TemplatePathStack' => array(
'options' => array(
'script_paths' => array(
'email' => __DIR__ . '/../view/application/email',
),
),
),
'Zend\View\Resolver\AggregateResolver' => array(
'attach' => array(
'Zend\View\Resolver\TemplatePathStack',
),
),
'Zend\View\Renderer\PhpRenderer' => array(
'setResolver' => 'Zend\View\Resolver\AggregateResolver',
),
),
),
inside TestController.php
$di = new \Zend\Di\Di;
$renderer = $di->get('Zend\View\Renderer\PhpRenderer');
$content = $renderer->render('email/test', null);
echo($content);
Message:
Zend\View\Renderer\PhpRenderer::render: Unable to render template "email/test"; resolver could not resolve to a file
Any help would be gratefully received.
Since writing the above, I was playing around and removed the TemplatePathStack from the di array and this had no effect at all, So I am not sure it is being used at all by the AggregateResolver, so it may be a chaining issue:
'di' => array(
'instance' => array(
/*'Zend\View\Resolver\TemplatePathStack' => array(
'addPaths' => array(
'paths' => array(
'email' => __DIR__ . '/../view/application/email',
),
),
),*/
'Zend\View\Resolver\AggregateResolver' => array(
'attach' => array(
'Zend\View\Resolver\TemplatePathStack',
),
),
'Zend\View\Renderer\PhpRenderer' => array(
'setResolver' => 'Zend\View\Resolver\AggregateResolver',
),
),
),
Aborgrove
In the end I solved it by moving the di array out of the module.conf.php and recreating it in the Module getServiceConf() method. (Although I am not sure this is the best place to put it)
public function getServiceConfig()
{
return array(
'factories' => array(
// using the Session Manger to create one instance of the follwing models
......... more code here ............
'EmailTemplatePathStack' => function($sm) {
$template_path_stack = new \Zend\View\Resolver\TemplatePathStack();
$paths = array('emailfolder' => __DIR__ . '/view/application/email');
$template_path_stack->addPaths($paths);
return $template_path_stack;
},
'EmailAggregateResolver' => function($sm) {
$resolver = new \Zend\View\Resolver\AggregateResolver();
$resolver->attach($sm->get('EmailTemplatePathStack'));
var_dump($resolver);
return $resolver;
},
'EmailPhpRenderer' => function($sm) {
$php_renderer = new \Zend\View\Renderer\PhpRenderer();
$php_renderer->setResolver($sm->get('EmailAggregateResolver'));
return $php_renderer;
},
),
);
}
Then changing the controller to:
$sm = \Application\Model\ServiceLocatorFactory::getInstance();
$renderer = $sm->get('EmailPhpRenderer');
$content = $renderer->render('test.phtml', null);
echo($content);

I need help about Input Filter

I have this method in Model TaiKhoan
public function getInputFilter()
{
if (!$this->inputFilter)
{
$inputFilter = new InputFilter();
$factory = new InputFactory();
$inputFilter->add($factory->createInput(array(
'name' => 'TenTaiKhoan',
'required' => true,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim'),
),
)));
$inputFilter->add($factory->createInput(array(
'name' => 'MatKhau',
'required' => true,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim'),
),
)));
}
return $this->$inputFilter;
}
Then i used it in my Controller like
$taikhoan = new TaiKhoan();
$form->setInputFilter($taikhoan->getInputFilter());
When i run, it show me this error
Catchable fatal error: Object of class Zend\InputFilter\InputFilter could not be converted to string in C:\wamp\www\ZF\module\CPanel\src\CPanel\Model\TaiKhoan.php on line 59
The problem is a typo in this statement:
return $this->$inputFilter;
PHP is interpreting this line as a dynamic property name, and this converting it to a string. The correct version is:
return $this->inputFilter;
Also you need to assign something to the input filter:
public function getInputFilter()
{
if (!$this->inputFilter)
{
// ...
$this->inputFilter = $inputFilter;
}
return $this->inputFilter;
}
You are lazy loading the input filter, but never setting $this->inputFilter.
public function getInputFilter()
{
if (!$this->inputFilter)
{
$this->inputFilter = new InputFilter();
}
return $this->inputFilter;
}
Not sure if this is your problem because the error is about casting your input filter to a string. Please provide the exact code on line 59 of TaiKhoan.php.

2 different ways to define a widget in symfony, which to use?

in the tutorial i can use either:
public function configure() {
$this->setWidgets(array(
'type' => new sfWidgetFormChoice(array(
'choices' => Doctrine_Core::getTable('Gender')->getTypesForForm(),
'expanded' => false,
'multiple' => false,
))
));
$this->widgetSchema['type'] = new sfWidgetFormChoice(array(
'choices' => Doctrine_Core::getTable('Gender')->getTypesForForm(),
'expanded' => false,
'multiple' => false,
));
}
to define a widget.
i wonder which i should use and why there is 2 ways of writing this?
thanks
They're equivalent; setWidgets() is cleaner: it doesn't assume that $this->widgetSchema is an array (accessing $this->widgetSchema directly breaks the encapsulation), plus, it allows you to set multiple widgets at once.

Resources