-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[PropertyAccess] RFC: PropertyPath options #5013
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 our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
maybe |
i dislike mapping arbitrary strings to methods. path or path parts should be collection keys. if registerXy("author.name", function validate($name) { ... }); // called on ->set("author.name", "...") get("tags") |
@cryptocompress the goal of the property path is to map to getters and setters, not to force the user to implement a get and a set method to handle it (the Form component should not force you to implement special methods in the underlying object you want to use) |
for generic get/set there is no need for a path at all... what am i missing? |
@cryptocompress why do you mean by generic get/set ? |
"the goal of the property path is to map to getters and setters" in the "article.tags" example i may want to normalize tags in setter. so i have to register my normalizeTag function somehow. otherwise only a "generic" setter is called with value and optional path as arguments. i dont understand the whole complexity. my only point is: do not map strings to something else. let them be strings. |
@cryptocompress the complexity is that the property path is not only about the property of the object (which would be easier) but about object graphs (you can access a property of a nested object) |
and getters and setters are a generic convention whereas a get and set methods accepting a method name are not. |
Do we have a syntax for accessing by reflection already? |
I prefer the inline syntax btw. Maybe path also needs to become an object. |
@stof "methods accepting a method name" would be the other way around. a method converted to string. let methods be methods and strings strings. |
@cryptocompress the property path is about configuring which method should be called to access the values |
then some sort of xpath would be powerful: Alternative 2 can't see singular/plural problem though... take as is: authors -> getAuthors |
am getAuthors is plural, so I'd expect that method to return some kind of collection either in form of an object or a plain array. |
There seems to be some confusion about what
PropertyPath is a bit more flexible than that, as it also supports public properties, magic getters etc. The above mentioned problems arise when we write into paths. Currently, when writing into the above path,
This is usually sufficient, but some people also want setter methods for the ancestors in the path to be called, e.g.
|
I prefer the Alternative 1. Alternative 2 is to overhead. |
I think solution 2 is more readable. It has the drawback of beeing harder to create programmatically (which is rarely needed I guess). For such cases, the PropertyPathBuilder should be used I guess. |
alternative #2 is more readable with few options but when number of options will raise it will become one big mess so i would prefer alternative 1. |
@Sorien: FYI I don't expect these options to be necessary in many occasions. I also don't expect the number of options to raise, as PropertyPath needs to remain as small and simple as possible. |
@bschussek Can you list the current (and probably the only) settings we will have? So that we can discuss the grammar if option 1 is chosen. |
Options 1 has the disadvantage of beeing redundant, i.e. you basically need to repeat the property path in the options array again (if you need it). And the property path is just some plain text, readable representation. Why not making use of that for the options, too? Esp. since they are highly correlated. |
@fabpot The three settings included in the above proposal are all that we have:
|
@bschussek if we add new options is it possible to have one new added:
|
+1 for alternative 1 because you could add future options without rewriting the syntax. Who want this ? Imagine the face of a dev looking at a form with this propertyPath for the first time. |
@jaugustin Hopefully this example will never become reality. I would like to keep the options few and for edge cases only. Another limitation of solution 1 just came to mind. In the Form component, the property path is guessed based on the context if it is not explicitely given. I.e.
Suppose he configures this path with solution 1:
If the context changes (i.e. the system does not guess
I don't think this is more understandable than
|
@bschussek In the second case you have to specify the |
That's what I was saying with
Do you prefer that version in terms of readabilitly? |
I prefer the array of options for readability, and for the kill the magic philosophy of sf 2 ;) |
or as @Tobion said, PropertyPathBuilder could be used, for example: <?php
use PropertyPathBuilder as Builder;
(new Builder)
->appendProperty('artikel', Builder::BY_VALUE) // second parameter - array or int
->appendProperty('stichwörter', Builder::USE_ADDERS, 'stichwort'); |
@Dattaya PropertyPathBuilder is just a helper for constructing property paths. Everything added by this helper should be contained in the string representation of the path. Thus we end up with a string containing the options anyway. We could also store the options internally in PropertyPath, but then one has to use PropertyPathBuilder to build property paths with options, which I don't like. |
I see what you mean now, thanks for the clarification. It also makes it more clear why you would want to use annotations to define how this serialization would happen because it would be usable in multiple contexts. I understand that if you were trying to use this serializer for multiple use cases (REST api and forms for example) that you would want to avoid duplicating the logic of how archived: true|false is transformed onto a model. I'm concerned that this is not a good enough argument for disallowing people the flexibility of controlling how form data is bound via code for the following reasons
|
I agree with @bvleur that the enabled/disabler can simply be implemented in user code as he showed. So there is no urgent need to support that in core. |
@bvleur I agree! @benglass' original request was to be able to map the But then again, does it matter? Probably not. |
Crashed on this one. A model property may be related to a language-specific domain. The singularization rules produce really funky results which totally break the readbility and coehrence of the model code. Any help like symfony/symfony-docs#1227 to set custom or language-specific rules would be much appreciated. |
@webmozart What is the status of this? I really like the idea of the model-specific configuration through annotations, XML, YAML or PHP code. This could fix a lot of issues at once (custom getter/setter methods, custom singularizing, by value/reference problems, array access, etc.) and would be a really nice feature to be added to Symfony 3.0. The approach allows BC and is future-proof, as more options can be added later. Could we agree to the syntax and move this forward? |
@wouterj I'd like to move this forward as there is a lot potential in this approach. @webmozart seems to be missing (or just busy). So, is there anyone from the Symfony team willing to take the lead on this? How can I help? |
Thank you! I'll give it a try, it's an excellent opportunity to dig into the Symfony internals. As I stated before, I think this feature can be rather useful to many people. |
@webmozart Can you check PR #18016 when you have some spare time? I've implemented custom getters/setters/adders/removers through property annotations instead method ones. There is still much work to do (i.e. supporting YAML/XML/PHP metadata), but I think is a good starting point. |
…rface and implementation on reflection (joelwurtz, Korbeil) This PR was merged into the 5.1-dev branch. Discussion ---------- [PropertyInfo] Add accessor and mutator extractor interface and implementation on reflection | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #30248, partially: #22190, #18016, #5013, #9336, #5219, | License | MIT | Doc PR | TODO This PR brings accessor / mutator extraction on the PropertyInfo component, There is no link to existing code, as IMO it should be in another PR as this will add a dependency on property access to the property info component and not sure this is something wanted (although, it will reduce a lot of code base on the property access component as a lot of code seems to be duplicated) Code is extracted from #30248 also there is some new features (that can be removed if not wanted) * Allow extracting private accessor / mutator (will do a new PR that improve private extraction on reflection latter) * Allow extracting static accessor / mutators * Allow extracting constructor mutators Current implementation try to be as close as the PropertyAccess implementation and i did not reuse some methods already available in the class as there is some differences in implementation, but maybe it will be a good time to make this consistent (Looking forward to your input) ? Things that should be done in a new PR: * Linking property info to property access to remove a lot of duplicate code * Add a new system that allow adding Virtual Property based on this extractor Commits ------- 0a92dab Rebase, fix tests, review & update CHANGELOG fc25086 [PropertyInfo] Add accessor and mutator extractor interface and implementation on reflection
Thank you for this issue. |
Just a quick reminder to make a comment on this. If I don't hear anything I'll close this. |
Hey, I didn't hear anything so I'm going to close it. Feel free to comment if this is still relevant, I can always reopen! |
The
PropertyPath
class currently makes a list of assumptions:1. Objects are treated by reference
When the path
author.name
is modified, the following methods are called:Note that
setAuthor()
is not called.2. Adders and removers are used if they exist
If a collection is written into the path
tags
and the methodsaddTag()
andremoveTag()
exist, these are used to merge into the old collection instead of accessing the old collection directly via itsArrayAccess
interface. The following methods are called:3. Adders and removers follow English singularization rules
If a property path is called
children
, the guessed adders and removers areaddChild()
andremoveChild()
.Limitations
The above assumptions do not hold in all applications:
So, these assumptions should be made configurable. The challenge is how to build this API in an intuitive way.
Alternative 1: Option arrays
The first alternative is to pass the options in an array separately from the property path. For example:
Alternative 2: Path flags
The second alternative is to build the configuration options into the path:
Alternative 3: Your suggestions
Do you have any other ideas? What approach do you prefer?
The text was updated successfully, but these errors were encountered: