feature #19137 [Serializer] Allow to use easily static constructors (Ener-Getick)

This PR was merged into the 3.2-dev branch.

Discussion
----------

[Serializer] Allow to use easily static constructors

| Q             | A
| ------------- | ---
| Branch?       | "master"
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | https://github.com/symfony/symfony/pull/19027#issuecomment-225527475
| License       | MIT
| Doc PR        | -

This PR allows to simply use static constructors to instantiate objects with the serializer by extending the default normalizers.

Commits
-------

9be6484 [Serializer] Allow to use easily static constructors
This commit is contained in:
Fabien Potencier 2016-06-29 07:52:42 +02:00
commit 4a0be68dd4
4 changed files with 98 additions and 2 deletions

View File

@ -251,6 +251,23 @@ abstract class AbstractNormalizer extends SerializerAwareNormalizer implements N
return (array) $data;
}
/**
* Returns the method to use to construct an object. This method must be either
* the object constructor or static.
*
* @param array $data
* @param string $class
* @param array $context
* @param \ReflectionClass $reflectionClass
* @param array|bool $allowedAttributes
*
* @return \ReflectionMethod|null
*/
protected function getConstructor(array &$data, $class, array &$context, \ReflectionClass $reflectionClass, $allowedAttributes)
{
return $reflectionClass->getConstructor();
}
/**
* Instantiates an object using constructor parameters when needed.
*
@ -282,7 +299,7 @@ abstract class AbstractNormalizer extends SerializerAwareNormalizer implements N
return $object;
}
$constructor = $reflectionClass->getConstructor();
$constructor = $this->getConstructor($data, $class, $context, $reflectionClass, $allowedAttributes);
if ($constructor) {
$constructorParameters = $constructor->getParameters();
@ -318,7 +335,11 @@ abstract class AbstractNormalizer extends SerializerAwareNormalizer implements N
}
}
return $reflectionClass->newInstanceArgs($params);
if ($constructor->isConstructor()) {
return $reflectionClass->newInstanceArgs($params);
} else {
return $constructor->invokeArgs(null, $params);
}
}
return new $class();

View File

@ -0,0 +1,31 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Serializer\Tests\Fixtures;
class StaticConstructorDummy
{
public $foo;
public $bar;
public $quz;
public static function create($foo)
{
$dummy = new self();
$dummy->quz = $foo;
return $dummy;
}
private function __construct()
{
}
}

View File

@ -0,0 +1,32 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Serializer\Tests\Fixtures;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
/**
* @author Guilhem N. <egetick@gmail.com>
*/
class StaticConstructorNormalizer extends ObjectNormalizer
{
/**
* {@inheritdoc}
*/
protected function getConstructor(array &$data, $class, array &$context, \ReflectionClass $reflectionClass, $allowedAttributes)
{
if (is_a($class, StaticConstructorDummy::class, true)) {
return new \ReflectionMethod($class, 'create');
}
return parent::getConstructor($data, $class, $context, $reflectionClass, $allowedAttributes);
}
}

View File

@ -9,6 +9,8 @@ use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Tests\Fixtures\AbstractNormalizerDummy;
use Symfony\Component\Serializer\Tests\Fixtures\ProxyDummy;
use Symfony\Component\Serializer\Tests\Fixtures\StaticConstructorDummy;
use Symfony\Component\Serializer\Tests\Fixtures\StaticConstructorNormalizer;
/**
* Provides a dummy Normalizer which extends the AbstractNormalizer.
@ -103,4 +105,14 @@ class AbstractNormalizerTest extends \PHPUnit_Framework_TestCase
$this->assertSame('bar', $proxyDummy->getFoo());
}
public function testObjectWithStaticConstructor()
{
$normalizer = new StaticConstructorNormalizer();
$dummy = $normalizer->denormalize(array('foo' => 'baz'), StaticConstructorDummy::class);
$this->assertInstanceOf(StaticConstructorDummy::class, $dummy);
$this->assertEquals('baz', $dummy->quz);
$this->assertNull($dummy->foo);
}
}