Permalink
Browse files

Prototype for a proxy extension that avoids loads when calling for a …

…getter that is named after an identifier.
  • Loading branch information...
1 parent 85fb1a3 commit bc4e14a99f26338e83c1e643293074c064bc5bdd @beberlei beberlei committed May 20, 2011
@@ -209,6 +209,11 @@ private function _generateMethods(ClassMetadata $class)
$methods .= $parameterString . ')';
$methods .= PHP_EOL . ' {' . PHP_EOL;
+ if ($this->isShortIdentifierGetter($method, $class)) {
+ $methods .= ' if ($this->__isInitialized__ === false) {' . PHP_EOL;
+ $methods .= ' return $this->_identifier["' . lcfirst(substr($method->getName(), 3)) . '"];' . PHP_EOL;
+ $methods .= ' }' . PHP_EOL;
+ }
$methods .= ' $this->__load();' . PHP_EOL;
@geoffrey-brier

geoffrey-brier Oct 3, 2012

I don't know why but these lines of code prevent my users being manually authenticated: the User->getId method always return null so when I set a specific UsernamePasswordToken, it fails (the token is destroyed) and my user is not authenticated.
This was not the case in 2.2.x, any ideas?

@stof

stof Oct 3, 2012

Member

which line are you talking about ? The one you commented on is also there in 2.2.x

@egeloen

egeloen Oct 3, 2012

Contributor

He talks about the added lines. Can you explain the goal? In our case, the proxy is not initialized and $this->_identifier is null, so the proxy returns null instead of the value.

@stof

stof Oct 4, 2012

Member

the goal is to avoid initializing the proxy when the only thing you care about is the id (to generate an url for instance) as it is already available.

How could you have an uninitialized proxy without identifier ?

@egeloen

egeloen Oct 4, 2012

Contributor

We have two User classes representing a Symfony & a Facebook user. These two classes are linked with a OneToOne bidirectionnal association with the owning side (inversedBy) on the Facebook user class.

When I fetch a Facebook user by id and lazy load my user with this code:

$facebookUser = $this->getDoctrine()
   ->getRepository('AcmeFacebookBundle:User')
   ->findOneBy(array('facebookId' => $authResponse->id));

$symfonyUser = $facebookUser->getSymfonyUser();

At this moment, the Symfony user is not initialized and the identifier is null.

@stof

stof Oct 4, 2012

Member

$facebookUser->getSymfonyUser(); never initialized a proxy. A proxy is initialized only when you call a method on it (and as of Doctrine 2.2, it is any method except the getter for the id).

However, I don't see how the identifier could be missing in the proxy object here (except if your mapping is invalid) so the getter for the id will continue working.

@egeloen

egeloen Oct 4, 2012

Contributor

Thanks for your answer. There are really no mismatch in my mapping:

@ORM\OneToOne(
   targetEntity = "Acme\UserBundle\Entity\User",
   inversedBy = "facebook"
)

@ORM\OneToOne(
   targetEntity = "Acme\FacebookBundle\Entity\User",
   mappedBy = "user"
)

I don't understand why the identifier is null.

$methods .= ' return parent::' . $method->getName() . '(' . $argumentString . ');';
$methods .= PHP_EOL . ' }' . PHP_EOL;
@@ -219,6 +224,21 @@ private function _generateMethods(ClassMetadata $class)
}
/**
+ * @param ReflectionMethod $method
+ * @param ClassMetadata $class
+ * @return bool
+ */
+ private function isShortIdentifierGetter($method, $class)
+ {
+ return (
+ $method->getNumberOfParameters() == 0 &&
+ substr($method->getName(), 0, 3) == "get" &&
+ in_array(lcfirst(substr($method->getName(), 3)), $class->identifier, true) &&
+ (($method->getEndLine() - $method->getStartLine()) <= 4)
+ );
+ }
+
+ /**
* Generates the code for the __sleep method for a proxy class.
*
* @param $class
@@ -78,7 +78,7 @@ public function testGetReferenceWithPostLoadEventIsDelayedUntilProxyTrigger()
$reference = $this->_em->getReference('Doctrine\Tests\ORM\Functional\LifecycleCallbackTestEntity', $id);
$this->assertFalse($reference->postLoadCallbackInvoked);
- $reference->getId(); // trigger proxy load
+ $reference->getValue(); // trigger proxy load
$this->assertTrue($reference->postLoadCallbackInvoked);
}
@@ -210,6 +210,10 @@ public function getId() {
return $this->id;
}
+ public function getValue() {
+ return $this->value;
+ }
+
/** @PrePersist */
public function doStuffOnPrePersist() {
$this->prePersistCallbackInvoked = true;
@@ -31,8 +31,8 @@ public function testCallUnserializedProxyMethods()
$entity = $this->_em->getReference('Doctrine\Tests\ORM\Functional\Ticket\DDC381Entity', $persistedId);
- // explicitly load proxy
- $id = $entity->getId();
+ // explicitly load proxy (getId() does not trigger reload of proxy)
+ $id = $entity->getOtherMethod();
$data = serialize($entity);
$entity = unserialize($data);
@@ -55,4 +55,9 @@ public function getId()
{
return $this->id;
}
+
+ public function getOtherMethod()
+ {
+
+ }
}

0 comments on commit bc4e14a

Please sign in to comment.