[252]: add DB type range validation rule - #253
Conversation
9450961 to
b21cb0e
Compare
|
@yburlakov Please review these changes |
|
@yburlakov Fixed review remarks |
There was a problem hiding this comment.
Pull request overview
Adds a new Laravel validation rule (db_type_range) intended to validate request values against predefined min/max ranges derived from DB column data types (with a default PostgreSQL type range map), and registers it for string-rule usage via the package service provider.
Changes:
- Introduces
DbTypeRangeRule(implementsValidationRule) that validates either numeric ranges or string length ranges based on a type→range map. - Adds a default PostgreSQL type range map via
PostgresDatabaseTypeEnumimplementingDatabaseTypeRangesContract, bound inHelpersServiceProvider. - Extends
ValidatorTestwith new coverage for the rule (pass/fail cases, missing/unknown type handling, object syntax).
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/ValidatorTest.php | Adds tests for the new db_type_range validator and object rule usage. |
| src/Rules/DbTypeRangeRule.php | Implements the core range validation logic using a container-resolved ranges provider. |
| src/HelpersServiceProvider.php | Registers the db_type_range string rule and binds the default ranges provider. |
| src/Enums/PostgresDatabaseTypeEnum.php | Defines the default Postgres type→range mapping. |
| src/Contracts/DatabaseTypeRangesContract.php | Adds the contract for providing type→range mappings. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
… length refs: #252 Comment: #253 (comment)
…asses" cases; refs: #252 Comment: #253 (comment)
06a9d24 to
190e71e
Compare
d1ce30a to
dea6e14
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: dea6e14fd1
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
|
||
| protected function validateInteger(string $attribute, mixed $value, mixed $min, mixed $max, Closure $fail): void | ||
| { | ||
| if (!preg_match(self::INTEGER_PATTERN, (string) $value)) { |
There was a problem hiding this comment.
Guard non-scalar integer inputs before casting
When an integer-backed rule receives a non-scalar value, such as a request array for db_type_range:integer, this cast runs before validation can fail normally. (string) ['foo'] emits an Array to string conversion warning, which Laravel/PHPUnit error handling commonly turns into an exception, and objects without __toString() throw immediately; those inputs should produce the integer validation error instead of crashing the validator.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: da9c0e9d1f
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
|
||
| protected function validateInteger(string $attribute, mixed $value, mixed $min, mixed $max, Closure $fail): void | ||
| { | ||
| if (!is_scalar($value) || !preg_match(self::INTEGER_PATTERN, (string) $value)) { |
There was a problem hiding this comment.
Reject booleans before integer range checks
When JSON/request data supplies true for an integer-backed type such as db_type_range:integer, this condition treats the boolean as scalar and then casts it to the string '1', so the range check passes. That allows a boolean value through a rule whose error text and DB type both require an integer, and PostgreSQL integer columns will reject a boolean parameter instead of accepting it as 1; booleans should be excluded before casting.
Useful? React with 👍 / 👎.
| match (true) { | ||
| $this->resolver->isTypeCategory(DBTypeCategoryEnum::Integer, $this->type) => $this->validateInteger($attribute, $value, $min, $max, $fail), | ||
| $this->resolver->isTypeCategory(DBTypeCategoryEnum::Float, $this->type) => $this->validateFloat($attribute, $value, $min, $max, $fail), | ||
| $this->resolver->isTypeCategory(DBTypeCategoryEnum::String, $this->type) => $this->validateString($attribute, $value, $max, $fail), | ||
| default => null, | ||
| }; |
There was a problem hiding this comment.
| match (true) { | |
| $this->resolver->isTypeCategory(DBTypeCategoryEnum::Integer, $this->type) => $this->validateInteger($attribute, $value, $min, $max, $fail), | |
| $this->resolver->isTypeCategory(DBTypeCategoryEnum::Float, $this->type) => $this->validateFloat($attribute, $value, $min, $max, $fail), | |
| $this->resolver->isTypeCategory(DBTypeCategoryEnum::String, $this->type) => $this->validateString($attribute, $value, $max, $fail), | |
| default => null, | |
| }; | |
| match ($this->resolver->getTypeCategory($this->type)) { | |
| DBTypeCategoryEnum::Integer => $this->validateInteger($attribute, $value, $min, $max, $fail), | |
| DBTypeCategoryEnum::Float => $this->validateFloat($attribute, $value, $min, $max, $fail), | |
| DBTypeCategoryEnum::String => $this->validateString($attribute, $value, $max, $fail), | |
| default => null, | |
| }; |
| enum DBTypeCategoryEnum: string | ||
| { | ||
| case Integer = 'int'; | ||
| case Float = 'float'; | ||
| case String = 'string'; |
There was a problem hiding this comment.
| enum DBTypeCategoryEnum: string | |
| { | |
| case Integer = 'int'; | |
| case Float = 'float'; | |
| case String = 'string'; | |
| enum DBTypeCategoryEnum | |
| { | |
| case Integer; | |
| case Float; | |
| case String; |
…ry(), removed backed enum string values; refs: #252
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3c1b2caf25
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| match ($this->resolver->getTypeCategory($this->type)) { | ||
| DBTypeCategoryEnum::Integer => $this->validateInteger($attribute, $value, $min, $max, $fail), | ||
| DBTypeCategoryEnum::Float => $this->validateFloat($attribute, $value, $min, $max, $fail), | ||
| DBTypeCategoryEnum::String => $this->validateString($attribute, $value, $max, $fail), |
There was a problem hiding this comment.
Enforce lower bounds for string ranges
When a custom resolver categorizes a type as String with a non-zero lower bound, this dispatch drops $min and validateString() only checks the maximum length, so values that are shorter than the declared range pass validation. Fresh evidence in the current code is that the string branch still passes only $max, even though getRange() returns both bounds and the custom resolver extension point exposes string ranges.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
For DB type validation, particularly for strings, using 0 as the lower bound makes sense. If the value is something other than zero, for example 5, that's more of a business rule than a type constraint. Laravel already provides the min validation rule for those kinds of requirements.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8d05e579d3
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
|
||
| private const array RANGES = [ | ||
| self::SMALLINT => [-32768, 32767], | ||
| self::INTEGER => [-2147483648, 2147483647], |
There was a problem hiding this comment.
Register PostgreSQL integer aliases
When callers use PostgreSQL's documented integer spellings such as int (or schema/introspection names like int2, int4, and int8), hasType() reports them as unknown because only integer, smallint, and bigint are keyed here. PostgreSQL documents these as aliases/extensions for the same integer types (https://www.postgresql.org/docs/current/datatype-numeric.html), so db_type_range:int currently throws instead of applying the existing integer range; add those aliases to the range map and category match.
Useful? React with 👍 / 👎.
refs: #252