I tried this this solution, but it seams not to work in Symfony 1.4.
Has something changed? How do I add selected attribute to the form select?
Here is my form class:
// /lib/form/doctrine/CurrencyListForm.class.php
class CurrencyListForm extends BaseCurrencyForm
{
public function configure()
{
$choices = '';
$choice = Doctrine::getTable('currency')
->createQuery('a')
->execute();
foreach($choice as $v)
$choices[$v->getCurrencyCode()] = $v->getCurrencyCode();
$this->setWidgets(array(
'currency_code' => new sfWidgetFormSelect(array('choices' => $choices)),
));
}
}
And this is how I instantiate it:
$this->form = new CurrencyListForm();
What kind of form are you rendering? If it's an object form (like sfFormDoctrine), the binding 'reverts' the defaults. (It sets the defaults of the model).
What I found was the simplest way to bind it, is creating a dummy object and set the property on that object. Then pass this object to the constructor of the form.
Something like this:
$defaultCurrency = new Currency();
$defaultCurrency->currency_code = 'EUR';
$this->form = new CurrencyListForm($defaultCurrency);
Related
I'm working with project where tables are created all the time depending on user adding new properties, so for my model i have below
class Hotel extends Model
{
public function __construct($hotel)
{
$this->table = $hotel;
}
protected $fillable = ['date', 'sold', 'sold_diff', 'rev', 'rev_diff', 'row', 'date_col', 'sold_col', 'rev_col'];
}
and i can use the table in controller by doing
$hotel_table = new Hotel($table);
but i like to use Model::updateOrCreate() when I'm adding or updating rows in table, and I'm not sure how to do that.
This is the signature for the updateOrCreate function
"static Model updateOrCreate( array $attributes, array $values = array())"
For you to update or create, you can pass the condition that must be met to update the table to the first argument and the values to be updated to the second.
for example.
$primaryKey = isset($request->input('id')) ? $request->input('id') : null;
$myModel = Model::updateOrCreate(['id' => $primaryKey], $request->all());
so with this if id is in the request object the table will be updated but if not a new record will be created.
In Laravel 5.2 you can use simply like this
class Hotel extends Model
{
protect $table = 'hotels'
protected $fillable = ['date', 'sold', 'sold_diff', 'rev', 'rev_diff', 'row', 'date_col', 'sold_col', 'rev_col'];
// protected $guarded = []; you can use this instead of `$fillable` this is for all columns fillable
}
now in your controller you can use
Model::update();
Model::create();
I want to create multi-level embed form in symfony 1.4.
I have three forms:
1 - Question form,
2 - Option form and
3 - answer form.
In that, one question have many options fields and one option have many answers fields.
When I tried to add one more field in option criteria by rendering the HTML for answer fields using ajax and try to save form that time I am getting error Unexpected extra form field named "1"
And I have embedded Option form in Question form and Answer form in Option form respectively.
The below error is produce after submit form :
pick_type_option [0 [pick_type_answers [Unexpected extra form field named "1".]]]
Can any one please help me to find out the solution for this problem.
In advanced thanks
As it's unknown how many Option forms will be there during construction of the form (inside configure(), you have to override bind() method and add as many as needed:
class QuestionForm extends sfForm {
public function configure() {
$this->embedFormArray('question', new OptionForm);
}
private $formArray = array();
public function embedFormArray($name, \sfForm $form, $decorator = null, $innerDecorator = null, $options = array(), $attributes = array(), $labels = array()) {
$this->formArray[] = array($name, $form, $decorator, $innerDecorator, $options, $attributes, $labels);
}
public function bind(array $taintedValues = null, array $taintedFiles = null) {
foreach($this->formArray as $fa) {
$c = (isset($taintedValues[$fa[0]]) ? count($taintedValues[$fa[0]]) : 0);
array_splice($fa, 2, 0, [$c]);
call_user_func_array(array($this, 'embedFormForEach'), $fa);
}
return parent::bind($taintedValues, $taintedFiles);
}
}
i new to zenframework 2. i have correctly set up zendframework 2,doctrine and zfcUser.All work correctly.
my issue now is now regarding how to prepoulated a form if a member is already logged in.
this is where i extend zfcUser to obtain the Id of a loggged in member:
public function setid( $id)
{
$this->id = $id;
}
public function getId()
{
if (!$this->id) {
$this->setid($this->zfcUserAuthentication()->getAuthService()->getIdentity()->getId());
}
return $this->id;
}
i know want to use that Id to obtain the values from the database and then populate the form with those values.
this is my form:
public function aboutYouAction()
{
$id = $this->getId() ;
$form = new CreateAboutYouForm($this->getEntityManager());
$aboutYou = new AboutYou();
$form->setInputFilter($aboutYou->getInputFilter());
$form->bind($aboutYou);
if ($this->request->isPost())
{
$form->setData($this->request->getPost());
if ($form->isValid())
{
$post = $this->request->getPost();
$this->getEntityManager()->persist($aboutYou);
$this->getEntityManager()->flush();
return $this->redirect()->toRoute('worker', array('action' => 'aboutYou'));
}
}
$messages='';
// return array('form' => $form);
return new ViewModel(array('form' => $form, 'messages' => $messages));
}
To set the values on the form all you need to do is $form->bind($aboutYou)
The bind() method is designed to take the passed entity instance and map it to the forms elements; This process being referred to as form hydration.
Depending on the hydrator attached to the form or fieldset (With doctrine this would normally be the DoctrineModule\Stdlib\Hydrator\DoctrineObject) this should be able to evaluate the AboutYou fields, including any entity references/associations, and set the corresponding form elements values. I'm assuming that one of these fields is user.
In you specific case it seems you are binding a new entity (which therefore will not have any properties set, such as your user)
$aboutYou = new AboutYou(); // Brand new entity
$form->bind($aboutYou); // Binding to the form without any data
What this means is that the form is trying to set the values of the elements but the provided AboutYou class has no data to set (as its new and was not loaded via doctrine) and/or the properties of the AboutYou class to not correctly map to the form's elements.
If you wish to bind the user you will need to fetch the populated instance. This can be done using doctrine ($objectManager->find('AboutYou', $aboutYouId)) or if you need to set the current logged in user call the controller plugin ZfcUser\Controller\Plugin\ZfcUserAuthentication from within the controller and no where else.
You workflow should be similar to this (illustration purposes only)
// Controller
public function aboutYouAction()
{
// Get the id via posted/query/route params
$aboutYouId = $this->params('id', false);
// get the object manager
$objectManager = $this->getServiceLocator()->get('ObjectManager');
// Fetch the populated instance
$aboutYou = $objectManager->find('AboutYou', $aboutYouId);
// here the about you entity should be populated with a user object
// so that if you were to call $aboutYou->getUser() it would return an user object
// Get the form from the service manager (rather than creating it in the controller)
// meaning you should create a factory service for this
$form = $this->getServiceLocator()->get('MyForm');
// Bind the populated object to the form
$form->bind($aboutYou);
//... rest of the action such as handle edits etc
}
I'm trying to create a form that change the validation of a field based on the select option from the html form field.
Ex: if user select a option 1 from drop down field "options", I want the field "metric" to validate as sfValidatorInteger. If user select option 2 from field "options", I want the field "metric" to validate as sfValidatorEmail, etc.
So inside the public function configure() { I have the switch statement to capture the value of "options", and create the validator based on that value returned from the "options".
1.) How do I capture the value of "options" ? I've tried:
$this->getObject()->options
$this->getTaintedValues()
The only thing that's currently working for me is but it's not really MVC:
$params = sfcontext::getInstance()->getRequest()->getParameter('options');
2.) Once I've captured that information, how can I assign the value of "metric" to a different field? ("metric" is not a real column in db). So I need to assign the value of "metric" to different field such as "email", "age" ... Currently I'm handling this at the post validator like this, just wondering if I can assign value within the configure():
$this->validatorSchema->setPostValidator(new sfValidatorCallback(array('callback' => array($this, 'checkMetric'))));
public function checkMetric($validator, $values) {
}
Thanks!
You want to use a post validator. Try doing something like this in your form:
public function configure()
{
$choices = array('email', 'integer');
$this->setWidget('option', new sfWidgetFormChoice(array('choices' => $choices))); //option determines how field "dynamic_validation" is validated
$this->setValidator('option', new sfValidatorChoice(array('choices' => array_keys($choices)));
$this->setValidator('dynamic_validation', new sfValidatorPass()); //we're doing validation in the post validator
$this->mergePostValidator(new sfValidatorCallback(array(
'callback' => array($this, 'postValidatorCallback')
)));
}
public function postValidatorCallback($validator, $values, $arguments)
{
if ($values['option'] == 'email')
{
$validator = new sfValidatorEmail();
}
else //we know it's one of email or integer at this point because it was already validated
{
$validator = new sfValidatorInteger();
}
$values['dynamic_validation'] = $validator->clean($values['dynamic_validation']); //clean will throw exception if not valid
return $values;
}
1) In a post validator, values can be accessed by using the $values parameter. Just use $values['options'] and it should be fine... or did you want to access this values from another part of you code? $this->getObject()->widgetSchema['options'] should work too I think, once your form is bound to an object.
2) The configure() method is called at the end of the form constructor, so values are not bound nor accessible yet, unless you are initializing your form with an object from the db (which does not require any validation). But if you want to initialize your form from $_POST, a post validator is definitely the way to go IMHO.
I got the validation error to appear alongside the field by throwing a sfValidatorErrorSchema instead of a sfValidatorError.
$values['dynamic_validation'] = $validator->clean($values['dynamic_validation']);
…becomes…
try
{
$values['dynamic_validation'] = $validator->clean($values['dynamic_validation']);
}
catch(sfValidatorError $e)
{
$this->getErrorSchema()->addError($e, 'dynamic_validation');
throw $this->getErrorSchema();
}
Not sure if this is the best way to get this result, but it seems to be working for me at the moment.
I have a action class for saving some data to a database.In action class iam getting a id through url.I have to save the id in table.
I am getting the id by $request->getParameter('id')
I used this code for saving
$this->form->bind($request->getParameter('question_answers'));
if ($this->form->isValid())
{
$this->form->save();
$this->redirect('#homepage');
}
in model class i used a override save method to save extra field
public function save(Doctrine_Connection $conn = null)
{
if ($this->isNew())
{
$now=date('Y-m-d H:i:s', time());
$this->setPostedAt($now);
}
return parent::save($conn);
so i want to get the id value here .
So how can i pass id value from action class to model class
is any-other way to save the id in action class itself
Thanks in advance
Just use
$this->form->getObject()->setQuestionId($request->getParameter('id'));
$this->form->save();
QuestionId=field name
$request->getParameter('id')= is the default value
Most probably not the best solution but you can save that id value in a session variable and use it later anywhere you need. something like:
$this->getUser()->setAttribute('id', $request->getParameter('id')); // in action class
and
sfContext::getInstance()->getUser()->getAttribute('id'); // in model class
If your model has a field for this ID already (eg in your example posted_id), then you can do one of 2 things:
1: Pass the ID to your form when you create it, as an option:
$this->form = new MyForm(array(), array("posted_id" => $id));
and then you can override your form's doSave() method to set the field:
// ...
$this->getObject()->posted_id = $this->getOption("posted_id");
// ...
or similar
2: Add a widget to your form in the configure() method with a corresponding validator, and pass in the ID when you get the values from the request:
$values = $request->getParameter('question_answers');
$values["posted_id"] = $request->getParameter("id");
$this->form->bind($values);
If you're rendering your form manually, just don't render this new field in your view template.
Either way, saving the model as a result of the form saving it will include this new field I believe. The second one is from memory, but it should technically work... :-)
Best practice I'm using consists of 2 steps:
Pass additional data to forms' options (2nd constructor's parameter or just $form->setOption('name', 'value'));
override protected method doUpdateObject in way like this:
protected function doUpdateObject($values)
{
$this->getObject()->setFoo($this->getOption('foo'));
parent::doUpdateObject($values);
}
Enjoy!
You could use (sfUser)->setFlash and (sfUser)->getFlash instead of setAttribute, it's more secure...