Memio v1.0 06/05/2015
TL;DR: Memio is a PHP code generator library, the main repository provides integration with Twig templates, but by using the smaller package
pretty-printer
on its own it is possible to be decoupled from any template engines.
Memio has finally be released in version 1.0 (stable). In this article, we'll see how the different packages are assembled in the main repository.
Standard Edition
Memio is composed of small packages (linter
, model
, pretty-printer
, twig-template-engine
, validator
),
the main repository (memio/memio) is a standard selection of those
to make their usage easier:
It can be installed using Composer:
composer require memio/memio:~1.0
It provides two services, which can be instanciated as follow:
<?php
// File: memio.php
require __DIR__.'/vendor/autoload.php';
use Memio\Memio\Config\Build;
$linter = Build::linter();
$prettyPrinter = Build::prettyPrinter();
To see how to use them, let's describe a request handler method:
// ...
use Memio\Model\Method;
use Memio\Model\Argument;
$handle = Method::make('handle')
->addArgument(Argument::make('Request', 'request'))
->addArgument(Argument::make('int', 'type')
->setDefaultValue('self::MASTER_REQUEST')
)
->addArgument(Argument::make('bool', 'catch')
->setDefaultValue('true')
)
;
Note: Each Model can be constructed using
new
or the static constructormake
. The last one has the advantage to allow method chaining (e.g.Method::make('doHandle')->makePrivate()
).
We can lint this model:
// ...
$linter->validate($handler); // @throws Memio\Validator\Exception\InvalidModelException if the model contains syntax errors.
And we can generate the corresponding PHP code:
// ...
$generatedCode = $prettyPrinter->generateCode($handle);
We can check in our console's output the result:
// ...
echo $generatedCode;
This should print:
public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true)
{
}
Limitations
Currently it is possible to describe:
- a File (License header, use statements)
- a Class (abstract, final, with parents, PHPdoc) or an Interface (with parents, PHPdoc)
- a class Constant
- a class Property (static, default value, PHPdoc)
- a class Method (static, abstract, final, visibility, PHPdoc)
- a method Argument (typehint, default value)
It is possible to describe a method Body, but only with a string:
// ...
$handle->setBody(<<<BODY
try {
$this->requestHandler->handle($request);
} catch (\Exception $e) {
if (!$catch) {
throw $e;
}
}
BODY
);
Use cases
In real life, models wouldn't be built manually as in the above examples. They would be built dynamically:
// ...
array_shift($argv); // remove binary name (php)
array_shift($argv); // remove script name (memio.php)
$methodName = array_shift($argv); // first argument = method name
$arguments = $argv; // all other arguments = argument types (e.g. `int`, `bool`, `DateTime`, etc)
$method = new Method($methodName);
$index = 1;
foreach ($arguments as $argumentType) {
$argumentName = 'argument'.$index++;
$method->addArgument(new Argument($argumentType, $argumentName));
}
echo $prettyPrinter->generatedCode($method);
Have a try by running php memio.php handle Request int bool
, it should print the following:
public function handle(Request $argument1, $argument2, $argument3)
{
}
With this we can already improve phpspec generator (generate typehinted arguments, PHPdoc, etc). This is going to be the next Memio package, a phpspec extension.
Extension points
The coding style can be changed by creating our custom templates. Those can be loaded as follow:
// ...
$prettyPrinter->addTemplatePath(__DIR__.'/our-custom-templates-dir');
Custom constraints can be written to check more things, for example we can ensure that arguments are always object.
Those steps, just like the rest, are heavily described in the official documentation.
Conclusion
Memio is a library that provides a PHP Code Generator:
- First we describe what we want by building
Models
(e.g.new Method('__construct')
) - Optionally we can
Lint
them to check if we introduced syntax errors (e.g.Method cannot be both abstract and final
) - Then we use a
PrettyPrinter
to get the generated code (returns a string, can be displayed on the output or saved in a file, etc)
You can read more about it with the following articles:
- Introducing Memio
- Memio Models
- Memio Validator and Linter
- Memio PrettyPrinter and TwigTemplateEngine
It also has an official documentation.
The next step is to create a phpspec extension to improve its code generator.