i have my application based in ZendSkeletonApplication , now i want create to relationship between my models so:
user portal
id id
firstName name
lastName url
........
portal_Id
I want to fill my select-option in the user form with database values
<?php
namespace Register\Form;
use Zend\Captcha\AdapterInterface as CaptchaAdapter;
use Zend\Form\Form;
use Zend\Form\Element;
class UserForm extends Form
{
protected $portalTable;
public function __construct($name = null)
{
parent::__construct('user');
$this->setAttribute('method', 'post');
$this->setAttribute('class', 'form-horizontal');
$this->add(array(
'name' => 'id',
'attributes' => array(
'type' => 'hidden',
),
));
$this->add(array(
'type' => 'Select',
'name' => 'portal_id',
'options' => array(
'label' => 'Portal',
'empty_option' => 'Seleccione un portal',
'value_options' => array(
'1' => 'portal 1',
'2' => 'portal 2',
'3' => 'portal 3',
//i want option from database with
),
)
));
$this->add(array(
'name' => 'firstName',
'attributes' => array(
'type' => 'text',
),
'options' => array(
'label' => 'First Name',
),
));
$this->add(array(
'name' => 'lastName',
'attributes' => array(
'type' => 'text',
),
'options' => array(
'label' => 'Last Name',
),
));
$this->add(array(
'name' => 'login',
'attributes' => array(
'type' => 'text',
),
'options' => array(
'label' => 'Login',
),
));
$this->add(array(
'name' => 'password',
'attributes' => array(
'type' => 'password',
),
'options' => array(
'label' => 'Password',
),
));
$this->add(array(
'name' => 'password_repeat',
'attributes' => array(
'type' => 'password',
),
'options' => array(
'label' => 'password (repeat)',
),
));
$this->add(array(
'name' => 'email',
'attributes' => array(
'type' => 'text',
),
'options' => array(
'label' => 'Email',
),
));
$this->add(array(
'type' => 'Zend\Form\Element\Csrf',
'name' => 'csrf',
'options' => array(
'csrf_options' => array(
'timeout' => 600
)
)
));
$this->add( array(
'type' => 'Captcha',
'name' => 'captcha',
'options' => array(
'label' => 'Please verify you are human.',
'captcha' => array('class' => 'Dumb',
),
),
));
$this->add(array(
'name' => 'submit',
'attributes' => array(
'type' => 'submit',
'value' => 'Go',
'id' => 'submitbutton',
),
));
}
}
in this part i want fill select from database
$this->add(array(
'type' => 'Select',
'name' => 'portal_id',
'options' => array(
'label' => 'Portal',
'empty_option' => 'Seleccione un portal',
'value_options' => array(
'1' => 'portal 1',
'2' => 'portal 2',
'3' => 'portal 3',
//i want option from database with
),
)
));
sorry for my English
I have written an in-depth blog "Zend\Form\Element\Select and Database-Values" about this topic. Basically though, this is what you have to do:
Basically all you have to do is Query the Database inside your Form for the Data. For this you need the DB-Adapter to be available inside your Form, which is done by Dependency-Injection. Since the DB-Adapter is required for your Form to function correctly, i'd suggest Setter-Injection.
Inside your getServiceConfig() do this:
return array('factories' => array(
'namespace-form-formname' => function($sm) {
$dbA = $sm->get('Zend\Db\Adapter\Adapter');
$form = new \Namespace\Form\Formname($dbA);
return $form;
}
));
This will inject the Zend\Db\Adapter\Adapter into your form, which should already be valid though other configuration. Then you need to modify your form code a little bit:
public function __construct(\Zend\Db\Adapter\Adapter $dbA) {
parent::__construct('form-name');
// Do the DB-Query here. You got the DB-Adapter
// http://zf2.readthedocs.org/en/latest/modules/zend.db.adapter.html
$selectArray = array(
'key' => 'value',
'key' => 'value',
'key' => 'value',
); // obviously, this is just a fake-$selectArray demonstrating
// what the output of your Queries should be
// Add your Form Elements here
// use $selectArray as value_options of your desired select element
}
And that's basically it. Sadly i can't give you an concrete example, as i've never worked with Zend\Db, but i assume this will get you started.
PS: In your controller, call the form like this:
$form = $this->getServiceLocator()->get('namespace-form-formname');
Try:
// add code on controller
$arrPortalId = array();
$results = array('1' => 'portal 1', '2' => 'portal 2', '3' => 'portal 3',); // this part change your database value
foreach ($results as $key => $val) {
$arrPortalId[$key] = $va;
}
$dataParams['portalId'] = $arrPortalId;
$form = new UserForm($dataParams);
<?php
namespace Register\Form;
use Zend\Captcha\AdapterInterface as CaptchaAdapter;
use Zend\Form\Form;
use Zend\Form\Element;
class UserForm extends Form
{
protected $portalTable;
public function __construct($params = array())
{ $name = isset($params['name'])?$params['name']:'';
parent::__construct('user');
$this->setAttribute('method', 'post');
$this->setAttribute('class', 'form-horizontal');
$this->add(array(
'name' => 'id',
'attributes' => array(
'type' => 'hidden',
),
));
$portalId = (isset($params['portalId']) && count($params['portalId']) > 0)?$params['portalId']:array();
$this->add(array(
'type' => 'Select',
'name' => 'portal_id',
'options' => array(
'label' => 'Portal',
'empty_option' => 'Seleccione un portal',
'value_options' => $portalId,
)
));
$this->add(array(
'name' => 'firstName',
'attributes' => array(
'type' => 'text',
),
'options' => array(
'label' => 'First Name',
),
));
$this->add(array(
'name' => 'lastName',
'attributes' => array(
'type' => 'text',
),
'options' => array(
'label' => 'Last Name',
),
));
$this->add(array(
'name' => 'login',
'attributes' => array(
'type' => 'text',
),
'options' => array(
'label' => 'Login',
),
));
$this->add(array(
'name' => 'password',
'attributes' => array(
'type' => 'password',
),
'options' => array(
'label' => 'Password',
),
));
$this->add(array(
'name' => 'password_repeat',
'attributes' => array(
'type' => 'password',
),
'options' => array(
'label' => 'password (repeat)',
),
));
$this->add(array(
'name' => 'email',
'attributes' => array(
'type' => 'text',
),
'options' => array(
'label' => 'Email',
),
));
$this->add(array(
'type' => 'Zend\Form\Element\Csrf',
'name' => 'csrf',
'options' => array(
'csrf_options' => array(
'timeout' => 600
)
)
));
$this->add( array(
'type' => 'Captcha',
'name' => 'captcha',
'options' => array(
'label' => 'Please verify you are human.',
'captcha' => array('class' => 'Dumb',
),
),
));
$this->add(array(
'name' => 'submit',
'attributes' => array(
'type' => 'submit',
'value' => 'Go',
'id' => 'submitbutton',
),
));
}
}
Related
I am creating page to insert data like a book. Where I'm using zend form fieldset and collection. Fieldset have only two fields heading field and content field. Heading and sub-heading have same content(fields).
Ex:
1: Heading Content
1.1: Sub Heading
Content
1.1.1: Sub Heading
Content
1.1.2: Sub Heading
Content
1.1.2.1: Sub Heading
Content
1.1.2.2: Sub Heading
Content
...
1.1.3: Sub Heading
Content
..
1.2: Sub Heading
Content
...
2: Heading Content
Note: here indexing is just to show the parent child relationship.
Code are below:
This is main form.
class BookPointlForm extends Form
{
public function __construct($name = null)
{
parent::__construct('Form');
$this->add(array(
'type' => 'Zend\Form\Element\Collection',
'name' => 'points',
'attributes' => array(
'class'=> 'point_collection '
),
'options' => array(
'label' => 'Add Book Points',
'count' => 1,
'should_create_template' => true,
'allow_add' => true,
'target_element' => array(
'type' => 'Book\Form\BookPointMainFieldset',
),
),
));
$this->add(array(
'name' => 'submit',
'type' => 'Submit',
'attributes' => array(
'value' => 'Submit',
'id' => 'submitbutton',
'class' => 'btn btn-primary pull-right',
),
));
}
}
This fieldset is called in BookPointlForm's points collection
class BookPointMainFieldset extends Fieldset implements InputFilterProviderInterface
{
public function __construct($name = null)
{
// we want to ignore the name passed
parent::__construct('Fieldset');
$this->add(array(
'type' => 'Zend\Form\Element\Collection',
'name' => 'points',
'attributes' => array(
'class'=> 'point_collection '
),
'options' => array(
'label' => 'Add Book Points',
'count' => 1,
'should_create_template' => true,
'allow_add' => true,
'target_element' => array(
'type' => 'Book\Form\BookPointFieldset',
),
),
));
$this->add(array(
'name' => 'add_nested_point',
'type' => 'Button',
'attributes' => array(
'value' => 'Add nested point',
'class'=> 'add_nested_point'
),
'options' => array(
'label' => 'Add Nested Point',
),
));
$this->add(array(
'type' => 'Zend\Form\Element\Collection',
'name' => 'nested-points',
'attributes' => array(
'class'=> 'nested_point_collection '
),
'options' => array(
'label' => 'Add Book Points',
'count' => 1,
'should_create_template' => true,
'allow_add' => true,
'target_element' => array(
'type' => 'Book\Form\BookPointFieldset',
),
),
));
}
public function exchangeArray($data) {
}
public function getInputFilterSpecification()
{
return array(
'weight' => array(
'required' => true,
),
);
}
}
This is main fieldset it contents heading and heading's content
class BookHeadingFieldset extends Fieldset implements InputFilterProviderInterface
{
public function __construct($name = null)
{
$kraHeadingText = '';
// we want to ignore the name passed
parent::__construct('BookHeadingFieldset');
// $this
// ->setHydrator(new ClassMethodsHydrator(false))
// ->setObject(new KraHeading())
;
$this->add(array(
'name' => 'id',
'type' => 'Hidden',
'attributes' => array(
'value' => ''
)
));
$this->add(array(
'name' => 'manualHeadingText',
'type' => 'Textarea',
'options' => array(
'label' => 'Heading',
'label_options' => [
'disable_html_escape' => true
],
),
'labelOptions' => array(
'disable_html_escape' => true,
),
'attributes' => array(
'class' => 'form-control',
'placeholder'=>"Enter heading",
'COLS'=>"150",
// 'required' => 'true',
),
));
}
public function exchangeArray($data) {
}
public function getInputFilterSpecification()
{
return array();
}
}
...
Hi is there a way to add style to a form element, besides adding a class?
$this->add(array(
'type' => 'Zend\Form\Element\Textarea',
'name' => 'notas',
'options' => array(
'label' => 'Notas',
'label_attributes' => array(
'class' => 'label-wrapped'
),
),
));
thanks!
This is the way, But I still don't know how to add several styles
$this->add(array(
'type' => 'Zend\Form\Element\Textarea',
'name' => 'notas',
'attributes' => array(
'style'=>'width:100px',
),
'options' => array(
'label' => 'Notas',
'label_attributes' => array(
'class' => 'label-wrapped'
),
),
));
I have this class:
<?php
class RegisterFilter extends InputFilter
{
public function __construct()
{
$this->add(array(
'name' => 'email1',
'required' => true,
'validators' => array(
array(
'name' => 'EmailAddress',
'options' => array(
'domain' => true,
),
),
array(
'name' => 'Identical',
'options' => array(
'token' => 'email2',
),
),
array(
'name' => 'Db\NoRecordExists',
'options' => array(
'table' => 'user',
'field' => 'email',
'messages' => array(
'recordFound' => "Email already exist ... ! <br>",
),
),
),
),
));
}
}
?>
I get this error: No database adapter present. Any ideas why this happens?
It would be good if you'd read the documentation about Zend\Validator\Db\Record*. The given error message means exactly what it said. You don't provide a DB-Adapter inside the Validator.
From the DOCs:
$validator = new Zend\Validator\Db\RecordExists(
array(
'table' => 'users',
'field' => 'emailaddress',
'adapter' => $dbAdapter
)
);
If you want to find out how to get the DB-Adapter into your Form, i have written a Blog Article about said topic.
there is a more than strange behavior of filterInput, the getting filter function itself is:
public function getInputFilter($id = null){
if (!$this->inputFilter){
$inputFilter = new InputFilter();
$factory = new InputFactory();
$id = intval($id);
$inputFilter->add($factory->createInput(array(
'name' => 'name',
'required' => true,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'StringLength',
'options' => array(
'encoding' => 'UTF-8',
'min' => 1,
'max' => 100,
),
),
array(
'name' => 'Db\NoRecordExists',
'options' => array(
'field' => 'name',
'table' => 'table',
'adapter' => $this->dbAdapter,
'message' => 'record exists',
'exclude' => array(
'field' => 'id',
'value' => $id
)
),
)
),
)));
$this->inputFilter = $inputFilter;
}
return $this->inputFilter;
}
setting the filter like:
$form->setInputFilter($model->getInputFilter($id));
Now, when we fire $form->isValid(), the validation error will rise about duplication in the database, if I will remove Db\NoRecordExists validator, the database will contain 2 records! more interesting, if I will set 'required' => false, there will be no double inserting, the same with adding second validation field. Working settings are:
public function getInputFilter($id = null){
if (!$this->inputFilter){
$inputFilter = new InputFilter();
$factory = new InputFactory();
$id = intval($id);
$inputFilter->add($factory->createInput(array(
'name' => 'name',
'required' => true,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'StringLength',
'options' => array(
'encoding' => 'UTF-8',
'min' => 1,
'max' => 100,
),
),
array(
'name' => 'Db\NoRecordExists',
'options' => array(
'field' => 'name',
'table' => 'table',
'adapter' => $this->dbAdapter,
'message' => 'record exists',
'exclude' => array(
'field' => 'id',
'value' => $id
)
),
)
),
)));
//test field
$inputFilter->add($factory->createInput(array(
'name' => 'id',
'required' => false,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim'),
array('name' => 'Int')
),
)));
$this->inputFilter = $inputFilter;
}
return $this->inputFilter;
}
So it fails to work correctly with filter config for only one field.. Does anybody knows the reason?
In \Zend\Validator\DateStep, I want to override the error message shown below:
protected $messageTemplates = array(
self::NOT_STEP => "The input is not a valid step"
);
I have an input filter connected to a form containing an element of the type 'Zend\Form\Element\Date' which automatically calls the DateStep validator.
Here is the relevant part of my form:
$this->add(array(
'type' => 'Zend\Form\Element\Date',
'name' => 'appointment-date',
'options' => array(
'label' => 'Appointment Date',
'format' => 'Y-m-d'
),
'attributes' => array(
'min' => date('Y-m-d'), // today's date
'max' => '2020-01-01',
'step' => '2', // days; default step interval is 1 day
)
));
Here is my input filter:
$inputFilter->add($factory->createInput(array(
'name' => 'appointment-date',
'required' => false,
'filters' => array(
array('name' => 'StripTags'),
),
'validators' => array(
array(
'name' => 'DateStep',
'options' => array(
//'step' => new DateInterval("P2D"),
//'baseValue' => new DateTime(),
'messages' => array(
\Zend\Validator\DateStep::NOT_STEP => 'Must be a day in the future',
),
),
),
),
)));
The inputFilter seems to be ignored. I tried setting up the step and baseValue in the inputFilter, but that seems to not work at all. Working app can be found here: https://github.com/bickerstoff/zf2_datetest if more details are needed.
Looks like you're trying to filter a "Date" input with a "DateStep" validator.
$this->add(array(
'type' => 'Zend\Form\Element\Date',
'name' => 'appointment-date',
'options' => array(
'label' => 'Appointment Date',
'format' => 'Y-m-d'
),
'attributes' => array(
'min' => date('Y-m-d'), // today's date
'max' => '2020-01-01',
'step' => '2', // days; default step interval is 1 day
)
));
This may cause your problem.