Skip to content

Conversation

neznaika0
Copy link
Contributor

Description
After a DB query, the entity may break if the result does not contain all the "fields == properties".
Example, do we need a "virtual" $entity->user property, which stores by default ?User. It may not be necessary to insert it into the database, but it's important in other work.

There are other questions:

  1. Why doesn't the documentation describe the case of underlining properties? They are skipped when calling Entity::toArray() but allowed in Entity::toRawArray()
  2. The behavior of superfluous properties is not described. How they will be shown for the entity and when working with the DB.

I would add this to the current PR. Answering questions may require correction if we find abnormal 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

@neznaika0 neznaika0 force-pushed the fix/entity-loses-attr branch from dce5359 to faca2d0 Compare October 7, 2025 09:30
@michalsn
Copy link
Member

michalsn commented Oct 8, 2025

Seems like a BC break. It's a developer's responsibility to assign properties that will not break the entity.

The differences between the arrays' methods are clear: https://codeigniter.com/user_guide/models/entities.html#bulk-accessing-properties - and when each of them is used is pretty obvious to me, but if you think this could use more clarification, then please send a PR.

@samsonasik
Copy link
Member

samsonasik commented Oct 8, 2025

probably add optional flag?, eg:

    public function injectRawData(array $data, bool $mergeToExistingAttributes = false)

@neznaika0
Copy link
Contributor Author

Okay. If we find a solution, I'll move it to 4.7.

@michalsn , description for methods. No specification for "_user _name _property". They're skipping.

$keys = array_filter(array_keys($this->attributes), static fn ($key): bool => ! str_starts_with($key, '_'));

@samsonasik my opinion is a system error. Does not require a flag.

Case:

  • Set the initial properties with exact values.
  • Create an empty object. It has a working state - the properties are initialized and not undefined (null whenever possible).
  • Make a query to the database, but it does not contain all the fields. We get uninitialized properties. When we access them, we see an exception.

It is important to understand: After the appearance of DataCaster, entities cannot be a simple reflection of a row from the database.
In fact, it can be used as an object with logic, and it is possible to forget that it is related to the database.

Therefore, I allow the possibility of having "virtual" properties, which may not be stored in the database or may be filled in later. I found out in michalsn/codeigniter-nested-model For example, in relationships OneToOne, OneToMany...

Having a DataCaster, the object's synchronization is almost the same - $original contains $attributes properties, including objects. Yes, this was the normal behavior when there were only scalars in the original.

Do we want to go back to saving scalar types in the original (copy for the database)? Then we need to review the entities: synchronization, has changed..

I hope I got the meaning right.

@michalsn
Copy link
Member

michalsn commented Oct 8, 2025

I think there might be a bit of a misunderstanding. The fact that we have model casting now doesn’t really change how entities are used (except that we shouldn't mix entity casting and model casting at the same time).

You're still free to define your own properties - just avoid using the attributes property, since it's reserved for data representing database columns (in the context of entities used with the database).

We can never really know how creative other developers have been, and a change like this (even if it seems minor) could impact their work. That said, I'm not stubborn about it. If most people think it's a good idea, I'm happy to go along with it.

@samsonasik's idea is a good one, but it wouldn't change anything in the OP's case, since the entity from the database is seeded with injectRawData() using the default parameter.

@neznaika0
Copy link
Contributor Author

I'm already exhausted. Everything works, but every time something special appears. Every time I want to drop the code...

I have already used private properties in a custom entity. Some behavior needs to be updated and the get/set magic is no longer needed. This is a more stable option. Therefore, I work manually with the attributes.

Do we need an interface to abstract the class? To completely rewrite the entity.

@neznaika0 neznaika0 force-pushed the fix/entity-loses-attr branch from faca2d0 to 7222141 Compare October 11, 2025 07:05
@neznaika0 neznaika0 changed the base branch from develop to 4.7 October 11, 2025 07:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants