Skip to content

Commit

Permalink
Adds configuration for the hydrator on a per property basis
Browse files Browse the repository at this point in the history
  • Loading branch information
flip111 committed Nov 23, 2015
2 parents fd458d3 + ba0c96c commit a5ff50c
Show file tree
Hide file tree
Showing 16 changed files with 588 additions and 159 deletions.
7 changes: 5 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ php:
- 5.4
- 5.5
- 5.6
- 7
- hhvm
- hhvm-nightly

before_script:
- composer self-update
Expand All @@ -13,12 +15,13 @@ before_script:
script:
- ./vendor/bin/phpunit --coverage-clover ./build/logs/clover.xml --exclude-group Functional
- ./vendor/bin/phpunit --group=Functional
- php -n ./vendor/bin/athletic -p ./tests/GeneratedHydratorPerformance/ -b ./tests/Bootstrap.php -f GroupedFormatter
- php -n ./vendor/bin/athletic -p ./tests/GeneratedHydratorPerformance/ -f GroupedFormatter
- ./vendor/bin/phpcs --standard=PSR2 ./src/ ./tests/

after_script:
- php vendor/bin/coveralls -v

matrix:
allow_failures:
- php: hhvm
- php: 7
- php: hhvm-nightly
80 changes: 79 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ to arrays.

## What does this thing do?

A [hydrator](http://framework.zend.com/manual/2.1/en/modules/zend.stdlib.hydrator.html) is an object capable of
A [hydrator](http://framework.zend.com/manual/current/en/modules/zend.stdlib.hydrator.html) is an object capable of
extracting data from other objects, or filling them with data.

A hydrator performs following operations:
Expand Down Expand Up @@ -144,6 +144,84 @@ class Baz extends Foo

This will be solved in milestone [1.1.0](https://github.com/Ocramius/GeneratedHydrator/issues?milestone=3)

## Tuning for Production

By default, GeneratedHydrator will generate hydrators on every new request.
While this is relatively fast, it will cause I/O operations, and you can
achieve even better performance by pre-generating your hydrators and telling
your application to autoload them instead of generating new ones at each run.

Avoiding regeneration involves:

1. pre-generating your hydrators
2. ensuring that your autoloader is aware of them

The instructions that follow assume you are using Composer.

### Pre-generating your hydrators

There is no built-in way to bulk-generate all required hydrators, so you will need
to do so on your own.

Here is a simple snippet you can use to accomplish this:

```php
require '/path/to/vendor/autoload.php'; // composer autoloader

// classes for which we want to pre-generate the hydrators
$classes = [
\My\Namespace\ClassOne::class,
\My\Namespace\ClassTwo::class,
\My\Namespace\ClassThree::class,
];

foreach ($classes as $class) {
$config = new \GeneratedHydrator\Configuration($class);

$config->setGeneratedClassesTargetDir('/path/to/target-dir');
$config->createFactory()->getHydratorClass();
}
```

Just add all the classes for which you need hydrators to the `$classes` array,
and have your deployment process run this script.
When complete, all of the hydrators you need will be available in `/path/to/target-dir`.

### Making the autoloader aware of your hydrators

Using your pre-generated hydrators is as simple as adding the generation target
directory to your `composer.json`:

```json
{
"autoload": {
"classmap": [
"/path/to/target-dir"
]
}
}
```

After generating your hydrators, have your deployment script run `composer dump-autoload`
to regenerate your autoloader.
From now on, `GeneratedHydrator` will skip code generation and I/O if a generated class already
exists.

### Fallback autoloader

Alternatively, `GeneratedHydrator` comes with a built-in autoloader that you can register
on your own. This simplifies deployment, but is a bit slower:

```php
$config = new \GeneratedHydrator\Configuration(\My\Namespace\ClassOne::class);

spl_autoload_register($config->getGeneratedClassAutoloader());

// now simply use your hydrator, and if possible, code generation will be skipped:
$hydratorName = $config->createFactory()->getHydratorClass();
$hydrator = new $hydratorName();
```

## Contributing

Please read the [CONTRIBUTING.md](https://github.com/Ocramius/GeneratedHydrator/blob/master/CONTRIBUTING.md) contents
Expand Down
23 changes: 15 additions & 8 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@
}
],
"require": {
"php": ">=5.4",
"zendframework/zend-stdlib": "2.*",
"nikic/php-parser": "0.9.*",
"ocramius/code-generator-utils": "0.1.*"
"php": "~5.4|~7.0",
"zendframework/zend-stdlib": "~2.3",
"nikic/php-parser": "~1.0",
"ocramius/code-generator-utils": "0.3.*"
},
"require-dev": {
"phpunit/phpunit": ">=3.7",
"phpmd/phpmd": "1.4.*",
"squizlabs/php_codesniffer": "1.4.*",
"phpunit/phpunit": "~4.0",
"phpmd/phpmd": "1.5.*",
"squizlabs/php_codesniffer": "1.5.*",
"satooshi/php-coveralls": "~0.6",
"athletic/athletic": "~0.1.6"
},
Expand All @@ -37,9 +37,16 @@
"GeneratedHydrator\\": "src"
}
},
"autoload-dev": {
"psr-0": {
"GeneratedHydratorPerformance\\": "tests",
"GeneratedHydratorTest\\": "tests",
"GeneratedHydratorTestAsset\\": "tests"
}
},
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
"dev-master": "1.2.x-dev"
}
}
}
2 changes: 1 addition & 1 deletion phpunit.xml.dist
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
<phpunit
bootstrap="./tests/Bootstrap.php"
bootstrap="./vendor/autoload.php"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@

namespace GeneratedHydrator\ClassGenerator\Hydrator\PropertyGenerator;

use PHPParser_Node_Stmt_Class;
use PHPParser_Node_Stmt_Property;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\Property;
use PhpParser\Node\Stmt\PropertyProperty;
use ReflectionProperty;
use CodeGenerationUtils\Inflector\Util\UniqueIdentifierGenerator;

Expand All @@ -30,7 +31,7 @@
* @author Marco Pivetta <ocramius@gmail.com>
* @license MIT
*/
class PropertyAccessor extends PHPParser_Node_Stmt_Property
class PropertyAccessor extends Property
{
/**
* @var \ReflectionProperty
Expand All @@ -48,8 +49,8 @@ public function __construct(ReflectionProperty $accessedProperty, $nameSuffix)
$name = UniqueIdentifierGenerator::getIdentifier($originalName . $nameSuffix);

parent::__construct(
PHPParser_Node_Stmt_Class::MODIFIER_PRIVATE,
array(new \PHPParser_Node_Stmt_PropertyProperty($name))
Class_::MODIFIER_PRIVATE,
array(new PropertyProperty($name))
);
}

Expand Down
14 changes: 7 additions & 7 deletions src/GeneratedHydrator/ClassGenerator/HydratorGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
use CodeGenerationUtils\Visitor\ClassImplementorVisitor;
use CodeGenerationUtils\Visitor\MethodDisablerVisitor;
use GeneratedHydrator\CodeGenerator\Visitor\HydratorMethodsVisitor;
use PHPParser_NodeTraverser;
use PhpParser\NodeTraverser;
use ReflectionClass;

/**
Expand All @@ -38,21 +38,21 @@
class HydratorGenerator
{
/**
* Generates an AST of {@see \PHPParser_Node[]} out of a given reflection class
* Generates an AST of {@see \PhpParser\Node[]} out of a given reflection class
* and a map of properties to be used to
*
* @param \ReflectionClass $originalClass
*
* @return \PHPParser_Node[]
* @return \PhpParser\Node[]
*/
public function generate(ReflectionClass $originalClass)
public function generate(ReflectionClass $originalClass, array $options = [])
{
$builder = new ClassBuilder();

$ast = $builder->fromReflection($originalClass);

// step 1: remove methods that are not used
$cleaner = new PHPParser_NodeTraverser();
$cleaner = new NodeTraverser();

$cleaner->addVisitor(
new MethodDisablerVisitor(
Expand All @@ -65,9 +65,9 @@ function () {
$ast = $cleaner->traverse($ast);

// step 2: implement new methods and interfaces, extend original class
$implementor = new PHPParser_NodeTraverser();
$implementor = new NodeTraverser();

$implementor->addVisitor(new HydratorMethodsVisitor($originalClass));
$implementor->addVisitor(new HydratorMethodsVisitor($originalClass, $options));
$implementor->addVisitor(new ClassExtensionVisitor($originalClass->getName(), $originalClass->getName()));
$implementor->addVisitor(
new ClassImplementorVisitor($originalClass->getName(), array('Zend\\Stdlib\\Hydrator\\HydratorInterface'))
Expand Down
Loading

0 comments on commit a5ff50c

Please sign in to comment.