feat(lagoon): check min and max as character length on string and url fields (quick-261104-f4x)

- on a string or url field that is not numeric or integer, min and max
  compare utf8.RuneCountInString (Laravel's mb_strlen) and answer with
  the lagoon::validation min.string / max.string messages
- a min or max argument that is not a whole number is the
  unrecognized-rule error, whatever the value
- rule strings without string or url keep their results (pinned by a
  test); between is unchanged
This commit is contained in:
Jakub Zych
2026-11-04 11:13:09 +01:00
parent d2ce3a2c3b
commit d166f1c308
5 changed files with 109 additions and 4 deletions

View File

@@ -108,7 +108,7 @@ fmt.Println(string(out))
// {"title":["The title field is required."],"views":["The views may not be greater than 1000."]}
```
A zero `time.Time`, `lagoon.Date` or `lagoon.TimeOfDay`, or a pointer to one, is empty for `required`, so a required date field with no value fails instead of saving year 1. The supported rules are `required`, `nullable`, `integer`, `numeric`, `between`, `min`, `max`, `in`, `unique`, `boolean`, `email`, `string`, `url`, `confirmed`, `different` and `mimes`. Any other rule is an error, so a rule that SummerCMS does not implement cannot be skipped by accident. `string` accepts a string or a pointer to one, and `url` a URL that matches Laravel's pattern (the same one request validation uses, so `javascript:` links and addresses without a scheme are refused). Both skip a missing, empty or blank value; use `required` to refuse those. On a field that is `integer` or `numeric`, `min`, `max` and `between` compare the number; on other fields they compare the length. A number below the lower bound gets the `min` message, one above the upper bound the `max` message, and a bound that came from `between` gets the numeric `between` message (`The views must be between 0 and 10.`).
A zero `time.Time`, `lagoon.Date` or `lagoon.TimeOfDay`, or a pointer to one, is empty for `required`, so a required date field with no value fails instead of saving year 1. The supported rules are `required`, `nullable`, `integer`, `numeric`, `between`, `min`, `max`, `in`, `unique`, `boolean`, `email`, `string`, `url`, `confirmed`, `different` and `mimes`. Any other rule is an error, so a rule that SummerCMS does not implement cannot be skipped by accident. `string` accepts a string or a pointer to one, and `url` a URL that matches Laravel's pattern (the same one request validation uses, so `javascript:` links and addresses without a scheme are refused). Both skip a missing, empty or blank value; use `required` to refuse those. On an `integer` or `numeric` field `min`, `max` and `between` compare the number. On a `string` or `url` field `min` and `max` compare the length in characters (`The title may not be greater than 255 characters.`), and a bound that is not a whole number is an error. `between` compares the length on any other field. A number below the lower bound gets the `min` message, one above the upper bound the `max` message, and a bound that came from `between` gets the numeric `between` message (`The views must be between 0 and 10.`).
`unique:<table>` runs a query to check that no other row of the table has the value in the field's column, so it needs a database handle; pass the transaction you are writing in. Soft-deleted rows do not count, and when the model you pass has an ID, its own row does not count either, so the same rules work for create and update. Pass a `phrasebook.Translator` as the last argument to get the messages in the request locale from the `lagoon::validate` catalog; with `nil` they are in English. See [Localization](../services/localization.md).