I been trying all day to do multiple insert for the same form based on a number and i couldn't go any where with it. I hope someone here would be help me out...
am using admin generator on 1.4 doctrine. I have a form which i generated with only two fields. what am trying to do is, based on a number inserted the form will be repeated x number of times.
In the generator file I added a partial which placed a text field in the beginning of the form with default value of 1. If I choose 2 the form below gets duplicated twice..
Here is what i did to my form.. In action
class prizesActions extends autoPrizesActions
{
public function executeNew(sfWebRequest $request)
{
$this->form = $this->configuration->getForm(null, array('n' => 5));
$this->prizes = $this->form->getObject();
}
}
and in the PrizesForm, I wrote the following
class PrizesForm extends BasePrizesForm
{
public function configure()
{
$array = $this->getOptions();
for ($i = 0; $i < $array['n']; $i++) {
$this->setWidgets(array(
'id' => new sfWidgetFormInputHidden(),
'prize_no' => new sfWidgetFormInputText(),
'prize' => new sfWidgetFormInputText(),
'created_at' => new sfWidgetFormDateTime(),
'updated_at' => new sfWidgetFormDateTime(),
));
$this->setValidators(array(
'id' => new sfValidatorDoctrineChoice(array('model' => $this->getModelName(), 'column' => 'id', 'required' => false)),
'prize_no' => new sfValidatorInteger(array('required' => false)),
'prize' => new sfValidatorString(array('max_length' => 200, 'required' => false)),
'created_at' => new sfValidatorDateTime(),
'updated_at' => new sfValidatorDateTime(),
));
$this->widgetSchema->setNameFormat('prizes['.$i.'][%s]');
$this->errorSchema = new sfValidatorErrorSchema($this->validatorSchema);
}
unset( $this['updated_at'],
$this['created_at']
);
}
}
I think the loop is working but its over writing the widgets at every entry and i cannot find other method to append instead. Any ideas?
Thanks,
Did you try embedForm()? Code below should give you an idea.
class PrizesForm extends BasePrizesForm
{
public function configure()
{
$this->setWidgets(array(
'id' => new sfWidgetFormInputHidden(),
'prize_no' => new sfWidgetFormInputText(),
'prize' => new sfWidgetFormInputText(),
'created_at' => new sfWidgetFormDateTime(),
'updated_at' => new sfWidgetFormDateTime(),
));
$this->setValidators(array(
'id' => new sfValidatorDoctrineChoice(array('model' => $this->getModelName(), 'column' => 'id', 'required' => false)),
'prize_no' => new sfValidatorInteger(array('required' => false)),
'prize' => new sfValidatorString(array('max_length' => 200, 'required' => false)),
'created_at' => new sfValidatorDateTime(),
'updated_at' => new sfValidatorDateTime(),
));
$this->widgetSchema->setNameFormat('prizes[%s]');
}
}
class PrizesGroupForm extends sfForm
{
public function configure()
{
$array = $this->getOptions();
for ($i = 0; $i < $array['n']; $i++)
{
$this->embedForm('prizes_' . $i, new PrizesForm());
}
$this->widgetSchema->setNameFormat('prizes_group[%s]');
}
}
Related
Please help me with Zend framework 2:)
I want to create a form with collection of fieldsets using Form Element Manager (absolutely like in official documentation).
My FormElementManager configuration:
'form_elements' => array(
'factories' => array(
'Admin\Form\TaskForm' => function($sm) {
$form = new TaskForm();
$doctrimeEntityManager = $sm->getServiceLocator()->get('Doctrine\ORM\EntityManager');
$form -> setEntityManager($doctrimeEntityManager);
$form -> init();
return $form;
},
'Admin\Form\TaskbrandFieldset' => function($sm) {
$doctrimeEntityManager = $sm->get('Doctrine\ORM\EntityManager');
$form = new TaskbrandFieldset();
$form->setEntityManager($doctrimeEntityManager);
return $form;
},
)
),
Admin\Form\TaskForm (only problem part):
namespace Admin\Form;
use Doctrine\ORM\EntityManager;
use Zend\Form\Form;
class TaskForm extends Form {
protected $entityManager;
public function init() {
$this->setAttribute('method', 'post');
// Id
$this->add(array(
'name' => 'id',
'attributes' => array(
'type' => 'hidden',
),
));
// My fieldset
$this->add(array(
'type' => 'Zend\Form\Element\Collection',
'name' => 'taskbrands',
'options' => array(
'label' => 'Brand of the product',
'count' => 0,
'should_create_template' => true,
'allow_add' => true,
'target_element' => array(
'type'=>'Admin\Form\TaskbrandFieldset'
),
),
'attributes' => array(
'id' => 'addressFieldset'
)
));
}
}
Admin\Form\TaskbrandFieldset:
namespace Admin\Form;
use Admin\Entity\Taskbrand;
use Zend\Form\Fieldset;
use Zend\InputFilter\InputFilterProviderInterface;
use Zend\Stdlib\Hydrator\ClassMethods as ClassMethodsHydrator;
use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
class TaskbrandFieldset extends Fieldset implements InputFilterProviderInterface, ServiceLocatorAwareInterface {
protected $entityManager;
protected $serviceLocator;
public function init() {
$this->setName('TaskbrandFieldset');
$this->setHydrator(new ClassMethodsHydrator(false))
->setObject(new Taskbrand());
$this->setLabel('Taskbrand');
$this->add(array(
'type' => 'DoctrineModule\Form\Element\ObjectSelect',
'name' => 'brand',
'options' => array(
'object_manager' => $this->getEntityManager(),
'target_class' => 'Module\Entity\Brand',
'property' => 'name',
),
));
}
}
And, finally, my controller:
$Task = $this->getServiceLocator()->get('Admin\Model\Task')->findByPk($id);
$formManager = $this->getServiceLocator()->get('FormElementManager');
$form = $formManager->create('Admin\Form\TaskForm');
$form->bind($Task);
The problem is that form Admin\Form\TaskForm instantiates in factory described in form_elements configuration section, but Admin\Form\TaskbrandFieldset does not. It just invokes.
Trying to understand this problem I found that Admin\Form\TaskForm and Admin\Form\TaskbrandFieldset instantiates with different instances of FormElementManager, first one have my config inside (including factories description), but second has nothing.
Please help me :)
The problem is in your controller. Use
$form = $formManager->get('Admin\Form\TaskForm');
instead of
$form = $formManager->create('Admin\Form\TaskForm');
Remember that you don't have to use $form->init(). It's automatically called, same like in zf1. There is a good tutorial on zf2 site
What I am actually doing is, fetching a list of companies from the database and passing that to the form SELECT element.
So I created a Model file, which returns an array
//=== return an array of $ID => $name of companies to use in dropdown in reports form
public function getTotalResult($table, $type, $id) {
$this->table = $table;
$select = new Select();
$spec = new Where();
$spec->equalTo('status', 1);
if ($type == 'name') {
$spec->equalTo('id', $id);
}
$select->from($this->table);
$select->where($spec);
$resultSet = $this->selectWith($select);
//$resultSet->buffer();
return $resultSet;
}
public function resultList($table){
$results = $this->getTotalResult($table, '', '');
foreach ($results as $result) {
$this->id[] = $result->id;
$this->name[] = $result->name;
}
$result = array_combine($this->id, $this->name);
return $result;
}
Then I tested this in my Controller, which returned exactly what I wanted:
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use SpangelLogin\Model\Register; // <-- Add this import
use SpangelLogin\Model\companyList; // <-- Add this import
class RegisterController extends AbstractActionController
{
protected $registerTable;
protected $companyList;
public function getcompanyList()
{
if (!$this->companyList) {
$sm = $this->getServiceLocator();
$this->companyList = $sm->get('SpangelLogin\Model\companyList');
}
return $this->companyList;
}
public function indexAction()
{
//== get list of companies
$company_table = 'rs_company';
$sector_table = 'rs_sector';
$companiesList = $this->getcompanyList()->getName($company_table, 2);
}
}
So now I want this companiesList array passed in my form's Select Element. How can I achieve that. Here is my form in which I am using select.
use Zend\Form\Form;
use Zend\Form\Element;
class SectorReportForm extends Form
{
public function __construct($name = null)
{
// we want to ignore the name passed
parent::__construct('sectorreport');
$companiesArray = $this->companiesList();
$sectorsArray = $this->sectorsList();
$this->setAttribute('method', 'post');
$this->setAttribute('enctype','multipart/form-data');
$this->add(array(
'type' => 'Zend\Form\Element\Select',
'name' => 'company',
'attributes' => array(
'id' => 'company',
'multiple' => true,
'options' => $companiesArray,
),
'options' => array(
'label' => 'Company',
),
));
$this->add(array(
'name' => 'submit',
'attributes' => array(
'type' => 'submit',
'value' => 'Upload',
'id' => 'submitbutton',
'class' => 'button violet right'
),
));
}
}
From a Design-Perspective, the best approach would be to handle this via Dependency-Injection. That sneaky little buzzword that confuses people so much, but actually is nothing more but to forward data between objects :P
General Dependency-Injection for Forms can be seen looking at the following answer, as well as my Blog article
How to get data from different model for select?
Zend\Form\Element\Select and Database-Values
If you do not want to go this approach, you can handle this at the Controller level, too.
$form = new My\Form();
$select = $form->get('selectCountries');
$model = new My\Countries();
$listData = $model->getCountriesAsArray();
$select->setValueOptions($listData);
I still advise you to go the different approach ;) Keeps the controllers more clean, too, which is always a good thing. Separation of concern!
I have form with some attributes:
class ToraForm extends Form
{
public function __construct($name = null)
{
parent::__construct('tora');
$this->setAttribute('method', 'post');
$this->add(array(
'name' => 'id',
'attributes' => array(
'type' => 'hidden',
),
));
$this->add(array(
'name' => 'name',
'attributes' => array(
'type' => 'text',
'required' => true,
),
'options' => array(
'label' => 'name',
),
));
}
but I want add drop-down list with data taken from another model. How to do it?
There are several different approaches you can take. Ultimately your Form has a dependency, which needs to be injected. I have written an in-depth blog-post about the three most common use-cases for Form-Dependencies for a Select-List.
Zend\Form\Element\Select and Database-Values
My BlogPost covers the following scenarios:
Zend\Form\Element\Select via DbAdapter
Zend\Form\Element\Select via TableGateway
DoctrineModule\Form\Element\DoctrineObject via Doctrine2
Here i will demonstrate only the DbAdapter approach without much explanation. Please refer to my blogpost for the in-depth explanations.
public function formDbAdapterAction()
{
$vm = new ViewModel();
$vm->setTemplate('form-dependencies/form/form-db-adapter.phtml');
$dbAdapter = $this->getServiceLocator()->get('Zend\Db\Adapter\Adapter');
$form = new DbAdapterForm($dbAdapter);
return $vm->setVariables(array(
'form' => $form
));
}
Then the respective Form Class:
class DbAdapterForm extends Form
{
protected $dbAdapter;
public function __construct(AdapterInterface $dbAdapter)
{
$this->setDbAdapter($dbAdapter);
parent::__construct('db-adapter-form');
$this->add(array(
'name' => 'db-select',
'type' => 'Zend\Form\Element\Select',
'options' => array(
'label' => 'Dynamic DbAdapter Select',
'value_options' => $this->getOptionsForSelect(),
'empty_option' => '--- please choose ---'
)
));
}
// more later...
// Also: create SETTER and GETTER for $dbAdapter!
}
And last but not least the DataProvider function:
public function getOptionsForSelect()
{
$dbAdapter = $this->getDbAdapter();
$sql = 'SELECT t0.id, t0.title FROM selectoptions t0 ORDER BY t0.title ASC';
$statement = $dbAdapter->query($sql);
$result = $statement->execute();
$selectData = array();
foreach ($result as $res) {
$selectData[$res['id']] = $res['title'];
}
return $selectData;
}
My use is like that:
Class Useful{
/**
* All languages
* #return array
*/
public static function getLanguages(){
return array(
'fr_DZ'=>'Algeria - Français',
'es_AR'=>'Argentina - Español',
'en_AU'=>'Australia - English',
'nl_BE'=>'België - Nederlands',
'fr_BE'=>'Belgique - Français',
'es_BO'=>'Bolivia - Español',
'bs_BA'=>'Bosna i Hercegovina - Hrvatski',
...
);
}
}
After I use like that:
$this->add(array(
'type' => 'Zend\Form\Element\Select',
'name' => 'languages',
'attributes'=>array(
'multiple'=>"multiple",
),
'options' => array(
'label' => 'My languages I speak',
'description' => '',
'value_options' => Useful::getLanguages()
),
));
I want to put a dropdown in my project which is made in zf2... I wasted all day but I only got a static dropdown, not dynamic. Can anyone help me with this problem??
UserForm.php
$this->add(array(
'name' => 'group_name',
'type' => 'select',
'attributes' => array(
'id'=>'group_name',
'class'=>'large',
'options' => array('1=>php','2'=>'java'),
),
'options' => array(
'label' => '',
),
));
Thanks in advance for your valuabe answer.
Try this:
$this->add(array(
'name' => 'group_name',
'type' => 'select',
'attributes' => array(
'id'=>'group_name',
'class'=>'large',
),
'options' => array(
'label' => '',
'value_options' => array(
'1' => 'php',
'2' => 'java'
),
),
));
This is what i did:
In my constructor for my form
$this->add(array(
'type' => 'Zend\Form\Element\Select',
'name' => 'color',
'options' => array(
'empty_option' => 'Select a Color',
'value_options' => self::getColors(),
'label' => 'Color',
),
));
In the form class yet, i created this method:
public static function getColors() {
// access database here
//example return
return array(
'blue' => 'Blue',
'red' => 'Red',
);
}
In my view script:
<div class="form_element">
<?php $element = $form->get('color'); ?>
<label>
<?php echo $element->getOption('label'); ?>
</label>
<?php echo $this->formSelect($element); ?>
</div>
Think about it from a abstract level.
You have one Form
The Form needs Data from the outside
So ultimately your Form has a Dependency. Since we've learned from the official docs, there's two types of Dependency-Injection aka DI. Setter-Injection and Constructor-Injection. Personally(!) i use one or the other in those cases:
Constructor-Injection if the dependency is an absolute requirement for the functionality to work
Setter-Injection if the dependencies are more or less optional to extend already working stuff
In the case of your Form, it is a required dependency (because without it there is no populated Select-Element) hence i'll be giving you an example for Constructor-Injection.
Some action of your controller:
$sl = $this->getServiceLocator();
$dbA = $sl->get('Zend\Db\Adapter\Adapter');
$form = new SomeForm($dbA);
That's all for the form. The population now happens inside your Form. This is only an example and may need some fine-tuning, but you'll get the idea:
class SomeForm extends \Zend\Form
{
public function __construct(\Zend\Db\Adapter\Adapter $dbA)
{
parent::__construct('my-form-name');
// Create all the form elements and stuff
// Get Population data
$popData = array();
$result = $dbA->query('SELECT id, title FROM Categories', $dbA::QUERY_MODE_EXECUTE)->toArray();
foreach ($result as $cat) {
$popData[$cat['id'] = $cat['title'];
}
$selectElement = $this->getElement('select-element-name');
$selectElement->setValueOptions($popData);
}
}
Important: I HAVE NO CLUE ABOUT Zend\Db the above code is only for how i think it would work going by the docs! This is the part that would need some optimization probably. But all in all you'll get the idea of how it's done.
In your controller you can do something like below;
On my first example assuming that you have a Group Table. Then we're going to fetchAll the data in group table;
We need the id and name to be display in select options;
public function indexAction()
{
$groupTable = new GroupTable();
$groupList = $groupTable->fetchAll();
$groups = array();
foreach ($groupList as $list) {
$groups[$list->getId()] = $list->getName();
}
$form = new UserForm();
$form->get('group_name')->setAttributes(array(
'options' => $groups,
));
}
OR
in this example the grouplist is hardcoded;
public function indexAction()
{
$groupList = array('1' => 'PHP', '2' => 'JAVA', '3' => 'C#');
$groups = array();
foreach ($groupList as $id => $list) {
$groups[$id] = $list;
}
$form = new UserForm();
$form->get('group_name')->setAttributes(array(
'options' => $groups,
));
}
Then in your view script;
<?php
$form = $this->form;
echo $this->formRow($form->get('group_name'));
?>
Or you can right a controller helper, you may check this link http://www.resourcemode.com/me/?p=327
Just came across the same problem and had to take a look into zf2 source.
Here's a more OOP solution:
Inside the form constructor:
$this->add(array(
'name' => 'customer',
'type' => 'Zend\Form\Element\Select',
'attributes' => array(
'options' => array(
0 => 'Kunde',
)
),
'options' => array(
'label' => 'Kunde'
)));
inside the controller:
$view->form = new SearchForm();
$customers = $view->form->get('customer')->getValueOptions();
$customers[] = 'Kunde1';
$customers[] = 'Kunde2';
$customers[] = 'Kunde3';
$customers[] = 'Kunde4';
$view->form->get('customer')->setValueOptions($customers);
I'm building a simple form mailer in symfony using sfExtraForm plugin captcha. Everything works except sfValidator is not redirecting the user and showing an error when any field is invalid. The only thing I can think of is I did not generate the module. I built it from scratch.
I have to do the redirect manually. Is this because this is a sfForm and not an sfDoctrine Form? It is if the line if ($form->isValid()) returns false but without the associated redirect and error codes. Here is the program. Thanks:
Form:
<?php
class AdsForm extends sfForm
{
public function configure()
{
$this->setWidgets(array(
'name' => new sfWidgetFormInputText(),
'email' => new sfWidgetFormInputText(),
'phone' => new sfWidgetFormInputText(),
'fax' => new sfWidgetFormInputText(),
'attention' => new sfWidgetFormInputText(),
'message' => new sfWidgetFormInputText(),
'captcha' => new sfWidgetFormReCaptcha( array('public_key'=>self::PUBLIC_KEY)),
));
$this->widgetSchema->setNameFormat('ads[%s]');
$this->setValidators(array(
'name' => new sfValidatorString(array('max_length' => 50)),
'email' => new sfValidatorString(array('max_length' => 50)),
'phone' => new sfValidatorString(array('max_length' => 50)),
'fax' => new sfValidatorString(array('max_length' => 50)),
'attention' => new sfValidatorString(array('max_length' => 50)),
'message' => new sfValidatorString(array('max_length' => 255)),
'captcha' => new sfValidatorReCaptcha(array('private_key' => self::PRIVATE_KEY))
));
$this->widgetSchema->setLabels(array(
'name' => 'Your Name:*',
'email' => 'Your Email:*',
'phone' => 'Your Phone:*',
'fax' => 'Your Fax',
'attention' => 'Attention:*',
'message' => 'Mail Message:*',
'captcha' => 'Image Verification:*',
));
}
}
Action:
class adsActions extends sfActions
{
public function executeIndex(sfWebRequest $request)
{
$this->form=new adsForm();
}
public function executeSend(sfWebRequest $request){
$this->forward404Unless($request->isMethod(sfRequest::POST));
$form=new adsForm();
$captcha = array('recaptcha_challenge_field' => $request->getParameter('recaptcha_challenge_field'),'recaptcha_response_field' => $request->getParameter('recaptcha_response_field'),);
$form->bind(array_merge($request->getParameter('ads'), array('captcha' => $captcha)));
if ($form->isValid())
{
print_r($_REQUEST);
$ads=$this->getRequestParameter('ads');
print_r($ads);
$headers = 'From: '."\r\n" .
'Reply-To: no-reply#yellowexplorer.com' . "\r\n" .
'X-Mailer: PHP/' . phpversion();
//mail(' ******#yahoo.com','Yellow Explorer','An account has been created for you at yellowexplorer.com with a username of '.$this->username.'. Please click here to finish creating your account.',$headers);
}
else{
$this->redirect('/ads');
}
}
}
You're not seeing any errors because you're redirecting! To render form fields with their errors, you need to be rendering the actual form instance that you called bind on. Try changing $this->redirect('/ads') to $this->setTemplate('index').
Other potential changes (outside the scope of the question):
You can enforce the request method requirements of the send action at the routing level. Make the send route an sfRequestRoute and add the requirement { sf_method: post }.
Symfony has a built in mailer, sfMailer. Any reason you've decided not to use it?