Automatic PHP Code Generation with Memio

Share this article

Ever thought of writing code responsible for generating certain PHP classes, methods, properties automatically? Read on to get the details on when exactly automatic code generation may be helpful and – what’s most important – how to implement it properly using the Memio library.

Code Generation Hero Image

The Concept

The basic idea is quite simple. You write code which will create other parts of the code, functions, variables, classes, doc blocks, etc. As you do it in a programming language (PHP in our case), you can specify parameters, if-else statements, loops, and so on.

Of course, being able to create PHP code automatically doesn’t mean we, the developers, will be replaced. But it may be used to form a basic structure which will later be further developed by a human. For example, instead of copy-pasting to prepare an initial set of classes in your application, you can use a generator.

Code generation is already being used in various frameworks. See Symfony2 GeneratorBundle, CakePHP console commands or Laravel Artisan for examples.

Generating PHP Classes with Memio

If you want to write your own script that generates PHP code automatically, one of the options is to use the Memio library. The good thing about Memio is that it’s well written, using object-oriented code. You don’t need to write the target code in strings, work on joining string variables, etc. Everything is being done by creating class instances and calling their methods. The templates for the output code itself are stored as Twig templates.

To start using Memio in your project, just add it to the composer.json file, as written in the documentation. The core class, responsible for generating the code – PrettyPrinter – requires a Twig_Environment instance as a constructor argument. It should be initialized the following way:

$twigLoaderFilesystem = new Twig_Loader_Filesystem('vendor/memio/memio/templates');
$twigEnvironment = new Twig_Environment($twigLoaderFilesystem, []);

$memioPrettyPrinter = new \Memio\Memio\PrettyPrinter($twigEnvironment);

To generate some PHP code with Memio, you have to create objects that represent specific code parts, then just pass them to the PrettyPrinter instance and you will get the output code as a result. Each of the objects that represents the auto-generated code is an instance of one of the Memio model classes. To customize the output code, you need to call specific methods on these instances and the Memio library will do the rest when printing. Adding a body to a method, setting the visibility of a property, setting an interface that the class implements – all that is being done by calling the proper methods. Here’s an example of generating a User class:

$class = \Memio\Memio\Model\Object::make('User');

$nameProperty = \Memio\Memio\Model\Property::make('name');
$class->addProperty($nameProperty);

$getNameMethod = \Memio\Memio\Model\Method::make('getName')->setBody('return $this->name');
$class->addMethod($getNameMethod);

echo $memioPrettyPrinter->generateCode($class);

This will produce the following output:

class User
{
    private $name;

    public function getName()
    {
        return $this->name;
    }
}

Real World Example: Object-Relational Mapping

Auto-generating PHP code is often being used when mapping the database structure to PHP classes. Each table in a database can be represented by a separate class in a PHP application. Then each of the table columns will be represented by a class property. Let’s try to write a simple script that will create such classes, based on a MySQL database structure.

To begin with our script, we need to fetch a list of the tables in a selected database. We will also need the list of columns in each of these tables. To get all this data we have to use two MySQL commands: SHOW TABLES at the beginning and then DESC <table name> for each of the tables returned in the first query.

The next step is to generate a separate PHP class for each of the tables. The name of the class will be the same as the table name, just starting with a capital letter:

foreach($tableNames as $table) {
    $class = new \Memio\Memio\Model\Object(ucfirst($table));

    //...
}

To make our classes more useful, we will add class properties representing each of the table columns. Assuming that we stored the column names in a flat array, the code will look as follows:

foreach($columnNames as $column) {
    $property = \Memio\Memio\Model\Property::make($column);
    $class->addProperty($property);
}

And… that’s all! To get the output code for the class, just pass the $class variable to the Memio PrettyPrinter@generateCode method:

$code = $memioPrettyPrinter->generateCode($class);

This lets us automatically generate classes for all of the tables in our database.

Extending the Model Generator

The example above is just a simple introduction to working with Memio. To make our classes more usable, we can extend them in many ways. First, let’s generate getters and setters for each of the properties. Our loop through column names in a table will now look as follows:

foreach($columnNames as $column) {
    $property = \Memio\Memio\Model\Property::make($column);
    $class->addProperty($property);

    $getter = Method::make('get' . ucfirst($column))->setBody('return $this->' . $column . ';');
    $class->addMethod($getter);

    $setterArgument = Argument::make('string', $column);
    $setter = Method::make('set' . ucfirst($column))->addArgument($setterArgument)->setBody('$this->' . $column . ' = $' . $column . ';');
    $class->addMethod($setter);
}

As you can see, we created two variables that instantiate the Memio Method class: $getter and $setter. The name of the methods that will be generated is get<Column> and set<Column>. As the setter method needs an argument, we need to create an instance of the Memio Argument class. Then we pass it to our setter method by calling the addArgument() on the $setter variable. The next step is to add the body to both getter and setter methods, just by calling the setBody() method. Finally, we add these methods to the class by calling the addMethod() on the $class variable.

The example above shows one important aspect of working with Memio. Please notice that we always pass objects representing small parts of code to higher level ones. First comes the method argument (the Argument class). Then we create a method (the Method class) and add the argument to the method ($method->addArgument()). The method should be put inside a class, so we create a class (the Object class) and add the method to the class ($class->addMethod()). So the general idea is to start from small parts of the code and link them to a higher level containers.

To represent the whole code structure in Memio, you can additionally put the output class (the Object class) in a file (instance of the File class). Including the File class in your Memio script allows you to generate code with namespace declaration, license information and the PHP opening tag at the beginning of the output. See the documentation to check how it can be implemented and try adding the proper code by yourself. To get the whole app based on the example above, just check the Github repo connected with the article.

Next Steps

In our example we created just a simple class generator that maps database tables into objects. The sample code can be extended into a much more advanced script. For example, you can use the information about column types from MySQL and validate variables that are being passed to the setter methods. As a next step, you can generate code that persists the object in a database, by transferring an object instance into a MySQL INSERT or UPDATE statement.

Also remember that the output of Memio-based scripts can be modified by changing the default templates. For example, if you want to generate code that adheres to the coding standards used in your project, all you need to do is make a change in the template. Then all the auto-generated code will be produced based on your own coding style and conventions. The template documentation contains all the details on how to replace the default templates with your own files.

I encourage you to write some auto-generating scripts by yourself to check out all the features of the Memio library. Share your results and thoughts in the comments below. Have fun!

Frequently Asked Questions (FAQs) about Automatic PHP Code Generation with Memio

What is Memio and how does it help in PHP code generation?

Memio is a highly efficient PHP code generator that allows developers to automate the process of writing code. It uses an object-oriented approach to generate PHP code, which makes it easier to maintain and modify. Memio provides a set of models that represent different PHP code structures such as classes, methods, and interfaces. These models can be manipulated using Memio’s API to generate the desired PHP code. This not only saves time but also ensures consistency and reduces the chances of errors in the code.

How does Memio differ from other PHP code generators?

Unlike many other PHP code generators, Memio uses an object-oriented approach. This means that instead of writing code as strings, you manipulate objects that represent different parts of the code. This makes the code easier to understand, maintain, and modify. Furthermore, Memio provides a higher level of abstraction, which simplifies the process of code generation.

How can I install Memio?

Memio can be easily installed using Composer, a dependency management tool for PHP. You just need to run the command composer require memio/memio in your terminal. This will download and install Memio along with its dependencies.

Can I use Memio to generate code for any PHP project?

Yes, Memio is versatile and can be used to generate code for any PHP project. It provides a set of models that represent different PHP code structures, which can be manipulated to generate the desired code. Whether you’re working on a small personal project or a large enterprise application, Memio can help you automate the process of writing code.

How can I generate a class using Memio?

To generate a class using Memio, you first need to create an instance of the ClassModel class. You can then use the methods provided by this class to define the properties and methods of your class. Once you’ve defined your class, you can use the PrettyPrinter class to generate the PHP code.

Can I generate interfaces with Memio?

Yes, Memio allows you to generate interfaces as well. Similar to classes, you can create an instance of the InterfaceModel class and use its methods to define the methods of your interface. The PrettyPrinter class can then be used to generate the PHP code.

How can I generate methods using Memio?

To generate methods using Memio, you can create an instance of the MethodModel class. This class provides methods that allow you to define the name, parameters, and body of your method. Once you’ve defined your method, you can add it to a class or interface using the addMethod method.

Can I generate properties with Memio?

Yes, Memio allows you to generate properties as well. You can create an instance of the PropertyModel class and use its methods to define the name and visibility of your property. Once you’ve defined your property, you can add it to a class using the addProperty method.

How can I generate code for a complete PHP file using Memio?

To generate code for a complete PHP file, you can use the FileModel class. This class allows you to define the namespace, use statements, and classes or interfaces of your file. Once you’ve defined your file, you can use the PrettyPrinter class to generate the PHP code.

Can I customize the code generated by Memio?

Yes, Memio provides a high level of customization. You can manipulate the models provided by Memio to generate the exact code you need. Furthermore, you can use the TemplateEngine class to customize the format of the generated code.

Jacek BareckiJacek Barecki
View Author

Jacek is a web developer specialized in building extensive web applications, mainly e-commerce solutions. The technologies he uses on a daily basis include PHP, MySQL, HTML+CSS and JS+jQuery. During the last few years he was the head developer of a highly customized online store platform in Poland. Now he's working on the development of several e-commerce websites running in Poland and Germany, often having hundreds of thousands pageviews a day. To take a break from coding, he does challenging crossfit workouts, goes out to taste some new food or dives into an interesting psychology magazine or book.

BrunoScode generationmemioOOPHPPHPtwig
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week