Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

Form Questions /

Editing the contents of a Form class object


Reply


7 Posts   674 Views

Avatar
Yokelassence

Community Member, 15 Posts

19 June 2012 at 9:53pm

Edited: 19/06/2012 9:56pm

There's a few topics out there already similar to this (Such as [url="http://www.silverstripe.org/form-questions/show/5819"]here[/url]) but they never got an answer. I'm reviving this topic again because there is some clear interest in this but no instruction on how to do it so far

In my case I have two items on a form: a dropdownbox for selecting a pre-set item and a textfield for defining your own item if its not in the dropdownbox.

Since these two form fields are just different ways of defining the same thing, both form fields are for the exact same database field. The logic is, if you use the textfield then content of the textfield goes to the database and the dropdownbox content is ignored. if the textfield is empty, the content of the combobox goes to the database

In my controller my logic would look like this:

function submitform($data, $form) {

if(!empty($data['textfield'])){
//code for setting variables in the $form array
$form->setFields(?);
}

$submission = new User_Item();
$form->saveInto($submission);
$submission->write();
}

Looking at the API, it looks like the setFields function is the only function capable of editing $form, but it's not clear how to use it properly. It takes a fieldset object containing an array of form objects, but giving $form a new fieldset object might completely replace everything rather than just overwrite what I want

SHORT VERSION: Is there a way to access and edit the contents of a [url="http://api.silverstripe.org/2.4/forms/core/Form.html#methodsetFields"]Form class object[/url]?

---

If editing $form is impossible, perhaps it would be better if I just updated the database with my own code using the DB class. Agree/Disagree?

function submitform($data, $form) {

if(!empty($data['textfield'])){
DB::query("INSERT INTO table VALUES (item=\'".$data['textfield']."\')");
} else {
DB::query("INSERT INTO table VALUES (item=\'".$data['dropdownbox']."\')");
}
}

Avatar
Yokelassence

Community Member, 15 Posts

21 June 2012 at 10:26pm

Alright since I really need to get this project done sooner than later, I'm going to take the silence as a 'no' and simply update the database myself with the DB class via my own MySQL queries. I know SQL inside and out so this is no problem for me

I am aware that according to the Silverstripe documentation, using the DB class to update the database yourself not recommended but right now it's the only way I know how to update the database in the specific way that I want it.

If anyone knows the proper way to customize database input then STOP ME NOW!

Avatar
Yokelassence

Community Member, 15 Posts

23 June 2012 at 5:34pm

Edited: 23/06/2012 5:41pm

No objections? Alright then I hereby conclude this thread.

I have resolved my problem by using the DB class to update my database in my own way, rather than rely on the form data and Silverstripes functions for processing it.

If you are dealing with a form that's not consistent with your database and you have to get fancy with the form data, forget about editing the form array. It's too much trouble. Instead you may have to what I did: Do it yourself the good old fashioned way with the DB class and a little SQL knowledge using the data array

Example:

function submitform($data, $form) {
DB::query("INSERT INTO table (col1, col1, col3) VALUES (".$data['col1'].",".$data['col2'].",".$data['col3'].");
}

Avatar
Willr

Forum Moderator, 5513 Posts

23 June 2012 at 7:00pm

What are you saving with the dropdown field? If you're trying to save to a has_one field you need to make sure you have your DropdownField name suffixed with 'ID'

static $has_one = array(
'Country' => 'Country'
);
..

new DropdownField('CountryID', 'Select your country', ....);

Then your saveInto should work. If you're saving it into a standard Database field make sure your dropdown has 'value' attributes in the HTML.

The method you've done is open to a massive SQL injection issue so I recommend you don't do that (or if you do, use Convert::raw2sql() on each input before you get it anywhere near your DB::query();

Relying on DB::query directly is also bad, Ideally try and use the ORM when possible. Even if your $form->saveInto() isn't working do something like

$obj = new User_Item();
$obj->Message = $data['Message'];
$obj->Field = $data['SomeOtherField'];
$obj->write();

Avatar
Yokelassence

Community Member, 15 Posts

26 June 2012 at 12:02am

Edited: 30/06/2012 3:25am

The dropdown field is technically saving just a single text object. It is not a country field, but for the sake of example; lets just pretend that it is.

The country specified in the dropdown field saves directly to the country column in the user table. Users may have only one country associated with them

While the dropdown field saves data to the user table, the contents of the dropdown field are retrieved from a separate table of countries: A country table filled with unique country names

I want users to be able to append to this table of countries so the dropdown box will list the countries that other users have chosen and/or any countries we forgot to list. This is done on the same form

So next to the dropdown you have a text field where the user can specify their own country if they cannot find the country they want in dropdown field.

If the user enters a new country in the text field, the contents of the text field is sent to the country column in the user table while the contents of the dropdown box is ignored completely. At the same time, the country is also added to the table of countries on record so that user-provided country will appear in the dropdown box for the next user.

NOTE: I stress again; it's not actually a country field. But exactly what it is, is not really important in this context so long as you understand the use case.

---

Anyway, thank you for your suggestion. It sounds like what I should be doing is instantiating a new object of class "user" and manipulating the individual properties of that class object (which will be easy enough to do)

The [url="http://api.silverstripe.org/2.4/sapphire/model/DataObject.html#methodwrite"]Write[/url] function will then do the SQL for me, is that what you mean?

EDIT: Answering my own question: Yes, that is what it does and that is what Willr meant.

Avatar
Willr

Forum Moderator, 5513 Posts

30 June 2012 at 9:38am

The dropdown field is technically saving just a single text object.

Ok, then just make sure you pass an array with the name of the country as both keys and values. The key value is used in the database, the value what the user see's.

$options = array(
'New Zealand' => 'New Zealand',
'Australia' => 'Australia'
);

$fields = new DropdownField('Country', 'Select your country', $options);

Avatar
Yokelassence

Community Member, 15 Posts

30 June 2012 at 3:03pm

Edited: 30/06/2012 3:05pm

Yep, that's all taken care of.

I resolved my problem like this:

if (!empty($data['country_alt'])) {
$data['country'] = $data['country_alt'];
}

$submission = new User();
$submission->country = $data['country'];
$submission->write();

Country is the dropdown and Country_alt is the text field. Absolutely no manipulation of $form is necessary.

Thanks for the help