Last active
June 21, 2016 11:28
-
-
Save sasezaki/d470ee4c73d48fb6f01033907cce9245 to your computer and use it in GitHub Desktop.
tasting implementation hydrator, serializer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types=1); | |
namespace ClassHydrator { | |
interface ClassHydrationInterface | |
{ | |
public function hydrate(array $data, string $className); | |
} | |
// | |
// Naming `InstanceArgs` is borrowd from ReflectionClass method name. | |
// http://php.net/reflectionclass.newinstanceargs | |
// $data keys should be sameorder class constructor args. | |
class InstanceArgsClassHydrator implements ClassHydrationInterface | |
{ | |
public function hydrate(array $data, string $className) | |
{ | |
$data = array_values($data); // Cannot unpack array with string keys, so use array_values | |
return new $className(...$data); | |
} | |
} | |
class ConstructorParameterNameClassHydrator implements ClassHydrationInterface | |
{ | |
public function hydrate(array $data, string $className) | |
{ | |
$refClass = new \ReflectionClass($className); | |
/** @var \ReflectionParameter[] $paramters */ | |
$parameters = $refClass->getConstructor()->getParameters(); | |
$constructors = []; | |
foreach ($parameters as $i => $parameter) { | |
$constructors[$i] = $data[$parameter->getName()] ?? null; | |
} | |
return new $className(...$constructors); | |
} | |
} | |
trait StrategyTrait | |
{ | |
private $strategies; | |
/** | |
* Gets the strategy with the given name. | |
* | |
* @param string $name The name of the strategy to get. | |
* | |
* @throws \InvalidArgumentException | |
* @return \Zend\Hydrator\Strategy\StrategyInterface | |
*/ | |
public function getStrategy($name) | |
{ | |
if (isset($this->strategies[$name])) { | |
return $this->strategies[$name]; | |
} | |
if (!isset($this->strategies['*'])) { | |
throw new \InvalidArgumentException(sprintf( | |
'%s: no strategy by name of "%s", and no wildcard strategy present', | |
__METHOD__, | |
$name | |
)); | |
} | |
return $this->strategies['*']; | |
} | |
/** | |
* Checks if the strategy with the given name exists. | |
* | |
* @param string $name The name of the strategy to check for. | |
* @return bool | |
*/ | |
public function hasStrategy($name) | |
{ | |
return array_key_exists($name, $this->strategies) | |
|| array_key_exists('*', $this->strategies); | |
} | |
} | |
class StrategyAwareHydrator implements ClassHydrationInterface | |
{ | |
use StrategyTrait; | |
public function __construct(array $strategies = []) | |
{ | |
$this->strategies = $strategies; | |
} | |
public function hydrate(array $data, string $className) | |
{ | |
$refClass = new \ReflectionClass($className); | |
/** @var \ReflectionParameter[] $paramters */ | |
$parameters = $refClass->getConstructor()->getParameters(); | |
$constructors = []; | |
foreach ($parameters as $i => $parameter) { | |
$name = $parameter->getName(); | |
$value = $data[$name] ?? null; | |
if ($this->hasStrategy($name)) { | |
$constructors[$i] = $this->getStrategy($name)->hydrate($value); | |
} else { | |
$constructors[$i] = $value; | |
} | |
} | |
return new $className(...$constructors); | |
} | |
} | |
} | |
namespace Sample { | |
class SampleUser | |
{ | |
private $id, $username, $birth; | |
/** | |
* SampleUser constructor. | |
* @param $id | |
* @param $username | |
* @param $birth | |
*/ | |
public function __construct($id, $username, $birth) | |
{ | |
$this->id = $id; | |
$this->birth = $birth; | |
$this->username = $username; | |
} | |
/** | |
* @return mixed | |
*/ | |
public function getId() | |
{ | |
return $this->id; | |
} | |
/** | |
* @return mixed | |
*/ | |
public function getUsername() | |
{ | |
return $this->username; | |
} | |
/** | |
* @return mixed | |
*/ | |
public function getBirth() | |
{ | |
return $this->birth; | |
} | |
} | |
} | |
// $classHydrator = new InstanceArgsClassHydrator(); | |
// $object = $classHydrator->hydrate(['id' => 1, 'username' => 'john', 'birth' => 'Japan'], SampleUser::class); | |
// var_dump($object); | |
//namespace { | |
// use ClassHydrator\ConstructorParameterNameClassHydrator; | |
// use Sample\SampleUser; | |
// | |
// $classHydrator = new ConstructorParameterNameClassHydrator(); | |
// $object = $classHydrator->hydrate(['username' => 'john', 'birth' => 'Japan', 'id' => 1], SampleUser::class); | |
// var_dump($object); | |
//} | |
namespace { | |
use ClassHydrator\StrategyAwareHydrator; | |
use Sample\SampleUser; | |
use Zend\Hydrator\Strategy\DateTimeFormatterStrategy; | |
require_once __DIR__.'/vendor/autoload.php'; | |
$data = ['username' => 'john', 'birth' => '2008-05-16T11:25:30+09:00', 'id' => 1]; | |
$classHydrator = new StrategyAwareHydrator([ | |
'birth' => new DateTimeFormatterStrategy(), | |
]); | |
$object = $classHydrator->hydrate($data, SampleUser::class); | |
var_dump($object); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment