Multiple choices¶
Use a checkbox group or a multiple select when people may choose several
options. The value is a list, such as ['suits', 'kanzu'].
Example¶
<?php
declare(strict_types=1);
namespace App\Forms;
use Ephraitech\Forms\Form;
class PreferencesForm extends Form
{
protected function define(): void
{
$this->checkboxes('interests', 'What are you interested in?', [
'suits' => 'Suits',
'shirts' => 'Shirts',
'kanzu' => 'Kanzu',
'accessories' => 'Accessories',
])
->rules('required')
->messages(['required' => 'Choose at least one.'])
->inline();
$this->select('branches', 'Branches you visit', [
'kampala' => 'Kampala',
'entebbe' => 'Entebbe',
'jinja' => 'Jinja',
])
->multiple()
->size(3)
->help('Hold Ctrl (Cmd on a Mac) to choose several.');
$this->submit('Save preferences');
}
}
validated() returns lists:
How it works¶
- Checkbox groups and multiple selects
checkboxes()shows one box per option;select()->multiple()shows a list where several items can be selected, withsize()setting how many rows are visible. Both are submitted asname[].- Always a list
validated()returns a list, and an empty one ([]) when nothing is chosen, nevernullor a missing key. A single value sent instead of a list is wrapped in one.- Rules
rules()applies to the list as a whole:requiredmeans at least one item.eachRules()applies to every item, for exampleeachRules('max_length[20]').- Options are checked
- Every chosen value must be one of the options. Anything else, such as a
value added with the browser's developer tools, is rejected with "Please
choose a valid option for ...". You do not need an
in_listrule. - Editing
fill()accepts a list, and the matching boxes are ticked. After a failed submission, exactly the boxes the visitor ticked stay ticked.
Storing lists¶
A list can be stored as JSON in a text column. CodeIgniter models convert it for you with casts:
<?php
declare(strict_types=1);
namespace App\Models;
use CodeIgniter\Model;
class CustomerPreferenceModel extends Model
{
protected $table = 'customer_preferences';
protected $returnType = 'array';
protected $allowedFields = ['customer_id', 'interests', 'branches'];
// Lists are stored as JSON text and come back as arrays.
protected array $casts = [
'interests' => 'json-array',
'branches' => 'json-array',
];
}
<?php
declare(strict_types=1);
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class CreateCustomerPreferences extends Migration
{
public function up(): void
{
$this->forge->addField([
'id' => ['type' => 'INT', 'unsigned' => true, 'auto_increment' => true],
'customer_id' => ['type' => 'INT', 'unsigned' => true],
'interests' => ['type' => 'TEXT'],
'branches' => ['type' => 'TEXT'],
]);
$this->forge->addPrimaryKey('id');
$this->forge->createTable('customer_preferences');
}
public function down(): void
{
$this->forge->dropTable('customer_preferences');
}
}
With the casts, $model->insert($form->validated()) stores
["suits","kanzu"], find() returns the list again, and fill() puts it
back into the form. When you need to search or join on the choices, store them
in a separate table with one row per choice instead.
Common mistakes¶
Saving the list straight into a plain column. Without a cast (or
json_encode()), saving an array fails. Use the casts above.
Using rules('in_list[...]') for the items. It checks the list as a
whole, not each item. The options are checked automatically; for other item
rules use eachRules().
Expecting a placeholder on a multiple select. A multiple select has no
"Choose..." option, because it would itself be selectable. Use help()
instead.
Related¶
- Layout to place a checkbox group in a row
- Getting started for a single-choice select