›
byrcsc/laravel-checklist · 1.x
Items define validated answer shapes while ordered sections organize them into a bounded tree.
Each item asks one question and decides which answers it accepts and how they score. Sections group items so the checklist reads in order, and a conditional rule can hide a whole section at once.
| Builder method | Accepted answer | Stored value | Score |
|---|---|---|---|
checkbox() | boolean, 0/1, checked/unchecked | boolean | checked 1, unchecked 0 |
yesNo() | boolean, 0/1, yes/no | boolean | yes 1, no 0 |
passFail() | boolean, 0/1, pass/fail | boolean | pass 1, fail 0 |
text() | string | string | unscored |
number() | numeric value | float | unscored |
rating() | whole number inside the bounds | integer | normalized from 0 to 1 |
date() | Y-m-d string or DateTimeInterface | Y-m-d string | unscored |
select() | configured option value | string or string list | option score or mean |
The three boolean types also accept the strings true and false, ignoring
case and surrounding whitespace. They do not accept another type's words, so a
pass/fail item rejects yes.
Dates parse strictly. Values such as now, +1 day, 2026-02-30, and a date
with a time are rejected.
yesNo() scores yes as 1 and no as 0, and checkbox() scores checked as
1. An answer whose score is exactly 0 is a failed answer: it triggers the
item-failed notification and, on a critical item, fails the whole checklist.
Phrasing therefore decides the result. "Any body damage?" scores an undamaged
vehicle at 0 and reports it as a failure, because the accurate answer is no:
// Scores backwards: a clean vehicle answers "no" and earns nothing.
$builder->yesNo('Any body damage?');
// Scores as intended: a clean vehicle answers "yes" and earns full weight.
$builder->yesNo('Is the bodywork free of damage?');Write the question so that yes, checked, and pass are the desired outcomes,
then branch on false when you need the follow-up questions. Nothing in the
package enforces this. The scoring is correct in both cases; only the second
question maps an undamaged vehicle to a passing score.
$builder
->text('Notes', maxLength: 500)
->number('Odometer', min: 0, max: 999999)
->rating('Cleanliness', min: 1, max: 5)
->select('Condition', options: [
['value' => 'good', 'label' => 'Good', 'score' => 1],
['value' => 'fair', 'label' => 'Fair', 'score' => 0.5],
['value' => 'poor', 'label' => 'Poor', 'score' => 0],
], multiple: false);Text length counts characters rather than bytes. Number bounds are optional
and inclusive. Rating bounds are required and min must be below max.
Select option values must be strings or integers and must be unique. Stored values are always strings. A multiple select stores choices in configured option order, not selection order, and rejects duplicates.
Modifiers apply to the item immediately before them:
$builder->passFail('Brakes operate correctly')
->required()
->critical()
->weight(3);required() blocks submission while an applicable item is unanswered.
critical() makes a zero-scoring applicable answer fail the checklist.
weight() changes the item's relative share of the total score.
A modifier after a section callback has no item in scope and throws. Put the modifier inside the callback beside the item it changes.
$builder->section('Exterior', function (TemplateBuilder $builder): void {
$builder->passFail('Lights operate');
$builder->section('Wheels', function (TemplateBuilder $builder): void {
$builder->passFail('Tires are roadworthy');
});
});Items outside a section attach directly to the version. Sibling sections and
items retain declaration order through their position values.
The default maximum depth is three, where a top-level section has depth one.
Raise checklist.max_section_depth before authoring when the domain needs a
deeper tree. Deep trees increase the work required for visibility and scoring
walks.