Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[FrameworkBundle][PropertyInfo] Allow defining accessors and mutators via an attribute#59529

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
HypeMC wants to merge1 commit intosymfony:7.4
base:7.4
Choose a base branch
Loading
fromHypeMC:with-accessors-attribute

Conversation

HypeMC
Copy link
Member

@HypeMCHypeMC commentedJan 16, 2025
edited
Loading

QA
Branch?7.3
Bug fix?no
New feature?yes
Deprecations?no
Issues-
LicenseMIT

A continuation/revival of#38515,contains#59497 and#59528

The idea of this PR is to allow defining accessors and mutators via a#[WithAccessors] attribute, eg:

class Foo{    #[WithAccessors(getter:'giveProp', setter:'receiveProp', adder:'pushProp', remover:'popProp')]privatearray$prop;publicfunctiongiveProp():string {}publicfunctionreceiveProp(string$prop):void {}publicfunctionpushProp(string$prop):void {}publicfunctionpopProp(string$prop):void {}}

I haven't added YAML or XML support yet, but the foundation is in place, so it can easily be added in a future PR if needed.

@carsonbotcarsonbot added this to the7.3 milestoneJan 16, 2025
@carsonbotcarsonbot changed the title[PropertyInfo][FrameworkBundle] Allow defining accessors and mutators via an attribute[FrameworkBundle][PropertyInfo] Allow defining accessors and mutators via an attributeJan 16, 2025
$allowGetterSetter = $context['enable_getter_setter_extraction'] ?? false;
$magicMethods = $context['enable_magic_methods_extraction'] ?? $this->magicMethodsFlags;
$allowMagicCall = (bool) ($magicMethods & self::ALLOW_MAGIC_CALL);
$allowMagicSet = (bool) ($magicMethods & self::ALLOW_MAGIC_SET);
$allowConstruct = $context['enable_constructor_extraction'] ?? $this->enableConstructorExtraction;
$allowAdderRemover = $context['enable_adder_remover_extraction'] ?? true;
Copy link
MemberAuthor

Choose a reason for hiding this comment

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

Needed earlier


$camelized = $this->camelize($property);
Copy link
MemberAuthor

@HypeMCHypeMCJan 16, 2025
edited
Loading

Choose a reason for hiding this comment

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

No point in getting the camelized version if the info can be extracted from the constructor. Moved it to when it's actually needed.

$constructor = $reflClass->getConstructor();
$singulars = $this->inflector->singularize($camelized);
Copy link
MemberAuthor

Choose a reason for hiding this comment

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

This was only used infindAdderAndRemover(), so I moved it there.

$mutator = new PropertyWriteInfo(PropertyWriteInfo::TYPE_ADDER_AND_REMOVER);
$mutator->setAdderInfo(new PropertyWriteInfo(PropertyWriteInfo::TYPE_METHOD, $adderAccessName, $this->getWriteVisibilityForMethod($adderMethod), $adderMethod->isStatic()));
$mutator->setRemoverInfo(new PropertyWriteInfo(PropertyWriteInfo::TYPE_METHOD, $removerAccessName, $this->getWriteVisibilityForMethod($removerMethod), $removerMethod->isStatic()));
if (null === $adderAccessName || null === $removerAccessName) {
Copy link
MemberAuthor

Choose a reason for hiding this comment

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

The$adderAccessName and$removerAccessName have been defined in the metadata.

@HypeMCHypeMCforce-pushed thewith-accessors-attribute branch 3 times, most recently from8aec093 tod54d95aCompareJanuary 17, 2025 12:57
->set('property_info.mapping.class_metadata_factory', ClassMetadataFactory::class)
->args([service('property_info.mapping.attribute_loader')])

->alias(ClassMetadataFactoryInterface::class, 'property_info.mapping.class_metadata_factory')

Choose a reason for hiding this comment

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

do you ancitipate a use case for autowiring this in an app? if not we could remove the alias

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

@HypeMCHypeMCforce-pushed thewith-accessors-attribute branch fromd54d95a toe55a729CompareJanuary 17, 2025 13:29
Copy link
Member

@nicolas-grekasnicolas-grekas left a comment

Choose a reason for hiding this comment

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

I'm wondering about the added metadata factory infrastructure. Do we really need to provide an API for this? I'm not sure it's a useful extensibility point.
Wouldn't the PR be way simpler without? What's the real world use case of these interfaces if you think we should add them?

->set('property_info.mapping.class_metadata_factory', ClassMetadataFactory::class)
->args([service('property_info.mapping.attribute_loader')])

// Cache

Choose a reason for hiding this comment

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

captain obvious ;) let's remove these

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

Done :D

public ?string $adder = null,
public ?string $remover = null,
) {
if (null === $this->getter && null === $this->setter && null === $this->adder && null === $this->remover) {

Choose a reason for hiding this comment

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

Suggested change
if (null ===$this->getter&&null ===$this->setter&&null ===$this->adder&&null ===$this->remover) {
if (!($this->getter||$this->setter||$this->adder||$this->remover)) {

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

Done

if (null === $this->getter && null === $this->setter && null === $this->adder && null === $this->remover) {
throw new LogicException('You need to have at least one method name set.');
}
if (null === $this->adder xor null === $this->remover) {

Choose a reason for hiding this comment

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

Suggested change
if (null ===$this->adderxornull ===$this->remover) {
if ($this->adderxor$this->remover) {

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

Done

{
$propertyMetadata = $this->getClassMetadata($reflClass->getName())?->getPropertyMetadataFor($property);
if ((null !== $addMethod = $propertyMetadata?->adder) && (null !== $removeMethod = $propertyMetadata?->remover)) {

Choose a reason for hiding this comment

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

for readability (to me at least), there are many cases where checks could be simplified like this:

Suggested change
if ((null !==$addMethod =$propertyMetadata?->adder) && (null !==$removeMethod =$propertyMetadata?->remover)) {
if (($addMethod =$propertyMetadata?->adder) && ($removeMethod =$propertyMetadata?->remover)) {

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

Done

}

if ($invalidMethods) {
throw new MappingException(\sprintf('The class "%s" does not have the following methods: "%s".', $refClass->name, implode('", "', $invalidMethods)), $refClass->name, $invalidMethods);

Choose a reason for hiding this comment

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

"Check its #[WithAccessors] attributes."

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

Done

@HypeMCHypeMCforce-pushed thewith-accessors-attribute branch frome55a729 tobb0f56dCompareFebruary 2, 2025 23:47
@HypeMC
Copy link
MemberAuthor

I'm wondering about the added metadata factory infrastructure. Do we really need to provide an API for this? I'm not sure it's a useful extensibility point. Wouldn't the PR be way simpler without? What's the real world use case of these interfaces if you think we should add them?

@nicolas-grekas I think it really depends on whether XML and/or YAML support should or will be added. If supporting multiple formats is desired, then the current infrastructure makes sense to me. Otherwise, I'd simplify it by keeping only an attribute loader, possibly with a cached loader.

Personally, I never use XML/YAML for any kind of mapping (validator, serializer, etc.), so I'd be fine with removing it.

@fabpotfabpot modified the milestones:7.3,7.4May 26, 2025
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Reviewers

@nicolas-grekasnicolas-grekasnicolas-grekas left review comments

@mtarldmtarldmtarld left review comments

@dunglasdunglasAwaiting requested review from dunglasdunglas is a code owner

Assignees
No one assigned
Projects
None yet
Milestone
7.4
Development

Successfully merging this pull request may close these issues.

5 participants
@HypeMC@nicolas-grekas@mtarld@fabpot@carsonbot

[8]ページ先頭

©2009-2025 Movatter.jp