Skip to content

feat: add insert-only fields to Model#10350

Open
memleakd wants to merge 4 commits into
codeigniter4:4.8from
memleakd:feat/model-insert-only-fields
Open

feat: add insert-only fields to Model#10350
memleakd wants to merge 4 commits into
codeigniter4:4.8from
memleakd:feat/model-insert-only-fields

Conversation

@memleakd

Copy link
Copy Markdown
Contributor

Description

This adds $insertOnlyFields to Model.

The goal is to allow fields that can be set when a row is created, but should not be submitted later through Model update operations. This can be useful for values like public IDs, external references, generated slugs, or similar fields that should normally stay unchanged after insert.

Example:

class UserModel extends Model
{
    protected $allowedFields = ['public_id', 'name', 'email'];

    protected $insertOnlyFields = ['public_id'];
}

With this configuration, public_id is allowed during insert() and insertBatch(), but update(), updateBatch(), and update-side save() will throw a DataException if the field is submitted.

This is only Model-level protection. It does not create a database constraint, does not inspect previous database values, and does not affect direct Query Builder writes. Calling protect(false) disables this protection, the same as other field protection.

I also added setInsertOnlyFields() for cases where the list needs to be changed at runtime.

Tests cover insert, insertBatch, update, save, set/update, updateBatch, entity updates, validation order, and protect(false).

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

- add $insertOnlyFields and setInsertOnlyFields() to Model
- prevent configured fields from being submitted during update operations
- allow insert-only fields during insert and insertBatch
- document the Model-level protection boundaries
- add coverage for update, save, updateBatch, entity, and protect(false) paths

Signed-off-by: memleakd <121398829+memleakd@users.noreply.github.com>
@github-actions github-actions Bot added the 4.8 PRs that target the `4.8` branch. label Jun 29, 2026
Signed-off-by: memleakd <121398829+memleakd@users.noreply.github.com>

@michalsn michalsn left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, I think this is a useful addition.

My main concern is whether insert-only fields should follow the existing $throwOnDisallowedFields behavior: silently remove them from updates by default and throw only in strict mode. I left an inline comment about that.

It would be helpful to document that replace() is outside this insert-only protection.

Comment thread system/BaseModel.php Outdated
Comment thread system/Commands/Generators/Views/model.tpl.php Outdated
Comment thread system/BaseModel.php Outdated
memleakd added 2 commits June 30, 2026 20:06
Signed-off-by: memleakd <121398829+memleakd@users.noreply.github.com>
Signed-off-by: memleakd <121398829+memleakd@users.noreply.github.com>
@memleakd

Copy link
Copy Markdown
Contributor Author

Thanks for the review @michalsn. Just pushed an update to match field protection behavior: discarded by default, and throws only in strict mode. Also addressed the other nits.

@michalsn michalsn left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. Thank you!

@michalsn michalsn added the enhancement PRs that improve existing functionalities label Jun 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

4.8 PRs that target the `4.8` branch. enhancement PRs that improve existing functionalities

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants