Skip to content

feat(entity): Provide a new API for entities - #56199

Open
CarlSchwan wants to merge 13 commits into
masterfrom
carl/attributes-entity-2
Open

feat(entity): Provide a new API for entities#56199
CarlSchwan wants to merge 13 commits into
masterfrom
carl/attributes-entity-2

Conversation

@CarlSchwan

@CarlSchwan CarlSchwan commented Nov 4, 2025

Copy link
Copy Markdown
Member

Entity are now simple data object with attributes for the database mapping. They are manipulated via a Repository which reads the attributes to insert, update, delete and queries the PDO from the database.

Using attributes makes it easier to extends in the future with relations (ManyToMany, OneToMany, OneToOne, ...).

The design of the Repository is based on a mix between the Doctrine ORM repository while keeping some methods from the QBMapper for easier porting.

Example of a entity

#[Entity(name: 'twofactor_backupcodes')]
final class BackupCode {
	#[Id(generatorClass: IGenerator::class)]
	#[Column(name: 'id', type: Types::STRING, length: 64, nullable: false)]
	public ?string $id = null;

	#[Column(name: 'user_id', type: Types::STRING, length: 64, nullable: false)]
	public string $userId;

	#[Column(name: 'code', type: Types::STRING, length: 128, nullable: false)]
	public string $code;

	#[Column(name: 'used', type: Types::SMALLINT, nullable: false, default: 0)]
	public int $used = 0;
}

Supported

  • OneToOne relationship
  • ManyToOne relationship
  • Autoincremented ID
  • Snowflake ID
  • Basic queries
  • Same feature coverage as the old Entities so it's a drop-in replacement

Missing but for later

Checklist

@blizzz

blizzz commented Nov 5, 2025

Copy link
Copy Markdown
Member

Would have preferred the new API and the reference implementation in backup codes and Tagging to be two different commits. But cool.

What do you think of a CacheEnabled repository next to it (that wraps the Repository and just has a runtime cache)? Have a mapper with such functionality in tables, and saw it on at least another app as well, might be worth to have something like this implemented once properly?

@CarlSchwan

Copy link
Copy Markdown
Member Author

Would have preferred the new API and the reference implementation in backup codes and Tagging to be two different commits. But cool.

Currently it's more of a prototype, I'll split that in multiple commits.

What do you think of a CacheEnabled repository next to it (that wraps the Repository and just has a runtime cache)? Have a mapper with such functionality in tables, and saw it on at least another app as well, might be worth to have something like this implemented once properly?

Yes that could make sense. That I also saw in multiple apps is the relation stuff: https://github.com/nextcloud/deck/blob/main/lib/Db/RelationalEntity.php which could be quite handy

Comment thread lib/public/AppFramework/Db/Attribute/Column.php Outdated
Comment thread lib/public/AppFramework/Db/Repository.php Outdated
Comment thread lib/public/AppFramework/Db/Repository.php Outdated

@come-nc come-nc left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks promising.

Comment thread apps/twofactor_backupcodes/lib/Db/BackupCode.php Outdated
Comment thread lib/private/Tags.php Outdated
Comment thread lib/public/AppFramework/Db/Repository.php Outdated
Comment thread lib/public/AppFramework/Db/Repository.php Outdated
@CarlSchwan
CarlSchwan force-pushed the carl/attributes-entity-2 branch from 27d1fd8 to 29a9903 Compare June 15, 2026 15:27
@CarlSchwan
CarlSchwan force-pushed the carl/attributes-entity-2 branch from 29a9903 to 0ac62ed Compare July 21, 2026 11:52
@CarlSchwan
CarlSchwan force-pushed the carl/attributes-entity-2 branch 2 times, most recently from f362314 to 68c1790 Compare July 21, 2026 14:12
@CarlSchwan CarlSchwan added 3. to review Waiting for reviews feature: database Database related DB labels Jul 21, 2026
@CarlSchwan
CarlSchwan marked this pull request as ready for review July 29, 2026 11:14
@CarlSchwan
CarlSchwan requested review from a team, ChristophWurst and miaulalala as code owners July 29, 2026 11:14
@CarlSchwan
CarlSchwan requested review from come-nc, leftybournes, nfebe and salmart-dev and removed request for a team July 29, 2026 11:14
Comment thread lib/public/AppFramework/ORM/Attribute/Entity.php Outdated
Comment thread lib/public/AppFramework/ORM/Repository.php Outdated

@come-nc come-nc left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

How is the modified columns detection replaced?
I think the old API was keeping track of which values were modified and I did not see how it is done here, as properties are public and set directly.

@CarlSchwan

Copy link
Copy Markdown
Member Author

How is the modified columns detection replaced? I think the old API was keeping track of which values were modified and I did not see how it is done here, as properties are public and set directly.

There is no detection, all properties are updated all the time. IHMO this is negligible in term of performance/network compared to the effort required to track changes via something similar to Doctrine Unit of Work as there isn't super frequent updates and for high performance code, it's best to anyway write queries manually requesting only what is needed and writing only what changed.

See https://www.doctrine-project.org/projects/doctrine-orm/en/3.6/reference/unitofwork.html At the moment, since the public API is minimal, we could add support for that later on.

@CarlSchwan
CarlSchwan force-pushed the carl/attributes-entity-2 branch 3 times, most recently from 5e9186a to 3584712 Compare August 6, 2026 11:05
@CarlSchwan
CarlSchwan force-pushed the carl/attributes-entity-2 branch from 77140cf to 476c196 Compare August 6, 2026 12:42

@ChristophWurst ChristophWurst 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.

Quick review

Good stuff 👏

Comment thread lib/public/AppFramework/ORM/Attribute/Id.php Outdated
Comment thread apps/comments/composer/composer/installed.php Outdated
@CarlSchwan
CarlSchwan force-pushed the carl/attributes-entity-2 branch 2 times, most recently from abafdee to 9afb6be Compare August 10, 2026 17:33
@miaulalala
miaulalala removed their request for review August 11, 2026 09:32
CarlSchwan and others added 12 commits August 11, 2026 17:27
Entity are now simple data object with attributes for the database
mapping. They are manipulated via a Repository which reads the
attributes to insert, update, delete and queries the PDO from the
database.

Using attributes makes it easier to extends in the future with relations
(ManyToMany, OneToMany, OneToOne, ...).

The design of the Repository is based on a mix between the Doctrine ORM
repository while keeping some methods from the QBMapper for easier
porting.

Signed-off-by: Carl Schwan <carl.schwan@nextcloud.com>
And do a lot of refactoring

Signed-off-by: Carl Schwan <carlschwan@kde.org>
Signed-off-by: Carl Schwan <carl@carlschwan.eu>
Assisted-by: ClaudeCode:claude-opus-4-8
Signed-off-by: Carl Schwan <carl@carlschwan.eu>
Signed-off-by: Carl Schwan <carl@carlschwan.eu>
Signed-off-by: Carl Schwan <carl@carlschwan.eu>
This is a left over from the maps prototype

Signed-off-by: Carl Schwan <carl@carlschwan.eu>
Signed-off-by: Carl Schwan <carl@carlschwan.eu>
Signed-off-by: Carl Schwan <carl@carlschwan.eu>
Let's keep this for a later refactor

Signed-off-by: Carl Schwan <carl@carlschwan.eu>
Assisted-by: ClaudeCode:claude-opus-5
Signed-off-by: Carl Schwan <carl@carlschwan.eu>
Signed-off-by: Carl Schwan <carl@carlschwan.eu>
@CarlSchwan
CarlSchwan force-pushed the carl/attributes-entity-2 branch from 9afb6be to 71ab884 Compare August 11, 2026 15:43
@CarlSchwan CarlSchwan added this to the Nextcloud 35 milestone Aug 11, 2026
@CarlSchwan
CarlSchwan enabled auto-merge August 11, 2026 18:55
@kesselb
kesselb requested a balanced review from Copilot August 11, 2026 19:11

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Introduces an attribute-driven ORM API and migrates tagging and two-factor backup-code persistence to it.

Changes:

  • Adds entity metadata, repositories, relations, and schema helpers.
  • Migrates tags and backup codes from QBMapper.
  • Adds ORM tests, static-analysis configuration, and autoload entries.

Reviewed changes

Copilot reviewed 29 out of 29 changed files in this pull request and generated 13 comments.

Show a summary per file
File Description
tests/lib/TagsTest.php Resolves the new mapper through DI.
tests/lib/AppFramework/ORM/RepositoryTest.php Tests repository and relation behavior.
psalm-strict.xml Enables strict ORM analysis.
lib/public/ITags.php Tightens tag API types.
lib/public/AppFramework/ORM/Repository.php Adds the public repository API.
lib/public/AppFramework/ORM/Attribute/OneToOne.php Defines one-to-one metadata.
lib/public/AppFramework/ORM/Attribute/ManyToOne.php Defines many-to-one metadata.
lib/public/AppFramework/ORM/Attribute/JoinColumn.php Defines relation columns.
lib/public/AppFramework/ORM/Attribute/Id.php Defines primary-key metadata.
lib/public/AppFramework/ORM/Attribute/Entity.php Defines entity metadata.
lib/public/AppFramework/ORM/Attribute/Column.php Defines column metadata.
lib/public/AppFramework/Db/QBMapper.php Corrects documentation grammar.
lib/private/Tags.php Adapts tags to data objects.
lib/private/TagManager.php Clarifies documentation.
lib/private/Tagging/TagMapper.php Migrates tags to Repository.
lib/private/Tagging/Tag.php Converts tags to attributed entities.
lib/private/AppFramework/ORM/PropertyAttributes.php Aggregates property metadata.
lib/private/AppFramework/ORM/EntityManager.php Implements ORM persistence and schemas.
lib/private/AppFramework/ORM/EntityInfo.php Reflects and validates entities.
lib/composer/composer/autoload_static.php Registers ORM classes.
lib/composer/composer/autoload_classmap.php Registers ORM classes.
build/rector-strict.php Enables strict Rector checks.
build/psalm-baseline.xml Removes resolved tag suppressions.
apps/twofactor_backupcodes/tests/Unit/Service/BackupCodeStorageTest.php Updates storage unit tests.
apps/twofactor_backupcodes/tests/Db/BackupCodeMapperTest.php Updates mapper integration tests.
apps/twofactor_backupcodes/lib/Service/BackupCodeStorage.php Uses repository operations.
apps/twofactor_backupcodes/lib/Listener/UserDeleted.php Uses the renamed deletion method.
apps/twofactor_backupcodes/lib/Db/BackupCodeMapper.php Migrates backup codes to Repository.
apps/twofactor_backupcodes/lib/Db/BackupCode.php Converts backup codes to attributed entities.
Suppressed comments (1)

lib/public/ITags.php:57

  • The updated PHP example still uses assignment syntax inside the array (=), so the documented snippet is invalid PHP. Use => for every key/value pair.
	 * 	['id' => 1, 'name' = 'Second tag', 'owner' = 'User B', 'type' => 'tagtype'],

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread lib/public/AppFramework/ORM/Repository.php
Comment thread lib/private/AppFramework/ORM/EntityManager.php
Comment thread lib/public/AppFramework/ORM/Repository.php Outdated
Comment thread lib/private/AppFramework/ORM/PropertyAttributes.php Outdated
Comment thread apps/twofactor_backupcodes/lib/Db/BackupCode.php Outdated
Comment thread lib/public/ITags.php Outdated
Comment thread lib/private/Tags.php Outdated
Comment thread lib/private/AppFramework/ORM/EntityManager.php Outdated
Comment thread lib/private/AppFramework/ORM/EntityInfo.php Outdated
Comment thread lib/public/ITags.php Outdated
Comment thread lib/public/ITags.php Outdated
@CarlSchwan
CarlSchwan force-pushed the carl/attributes-entity-2 branch from 82eec0d to 3ce00e2 Compare August 12, 2026 09:02
Signed-off-by: Carl Schwan <carl@carlschwan.eu>
@CarlSchwan
CarlSchwan force-pushed the carl/attributes-entity-2 branch from 3ce00e2 to 822cb18 Compare August 12, 2026 09:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

3. to review Waiting for reviews AI assisted feature: database Database related DB

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants