The above answer is good if you need the fields to be numbered. In my case, I didn't. I have a widget with options that allow the user to select any number of categories to be used within the widget.
Here's my widget form
. — Three important things here
- Make sure to default the value to an empty
array()
if the widget's value is not set
- In the form
<label>
name
attribute, notice that I attach a []
at the end. This tells PHP that I'm submitting an array of values for this key
- Wrap the checkbox in the label as
<label><input type="checkbox" ...></label>
. — Each of our checkboxes will not have a unique id
attribute, so the <label>
for
attribute will not work. We could generate unique IDs, but that's a hassle. If you just wrap the label around the input, the label get associated properly without the hassle of connecting the for
+id
Now the code
public function form($instance) {
$title = isset($instance['title']) ? $instance['title'] : '';
$categories = isset($instance['categories']) ? $instance['categories'] : array();
?>
<p>
<label for="<?php echo $this->get_field_id('title') ?>">
<?php _e( 'Title:' ) ?>
</label>
<input class="widefat"
id="<?php echo $this->get_field_id('title') ?>"
name="<?php echo $this->get_field_name('title') ?>"
value="<?php echo $title ?>" />
</p>
<p>Categories</p>
<ul>
<?php foreach (\get_categories() as $category): ?>
<li>
<label>
<input type="checkbox"
class="checkbox"
name="<?php echo $this->get_field_name('categories') ?>[]"
value="<?php echo $category->cat_ID ?>"
<?php checked(in_array($category->cat_ID, $categories)) ?> />
<?php echo $category->name ?>
</label>
</li>
<?php endforeach ?>
</ul>
<?php
}
And here's my update function
I'm interested in saving the Category IDs in an array, which are numbers, so I use array_map
with intval
to ensure that all submitted datum are valid integers. Additionally, I use array_filter
to remove any invalid submissions.
// @param array $a - the new instance options
// @param arram $b - the old instance options
public function update($a, $b) {
return array(
'title' => isset($a['title']) ? strip_tags($a['title']) : $b['title'],
'categories' => isset($a['categories']) ? array_filter(array_map(function($id) { return intval($id); }, (array) $a['categories'])) : (array) $b['title']
);
}
It's particularly challenging to describe this WordPress stuff. If you have any questions, I'll be happy to elaborate.
$instance
is an array and contains all values. And what do you mean by 'to store the data of all fields in just one row'? Did you mean one database row?