field = $field; $this->isRequired = $isRequired; } public function validate(string $attribute, mixed $value, Closure $fail): void { if (!$this->isRequired && empty($value)) { return; // If not required and empty, validation passes } if (!is_array($value)) { $fail('The Matrix field must be an array.'); return; } $rows = $this->field['rows']; $columns = $this->field['columns']; foreach ($rows as $row) { if (!array_key_exists($row, $value)) { if ($this->isRequired) { $fail("Missing value for row '{$row}'."); } continue; } $cellValue = $value[$row]; if ($cellValue === null) { if ($this->isRequired) { $fail("Value for row '{$row}' is required."); } continue; } if (!in_array($cellValue, $columns)) { $fail("Invalid value '{$cellValue}' for row '{$row}'."); } } // Check for extra rows that shouldn't be there $extraRows = array_diff(array_keys($value), $rows); foreach ($extraRows as $extraRow) { $fail("Unexpected row '{$extraRow}' in the matrix."); } } }