I have a form using the multiform module. I have a checkboxsetfield populated by a dataobject.
When saving the form I am getting strange results. For instance if I select the first and third checkboxes then this is how the array appears in the database: 1{comma}3 when I expected to see 1,3
MyDataObject.php
<?php
...
if($SomeData = DataObject::get('SomeData')->sort('SortColumn'){
$fields->push( new CheckboxSetField('SomeData', 'Field Name', $SomeData->map('ID', 'Name')
));
}
MultiForm.php
<?php
...
public function finish($data, $form){
if(isset($_SESSION['FormInfo']['MultiForm']['errors'])){
unset($_SESSION['FormInfo']['Form']['errors']);
}
parent::finish($data, $form);
$steps = DataObject::get('MultiFormStep', "SessionID = {$this->session->ID}");
$MyStep = $this->getSavedStepByClass('MyStep');
if($this->getSavedStepByClass('MyStep')){
if($MyStep->loadData()){
$MyDataObject = new MyDataObject();
$MyStep->saveInto($MyDataObject);
$MyDataObject->write();
}
}
...
Any ideas how to process the array?
CheckboxSetField does have code which refers to {comma} when saving to the DB or when calling the dataValue function. This is essentially escaping any commas that were defined as values in the string when saving to a single column.
This tells me that either your multiform isn't providing the right input to CheckboxSetField or that there is more to this situation than your code is showing.
If CheckboxSetField gets an array like array('1,3'), that is when I would expect to see that type of result. Calling map like you have returns an SS_Map object which may not automatically convert the way you are expecting. Try adding ->toArray() after the map call when you are passing the values into the CheckboxSetField.
If that doesn't solve the issue, we probably will need to see the DataObject itself and a few other bits and pieces of information.
Related
I am submitting a form and in my controller I use handleRequest to validate the form.
Lets say I try to update my object name 'object' - It has an id, name and color field.
On the same page I also show a lost with the names of all my objects that I fetch from the database
Here is my code:
$object = self::getObjectById($objectId);
$objects = self::getAllObjects();
$objectForm = self::CreateObjectForm($object);
$objectFormForm->handleRequest($request);
dd($objects);
When I submit the form and I leave the name field open,
It throws an error that the field is required when it reloads the page, the name field of the form is still empty which is normal.
But here is the problem, in the list of objects that is also showing on this page the name of the object I tried to update has no name showing anymore in this list.
I don't know why this is happening since I fetched this list of objects completely separately from the form object. When I dd() the objects after the handleRequest() I cans see in the dumped vars that indeed the name field is empty. When I check the database, the name field is not empty and still holds the old name. Which makes sense because the object is not persisted and flushed to de db.
When I dd() the same list before the handleRequest() everything is normal.
How can I prevent this behavior? And why is this happening?
I don't know why this is happening since i fetched this list of objects completely seperatly from the form object.
It's referencing the same entity which get's dumped in it's current, live, dirty state as submitted by the form.
If you need to render the clean, persisted values then you just need to store them in a variable as a string instead of as the object, and before handling the request.
Try something like this:
$object = self::getObjectById($objectId);
$objects = self::getAllObjects();
$persistedObjects = [];
foreach($objects as $obj){
$persistedObjects[$obj->getId()] = $obj->getName();
}
$objectForm = self::CreateObjectForm($object);
$objectFormForm->handleRequest($request);
dd($persistedObjects);
So, I have the following code:
$homepage = Homepage::first();
if (!$homepage) {
$homepage = new Homepage;
}
$homepage->first_presta_title = $request->first_presta_title;
$homepage->first_presta_content = $request->first_presta_content;
$homepage->second_presta_title = $request->second_presta_title;
$homepage->second_presta_content = $request->second_presta_content;
$homepage->third_presta_title = $request->third_presta_title;
$homepage->third_presta_content = $request->third_presta_content;
$homepage->shiatsu_text = $request->shiatsu_text;
$homepage->shiatsu_image = $request->shiatsu_image;
$homepage->doin_text = $request->doin_text;
$homepage->doin_image = $request->doin_image;
$homepage->save();
Everything works, but I wanted to see if there weren't any better way to save datas without asigning every single element to its column, then I found out someone answering to a question by using the following code:
$homepage->save($request->all());
So I tried it by myself, but nothing happened: no error, but also nothing saved in my database.
So, is there any fastest way to save datas ? Is it possible to use a loop to save everything?
Thank you in advance
When you use save(), you are actually using Mass assignment. So, either you explicitly define all the fields in your model to be mass assignable or you could use create() instead.
However, in your particular case, the whole method could be cleaned up to just one line:
return Homepage::updateOrCreate($request->all());
If you want the model to autofill based on a given array you need to create a new model entity Like this
$homepage = HomePage::create($request->all());
$homepage->save()
If you give an array to save() it expects the options for saving not for values to assign
Source:
laravel api docs for model/save()
laravel api docs for model::create()
I'm using a form which contains wrapped elements. The wrapping happens in the view like described here.
My action looks like this:
$myForm = [definition here]
$myForm->setName('entity');
$myForm->setWrapElements(true);
$request = $this->getRequest();
if ($request->isPost()) {
$myEntity = new Entity();
$myForm->bind($myEntity);
$myForm->setData($request->getPost()->get('entity'));
The problem: When calling $myForm->isValid() it's invalid. When calling $myForm->getData() afterwards it's empty.
I repeated the setName and setWrapElements in the action but with or without it, it doesn't work.
Any ideas what I might be doing wrong? The form definition is untouched and works for non-wrapped forms. So I guess the error is not in there.
P.S.: An echo of $myForm->isValid() returns an empty string. Is there maybe a way to get the error message? The form fields are filled with the data I've put in there and don't show any errors.
Using the following:
$form->getMessages()
Will give you the validation messages.
You can dump the contents or loop the messages in a foreach loop. For example:
foreach($form->getMessages() as $msgId => $msg) {
echo "Validation error: $msgId => $msg"
}
can you try to add line to your code, as I can see in zend's Form.php, element names aren't wrapped with 'entity' till the moment you call prepare();
$myForm->setName('entity');
$myForm->setWrapElements(true);
$myForm->prepare(); // << add this
But I don't believe that it will help, becuase behaviour you describe looks little different. Cau you show us more source code of Entity and var_dumps of things that Aydin and Sina wanted.
In ZF2 data is not binded if the form is not valid. The reason because you see an empty string in the return of isValid is that the return type is a boolean, use var_dump instead.
I am having problem displaying values set by select elements created by FormHelper. I have searched the internet but doesn't seem to be able to find the answer. Here is the scene:
I have a questionnaire form that has many options. In the model I put those items into an array, say ($frequencyOptions) and when formhelper is used,
$this->Form->input('frequency',array("options"=> $frequencyOptions));
Currently, the option value is the array index, which looks like:
<option value="">(choose one)</option>
<option value="0">Rare</option>
<option value="1">Frequent</option>
<option value="2">Moderate</option>
Of course I know that if I set the key as well when constructing the $frequencyOptions variable like
$frequencyOptions = array("Rare" => "Rare", ...
I will be able to store the value in text.
However, since some of these options are very very long, I would prefer to save them in INT in the database.
Yet the challenge I have at this moment is how to display those fields in the "list" in the index page. When I use the form field to display in the view or edit action, it is okay because the select element will be used again. However, if I want to display it in plain text, how should I "translate" it?
One thing I can think of is to create these "conversion" methods in the Model, but I think calling model method in views is not a good practice in MVC.
Any idea?
I'd think adding a method to your Model would be the way to go. How about this:
// In your Model class
// Store the index-to-name map in the Model as well
var $frequencyOptions = array(...);
public function translateFrequency(&$data) {
foreach ($data as &$record) {
$index = $record['ModelName']['frequency'];
$record['ModelName']['frequency'] = $this->frequencyOptions[$index];
}
}
// In your Controller action:
$data = $this->ModelName->find(...);
$this->ModelName->translateFrequency($data);
And then it should display the human-readable value when passed to the index page. If preferred, the above method could be changed so it works on $this->data inside the Model.
Note: The method has to be changed if it should work for a single record data array as well.
A submitted form on my site returns an array of request data that is accessible with
$data = $this->getRequest();
This happens in the controller which gathers the data and then passes this array to my model for placing/updating into the database.
Here is the problem. What if I want to manipulate one of the values in that array? Previously I would extract each value, assigning them to a new array, so I could work on the one I needed. Like so:
$data = $this->getRequest();
$foo['site_id'] = $data->getParam('site_id');
$foo['story'] = htmlentities($data->getParam('story'));
and then I would pass the $foo array to the model for placing/updating into the database.
All I am doing is manipulating that one value (the 'story' param) so it seems like a waste to extract each one and reassign it just so I can do this. Additionally it is less flexible as I have to explicitly access each value by name. It's nicer to just pass the whole request to the model and then go through getting rid of anything not needed for the database.
How would you do this?
Edit again: Looking some more at your question what I am talking about here all goes on in the controller. Where your form`s action will land.
Well you have a couple of options.
First of all $_GET is still there in ZF so you could just access it.
Second there is:
$myArray = $this->_request->getParams();
or
$myArray = $this->getRequest()->getParams();
Wich would return all the params in an array instead of one by one.
Thirdly if the form is posted you have:
$myArray = $this->_request()->getPost();
Wich works with $this->_request->isPost() wich returns true if some form was posted.
About accessing all that in your view you could always just in controller:
$this->view->myArray = $this->_request->getParams();
edit: right I taught you meant the view not the model. I guess I do not understand that part of the question.
If you want to deal with the post data inside your model just:
$MyModel = new Model_Mymodels();
$data = $this->_request->getParams();
$data['story'] = htmlentities($data['story']);
$myModels->SetItAll($data);
And then inside your model you create the SetItAll() function (with a better name) and deal with it there.
Edit: oh wait! I get it. You hate sanytising your input one by one with your technique. Well then what I showed you about how to access that data should simplify your life a lot.
edit:
There is always the Zend_Form route if the parameters are really coming from a form. You could create code to interface it with your model and abstract all this from the controller. But at the end of the day if you need to do something special to one of your inputs then you have to code it somewhere.