Skip to content

[PropertyInfo] Add an extractor to guess if a property is initializable #26997

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

Merged
merged 1 commit into from
Sep 4, 2018

Conversation

dunglas
Copy link
Member

@dunglas dunglas commented Apr 21, 2018

Q A
Branch? master
Bug fix? no
New feature? yes
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets n/a
License MIT
Doc PR symfony/symfony-docs#10319

When dealing with value objects, being able to detect if a property can be initialized using the constructor is a very valuable information. It's mandatory to add a proper value object support in API Platform and in the Serializer component.

See api-platform/core#1749 and api-platform/core#1843 for the related discussions, extended use cases and proof of concepts.

This PR adds a new interface to guess if a property can be initialized through the constructor, and an implementation using the reflection (in ReflectionExtractor).

*/
public function isInitializable(string $class, string $property, array $context = array()): ?bool
{
$this->assertIsString($class);
Copy link
Contributor

Choose a reason for hiding this comment

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

What's the point of this?

Copy link
Member Author

Choose a reason for hiding this comment

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

I added this for consistency with other methods, I'm not sure of the origin intent...

Copy link
Member Author

@dunglas dunglas Apr 22, 2018

Choose a reason for hiding this comment

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

Here is the original intent: #19437

Copy link
Contributor

Choose a reason for hiding this comment

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

Right. So type hints are added now so these checks are redundant

/**
* Is the property initializable?
*/
public function isInitializable(string $class, string $property, array $context = array()): ?bool;
Copy link
Contributor

Choose a reason for hiding this comment

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

What's the use-case for returning null? Also, shouldn't we explicit within the method name that we are talking about the constructor in here? isInitializableViaConstructor or something like that?

Copy link
Contributor

Choose a reason for hiding this comment

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

null means "we don't know"?

Copy link
Member Author

Choose a reason for hiding this comment

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

@teohhanhui is right. It means "this extractor cannot guess", try the next registered in the chain. It's mandatory to keep this behavior for consistency with existing interfaces and to provide an extension point.

Copy link
Member Author

Choose a reason for hiding this comment

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

@sroze I prefer the current name, isInitializableViaConstructor is too verbose and brings nothing much.

Copy link
Contributor

Choose a reason for hiding this comment

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

My 2cts are that I didn't understand what isInitializable meant before reading more about your PR. I can tell you that if I saw this interface I'd think "wait. What is that about?". While the isInitializableViaConstructor clarifies it and is not too verbose.

Copy link
Contributor

Choose a reason for hiding this comment

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

I wouldn't, the PhpDoc that you've put is enough (to me).

Copy link
Contributor

@teohhanhui teohhanhui Jun 30, 2018

Choose a reason for hiding this comment

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

"Property initializable" on its own indeed makes no sense to me. Perhaps ConstructorInitializableExtractorInterface::isPropertyInitializable?

Copy link
Member Author

@dunglas dunglas Jul 3, 2018

Choose a reason for hiding this comment

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

PropertyInitializableViaConstructorExtractorInterface::isInitializable?

Copy link
Contributor

Choose a reason for hiding this comment

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

I guess we could just stick with the current names. Lol...

Copy link
Member Author

@dunglas dunglas Jul 4, 2018

Choose a reason for hiding this comment

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

@sroze @fabpot ok for you to keep the current names?

@nicolas-grekas nicolas-grekas added this to the next milestone Apr 22, 2018
Copy link
Member

@lyrixx lyrixx left a comment

Choose a reason for hiding this comment

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

Looks good to me

if ($property !== $parameter->name) {
continue;
if ($property === $parameter->name) {
return array($this->extractFromReflectionType($parameter->getType()));
}
Copy link
Contributor

Choose a reason for hiding this comment

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

what's the point of this change ? I know it does the same, but with a different style, but then ?

Copy link
Member Author

Choose a reason for hiding this comment

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

Removing 2 lines and making the code more explicit, but yes it's not mandatory.

return null;
}

if ($constructor = $reflectionClass->getConstructor()) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why don't you test if the constructor is instantiable first?

Copy link
Member Author

Choose a reason for hiding this comment

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

Good idea, I'll update the code.

Copy link
Member Author

Choose a reason for hiding this comment

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

done

interface PropertyInitializableExtractorInterface
{
/**
* Is the property initializable?
Copy link
Member

Choose a reason for hiding this comment

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

not sure this is useful :)

Copy link
Member Author

Choose a reason for hiding this comment

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

It's for consistency with other interfaces.

@nicolas-grekas
Copy link
Member

rebase needed (and some comments to address)

@dunglas dunglas force-pushed the propertyinfo-constructor branch from 88b2286 to 17cf6a1 Compare June 30, 2018 08:59
@dunglas
Copy link
Member Author

dunglas commented Jun 30, 2018

rebased and comments addressed

/**
* Is the property initializable?
*/
public function isInitializable(string $class, string $property, array $context = array()): ?bool;
Copy link
Contributor

Choose a reason for hiding this comment

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

My 2cts are that I didn't understand what isInitializable meant before reading more about your PR. I can tell you that if I saw this interface I'd think "wait. What is that about?". While the isInitializableViaConstructor clarifies it and is not too verbose.

@dunglas dunglas force-pushed the propertyinfo-constructor branch from fced167 to 6737e71 Compare July 13, 2018 11:48
@dunglas
Copy link
Member Author

dunglas commented Jul 13, 2018

Rebased, I suggest to keep the current name as there are no consensus on another name.

4.2.0
-----

* added `PropertyInitializableExtractorInterface` to test if a property can be initialized through the constructor and an implementation is `ReflectionExtractor`
Copy link
Member

Choose a reason for hiding this comment

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

if a property can be initialized through the constructor (implemented by ReflectionExtractor)


if ($constructor = $reflectionClass->getConstructor()) {
foreach ($constructor->getParameters() as $parameter) {
if ($property === $parameter->name) {
Copy link
Member

Choose a reason for hiding this comment

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

The fact that the constructor parameter name must match the property one should be documented somewhere.

interface PropertyInitializableExtractorInterface
{
/**
* Is the property initializable?
Copy link
Member

Choose a reason for hiding this comment

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

This is probably where we need more docs about the naming convention.

@fabpot
Copy link
Member

fabpot commented Sep 4, 2018

@dunglas Do you have time to have a look at my comments?

@dunglas dunglas force-pushed the propertyinfo-constructor branch 2 times, most recently from d125f25 to 4a0483d Compare September 4, 2018 11:00
@dunglas
Copy link
Member Author

dunglas commented Sep 4, 2018

@fabpot done

@dunglas
Copy link
Member Author

dunglas commented Sep 4, 2018

CI errors look unrelated.

@fabpot fabpot force-pushed the propertyinfo-constructor branch from a8fb40e to 9d2ab9e Compare September 4, 2018 15:17
@fabpot
Copy link
Member

fabpot commented Sep 4, 2018

Thank you @dunglas.

@fabpot fabpot merged commit 9d2ab9e into symfony:master Sep 4, 2018
fabpot added a commit that referenced this pull request Sep 4, 2018
… is initializable (dunglas)

This PR was squashed before being merged into the 4.2-dev branch (closes #26997).

Discussion
----------

[PropertyInfo] Add an extractor to guess if a property is initializable

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no     <!-- see https://symfony.com/bc -->
| Deprecations? | no <!-- don't forget to update UPGRADE-*.md and src/**/CHANGELOG.md files -->
| Tests pass?   | yes    <!-- please add some, will be required by reviewers -->
| Fixed tickets | n/a   <!-- #-prefixed issue number(s), if any -->
| License       | MIT
| Doc PR        | todo

When dealing with value objects, being able to detect if a property can be initialized using the constructor is a very valuable information. It's mandatory to add a proper value object support in API Platform and in the Serializer component.

See api-platform/core#1749 and api-platform/core#1843 for the related discussions, extended use cases and proof of concepts.

This PR adds a new interface to guess if a property can be initialized through the constructor, and an implementation using the reflection (in `ReflectionExtractor`).

Commits
-------

9d2ab9e [PropertyInfo] Add an extractor to guess if a property is initializable
@nicolas-grekas
Copy link
Member

nicolas-grekas commented Sep 5, 2018

This PR breaks the CI by breaking BC somehow, see deps=high failures (which mean that 4.1 is broken when using PropertyInfo master)
@dunglas could you have a look please?
(note that we should be careful when merging PRs which have failures)

@nicolas-grekas
Copy link
Member

nicolas-grekas commented Sep 5, 2018

(fixed in 5557e38, we'll have to deal with this kind of BC breaks now that we put DI passes in components and not in bundles anymore.)

@dunglas dunglas deleted the propertyinfo-constructor branch September 5, 2018 14:23
@dunglas
Copy link
Member Author

dunglas commented Sep 5, 2018

Thanks for the fix @nicolas-grekas

@javiereguiluz
Copy link
Member

I've created symfony/symfony-docs#10272 to document this new feature. Please, don't forget to create a doc issue for every new feature.

Kévin, if you don't have time to contribute the docs, we'll need some code examples of using this feature in action. Thanks!

javiereguiluz added a commit to symfony/symfony-docs that referenced this pull request Sep 11, 2018
…s initializable (dunglas, javiereguiluz)

This PR was merged into the master branch.

Discussion
----------

[PropertyInfo] Add an extractor to guess if a property is initializable

symfony/symfony#26997
symfony/symfony#24571
Closes #10272.

Commits
-------

8415f96 Minor tweaks
eebca4a RST
f7ed144 [PropertyInfo] Add an extractor to guess if a property is initializable
@nicolas-grekas nicolas-grekas modified the milestones: next, 4.2 Nov 1, 2018
This was referenced Nov 3, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.