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.
$instanceis 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?