Skip to content

Conversation

@michalsn
Copy link
Member

Description
This PR adds primary key validation to the Model's insert(), insertBatch(), update(), and delete() methods (for insert* when useAutoIncrement is disabled). This ensures that invalid primary key values are caught early with clear error messages, rather than causing confusing database errors.

Previously, when you passed invalid values like 0, '0', or empty strings as primary keys, these values would often be silently ignored by the query builder.

The new validateID() method in BaseModel now explicitly rejects these invalid primary key values:

  • null (for insert when auto-increment is disabled)
  • 0 (integer zero)
  • '0' (string zero)
  • '' (empty string)
  • true and false (booleans)
  • [] (empty array)
  • Nested arrays like [[1, 2]]
  • Arrays containing any invalid values

When these values are detected, the model throws an InvalidArgumentException with a specific message like "Invalid primary key: 0 is not allowed".

Validation timing

  • For update() and delete(): Validation happens in BaseModel before beforeUpdate/beforeDelete events, preventing invalid values from reaching event handlers
  • For insert() and insertBatch() (when auto-increment is disabled): Validation happens in Model::doInsert() and Model::doInsertBatch() after the beforeInsert event (allowing devs to use this event to produce the PK), but before database queries

If developers have a legitimate need to use values like 0 or '0' as primary keys (e.g., legacy systems), they can override the validateID() method in their model to customize the behavior.

Checklist:

  • Securely signed commits
  • Component(s) with PHPDoc blocks, only if necessary or adds value (without duplication)
  • Unit testing, with >80% coverage
  • User guide updated
  • Conforms to style guide

@michalsn michalsn added enhancement PRs that improve existing functionalities breaking change Pull requests that may break existing functionalities 4.7 labels Dec 14, 2025
@neznaika0
Copy link
Contributor

Great work! I tried to do this in the first PR, unsuccessfully. I won't be able to test locally, looking at the tests everything should work as planned.

Since I am refactoring the code more, I would not like to add new phpstan errors. Maybe you should ignore them completely in the tests?

@michalsn
Copy link
Member Author

Since I am refactoring the code more, I would not like to add new phpstan errors. Maybe you should ignore them completely in the tests?

I'm not sure what you mean.

I added return types to the providers to avoid introducing new errors.

@github-actions github-actions bot added the stale Pull requests with conflicts label Dec 14, 2025
@michalsn michalsn force-pushed the feat/primaryKeyValidation branch from a706eaa to 262a996 Compare December 14, 2025 17:05
@codeigniter4 codeigniter4 deleted a comment from github-actions bot Dec 14, 2025
@michalsn michalsn removed the stale Pull requests with conflicts label Dec 14, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

4.7 breaking change Pull requests that may break existing functionalities enhancement PRs that improve existing functionalities

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Possible bug: Model functions (doDelete, doFirst, etc..) ignores zero as id

2 participants