Skip to content

Instantly share code, notes, and snippets.

@sasezaki
Last active June 21, 2016 11:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sasezaki/d470ee4c73d48fb6f01033907cce9245 to your computer and use it in GitHub Desktop.
Save sasezaki/d470ee4c73d48fb6f01033907cce9245 to your computer and use it in GitHub Desktop.
tasting implementation hydrator, serializer
<?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