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

[DI][Config] Add & use ReflectionClassResource#21419

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

Merged

Conversation

nicolas-grekas
Copy link
Member

@nicolas-grekasnicolas-grekas commentedJan 26, 2017
edited
Loading

QA
Branch?master
Bug fix?no
New feature?yes
BC breaks?no
Deprecations?yes
Tests pass?yes
Fixed tickets#21079
LicenseMIT
Doc PR-

With new changes comming to 3.3, we need a more generic reflection tracking logic than the one already managed by the autowiring subsystem.

This PR adds a new ReflectionClassResource in the Config component, and a new ContainerBuilder::getReflectionClass() method in the DI one (for fetching+tracking reflection-related info).

ReflectionClassResource tracks changes to any public or protected properties/method.

PR updated and ready, best viewedignoring whitespaces.

changelog:

  • addedReflectionClassResource class
  • added second$exists constructor argument toClassExistenceResource - with a special mode that prevents fatal errors from happening when some parent class is broken (logic generalized from AutowiringPass)
  • madeClassExistenceResource also work with interfaces and traits
  • addedContainerBuilder::getReflectionClass() for retrieving and tracking reflection class info
  • deprecatedContainerBuilder::getClassResource(), useContainerBuilder::getReflectionClass() orContainerBuilder::addObjectResource() instead

chalasr reacted with thumbs up emoji

unlink($tmp);
$this->assertFalse($res->isFresh($now), '->isFresh() returns false if the resource does not exist');
}
Copy link
Member

Choose a reason for hiding this comment

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

is there a way to test the handling of the hash ?

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

I split the logic to allow for testing signature mutations - tests added

@@ -459,6 +424,9 @@ private function addServiceToAmbiguousType($id, $type)
$this->ambiguousServiceTypes[$type][] = $id;
}

/**
* @deprecated since version 3.3, to be removed in 4.0.
Copy link
Member

Choose a reason for hiding this comment

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

deprecating a private method does not make sense. Either we don't use it anymore, and we should remove it already, or we use it in deprecated method and it will become dead code when removing the other method (which is catched by IDEs and any static analysis tool, for instance SensioLabsInsight)

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

It's just a friendly reminder for the one who will cleanup the code preparing 4.0

*
* @param string $class
*
* @return \ReflectionClass|false
Copy link
Member

Choose a reason for hiding this comment

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

Can we use\ReflectionClass|null instead ? It would be cleaner (PHP 7.1 has nullable types, not falsable types)

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

would only add boilerplate (isset(false) is used in the code)

Copy link
Member

Choose a reason for hiding this comment

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

Well, if this was a private API, I would be OK with this argument about simplifying the internal implementation.
But this is a public API.

Copy link
Member

Choose a reason for hiding this comment

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

@nicolas-grekas I think we need to try to not use mixed return args in our public APIs (anymore). With\ReflectionClass|null, we could add a native PHP return type in 7.1, but\ReflectionClass|false, we cannot.

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

done

@@ -20,7 +20,7 @@
},
"require-dev": {
"symfony/yaml": "~3.2",
"symfony/config": "~2.8|~3.0",
"symfony/config": "~3.3",
Copy link
Member

Choose a reason for hiding this comment

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

should we add a conflict rule to avoid issues when getting a lower version for people using standalone components ?

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

good idea, added

*/
public static function createResourceForClass(\ReflectionClass $reflectionClass)
{
@trigger_error('The '.__METHOD__.'() method is deprecated since version 3.3 and will be removed in 4.0. Use ContainerBuilder::getReflectionClass() instead.', E_USER_DEPRECATED);
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 if it's a good idea or not. The current implementation will more efficient because some changes doesn't impact autowiring (like properties changes).

Copy link
MemberAuthor

@nicolas-grekasnicolas-grekasJan 26, 2017
edited
Loading

Choose a reason for hiding this comment

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

In practice, I don't think there are that more situations where the new code would invalidate where the existing wouldn't. And I see the benefit for having only one place where this tracking logic is implemented. So I think it's in fact a desirable thing yes. Allows better aggregation of resources across passes also - and maybe faster checking (with simpler/optimized logic.)

@dunglas
Copy link
Member

👍

@nicolas-grekasnicolas-grekasforce-pushed thedi-reflection-resource branch 8 times, most recently fromdfcd57d tod287508CompareJanuary 27, 2017 17:38
@nicolas-grekasnicolas-grekas mentioned this pull requestJan 28, 2017
5 tasks
@nicolas-grekasnicolas-grekasforce-pushed thedi-reflection-resource branch 2 times, most recently from061a58a to86836f9CompareJanuary 28, 2017 10:14
@nicolas-grekas
Copy link
MemberAuthor

nicolas-grekas commentedJan 28, 2017
edited
Loading

addObjectResource andReflectionClassResource now track mtimes of parents, traits and interfaces.

Hash computation, file and class existence is now done lazily - ie after the resources are deduplicated.

And to prevent checking the hash again when it was found valid in a previous run, files are "touched" when needed.

@nicolas-grekas
Copy link
MemberAuthor

Rebased
ping@stof :)

@nicolas-grekasnicolas-grekasforce-pushed thedi-reflection-resource branch 7 times, most recently fromb267a7f toe251e19CompareFebruary 1, 2017 14:37
if (is_subclass_of($class, 'Symfony\Component\Translation\TranslatorInterface') && is_subclass_of($class, 'Symfony\Component\Translation\TranslatorBagInterface')) {
if (!$r = $container->getReflectionClass($class)) {
throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $translatorAlias));
} elseif ($r->isSubclassOf(TranslatorInterface::class) && $r->isSubclassOf(TranslatorBagInterface::class)) {
Copy link
Member

Choose a reason for hiding this comment

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

justif here, as the previous case is throwing

*/
public function __construct($resource)
public function __construct($resource, $exists = null)
Copy link
Member

Choose a reason for hiding this comment

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

the name is confusing here. It is not a value telling whether the class exists (which is what I thought when seeing the param name, compared to the level), but a checking level

{
$this->resource = $resource;
$this->exists = class_exists($resource);
if (null !== $exists) {
$this->exists = (int) $exists;
Copy link
Member

Choose a reason for hiding this comment

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

I would rename the property, as this isnot storing whether the class exists (unlike previously)

yield $class->getDocComment().$class->getModifiers();

if ($class->isTrait()) {
yield print_r(class_uses($class->name), true);
Copy link
Member

Choose a reason for hiding this comment

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

shouldn't this be always included ?

Copy link
MemberAuthor

@nicolas-grekasnicolas-grekasFeb 1, 2017
edited
Loading

Choose a reason for hiding this comment

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

no need: traits are not directly part of the signature - the methods they provide will be seen as any other methods, thus tracked


public function testExistsKo()
{
spl_autoload_register(function ($class) use (&$loadedClass) { $loadedClass = $class; });
Copy link
Member

Choose a reason for hiding this comment

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

you should unregister it at the end of the test (even when it fails)

@@ -30,13 +32,17 @@ public function process(ContainerBuilder $container)
$definition = $container->getDefinition($id);

if ($definition->isAbstract()) {
throw new \InvalidArgumentException(sprintf('The service "%s" tagged "console.command" must not be abstract.', $id));
continue;
Copy link
Member

Choose a reason for hiding this comment

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

why changing this ?

// ensure the next checks won't require a hash computation again,
// use a local mtime cache so that the current process still sees
// the original mtime and validates the hash for child classes
@touch($file, $timestamp);
Copy link
Member

Choose a reason for hiding this comment

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

this might break other systems relying on the real mtime of the file because they are concerned about more things than the ones involved in the Symfony hash

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

true, removed

@@ -251,7 +253,32 @@ public function setResources(array $resources)
public function addObjectResource($object)
{
if ($this->trackResources) {
$this->addClassResource(new \ReflectionClass($object));
if (is_object($object)) {
Copy link
Member

Choose a reason for hiding this comment

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

if it also accepts class names, the phpdoc must be updated

*/
public function addClassResource(\ReflectionClass $class)
{
if (!$this->trackResources) {
return $this;
@trigger_error('The '.__METHOD__.'() mehtod is deprecated since version 3.3 and will be removed in 4.0. Use the addObjectResource() or the getReflectionClass() method instead.', E_USER_DEPRECATED);
Copy link
Member

Choose a reason for hiding this comment

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

typo

}

throw new InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, $interface));
if (!$r = $container->getReflectionClass($class)) {
Copy link
Member

Choose a reason for hiding this comment

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

We actually need to invalidate the cache when the implementation of the class changes here, as it can change the list of events (btw, it means we are missing a ClassResource today)

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

good catch, fixed

@nicolas-grekasnicolas-grekasforce-pushed thedi-reflection-resource branch 2 times, most recently from3e78969 to0db525aCompareFebruary 1, 2017 18:36
@nicolas-grekas
Copy link
MemberAuthor

@stof comments addressed

if ($this->trackResources) {
if (!$classReflector) {
$this->addResource($resource ?: new ClassExistenceResource($class, ClassExistenceResource::EXISTS_KO));
} elseif (!$classReflector->isInternal()) {
Copy link
Member

Choose a reason for hiding this comment

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

why is there this check. Should we replace it with a ClassExistenceResource at least for internal classes if there is no way to check for details ?
and if the hash computation does not work for internal classes, what happens for classes extending an internal one ?

Copy link
MemberAuthor

@nicolas-grekasnicolas-grekasFeb 1, 2017
edited
Loading

Choose a reason for hiding this comment

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

We can track details for internal classes, but this makes no sense: if you switch your version/extension of PHP, the container is not invalidated. Tracking here would mean checking the signature every single time.

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

See#21505 for internal classes

foreach ($this->classResources as $r) {
$this->container->addClassResource($r);
}
$this->classResources = array();
Copy link
Member

Choose a reason for hiding this comment

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

do we actually have this duplicate code in older branches, or was it all added in 3.3 only ?

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

3.3 only

*
* @final
*/
public function fileExists($path, $trackContents = true)
Copy link
MemberAuthor

Choose a reason for hiding this comment

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

moved as is above with other resource-related methods

@fabpot
Copy link
Member

Thank you@nicolas-grekas.

@fabpotfabpot merged commit37e4493 intosymfony:masterFeb 2, 2017
fabpot added a commit that referenced this pull requestFeb 2, 2017
…s-grekas)This PR was merged into the 3.3-dev branch.Discussion----------[DI][Config] Add & use ReflectionClassResource| Q             | A| ------------- | ---| Branch?       | master| Bug fix?      | no| New feature?  | yes| BC breaks?    | no| Deprecations? | yes| Tests pass?   | yes| Fixed tickets |#21079| License       | MIT| Doc PR        | -With new changes comming to 3.3, we need a more generic reflection tracking logic than the one already managed by the autowiring subsystem.This PR adds a new ReflectionClassResource in the Config component, and a new ContainerBuilder::getReflectionClass() method in the DI one (for fetching+tracking reflection-related info).ReflectionClassResource tracks changes to any public or protected properties/method.PR updated and ready, best viewed [ignoring whitespaces](https://github.com/symfony/symfony/pull/21419/files?w=1).changelog:* added `ReflectionClassResource` class* added second `$exists` constructor argument to `ClassExistenceResource` - with a special mode that prevents fatal errors from happening when some parent class is broken (logic generalized from AutowiringPass)* made `ClassExistenceResource` also work with interfaces and traits* added `ContainerBuilder::getReflectionClass()` for retrieving and tracking reflection class info* deprecated `ContainerBuilder::getClassResource()`, use `ContainerBuilder::getReflectionClass()` or `ContainerBuilder::addObjectResource()` insteadCommits-------37e4493 [DI][Config] Add & use ReflectionClassResource
@@ -22,7 +22,7 @@
"symfony/dependency-injection": "~3.3",
"symfony/config": "~3.3",
"symfony/event-dispatcher": "~3.3",
"symfony/http-foundation": "~3.1",
"symfony/http-foundation": "~3.3",
Copy link
Member

Choose a reason for hiding this comment

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

What is the reason for this change?

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

Transitivity and composer bug, this doesn't change the result, it only helps composer

Copy link
Member

Choose a reason for hiding this comment

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

thanks, I was just wondering as the code changes didn't indicate any need for this change

@nicolas-grekasnicolas-grekas deleted the di-reflection-resource branchFebruary 3, 2017 12:23
sstok added a commit to rollerworks-graveyard/breadcrumbs-bundle that referenced this pull requestFeb 4, 2017
This PR was merged into the 1.0-dev branch.Discussion----------| Q             | A| ------------- | ---| Bug fix?      | yes| New feature?  | no| BC breaks?    | no| Deprecations? | no| Tests pass?   | yes| Fixed tickets | | License       | MIT`ContainerBuilder::addClassResource()` is deprecated.symfony/symfony#21419Commits-------de72f26 Fix Symfony 4.0 compatibility
fabpot added a commit that referenced this pull requestFeb 16, 2017
…sn't exist (chalasr)This PR was merged into the 3.3-dev branch.Discussion----------[DI] Don't try to instantiate reflection class if it doesn't exist| Q             | A| ------------- | ---| Branch?       | master| Tests pass?   | yes| Fixed tickets | n/a| License       | MIT| Doc PR        | n/aIntroduced in#21419 so master only.It breaks on bundles that ~~do not use the convention for naming their `Configuration`~~ do not have configuration, e.g. SecurityBundle's FirewallEntryPointExtension for which tests are actually broken (see travis).Commits-------f9b917a [DI] Don't instantiate unexisting reflection class
@fabpotfabpot mentioned this pull requestMay 1, 2017
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Reviewers

@fabpotfabpotfabpot left review comments

@dunglasdunglasdunglas left review comments

@stofstofstof requested changes

@xabbuhxabbuhxabbuh left review comments

Assignees
No one assigned
Projects
None yet
Milestone
3.3
Development

Successfully merging this pull request may close these issues.

6 participants
@nicolas-grekas@dunglas@fabpot@stof@xabbuh@carsonbot

[8]ページ先頭

©2009-2025 Movatter.jp