使用Memio自动生成PHP代码

tech2022-09-04  168

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.

是否曾经想过编写负责自动生成某些PHP类,方法和属性的代码? 继续阅读以获得有关何时自动生成代码可能有用以及最重要的是如何使用Memio库正确实现代码的详细信息。

这个概念 (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.

基本思想很简单。 您编写的代码将创建代码,函数,变量,类,文档块等的其他部分。以编程语言(在本例中为PHP)进行操作时,您可以指定参数,if-else语句,循环,等等。

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.

当然,能够自动创建PHP代码并不意味着我们将被开发人员取代。 但是它可以用来形成一个基本结构,以后人类会进一步开发它。 例如,您可以使用生成器,而不是通过复制粘贴来准备应用程序中的初始类集。

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

代码生成已在各种框架中使用。 有关示例,请参见Symfony2 GeneratorBundle , CakePHP控制台命令或Laravel Artisan 。

使用Memio生成PHP类 (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.

如果您要编写自己的脚本来自动生成PHP代码,那么一种选择是使用Memio库 。 Memio的优点在于,它使用面向对象的代码编写得很好。 您不需要用字符串编写目标代码,不需要连接字符串变量等。一切都通过创建类实例并调用其方法来完成。 输出代码本身的模板存储为Twig模板。

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:

要在您的项目中开始使用Memio,只需按照文档中的说明将其添加到composer.json文件中即可。 负责生成代码的核心类– PrettyPrinter –需要Twig_Environment实例作为构造函数参数。 应该通过以下方式初始化:

$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:

要使用Memio生成一些PHP代码,您必须创建代表特定代码部分的对象,然后将它们传递给PrettyPrinter实例,然后您将获得输出代码。 代表自动生成的代码的每个对象都是Memio model类之一的实例。 要自定义输出代码,您需要在这些实例上调用特定方法,Memio库将在打印时完成其余工作。 向方法添加主体,设置属性的可见性,设置类实现的接口–所有这些都通过调用适当的方法来完成。 这是生成User类的示例:

$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.

将数据库结构映射到PHP类时,通常会使用自动生成PHP代码。 数据库中的每个表都可以由PHP应用程序中的单独类表示。 然后,每个表列将由一个class属性表示。 让我们尝试编写一个简单的脚本,该脚本将基于MySQL数据库结构创建此类。

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.

首先,从我们的脚本开始,我们需要获取所选数据库中表的列表。 我们还将需要每个这些表中的列列表。 为了获得所有这些数据,我们必须使用两个MySQL命令:在开始处SHOW TABLES ,然后对第一个查询中返回的每个DESC <table name> 。

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:

下一步是为每个表生成一个单独PHP类。 类的名称将与表名称相同,只是以大写字母开头:

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:

就这样! 要获取该类的输出代码,只需将$class变量传递给Memio PrettyPrinter@generateCode方法:

$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:

上面的示例只是使用Memio的简单介绍。 为了使我们的班级更加有用,我们可以通过多种方式扩展它们。 首先,让我们为每个属性生成getter和setter。 现在,我们遍历表中列名称的循环将如下所示:

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.

如您所见,我们创建了两个实例化Memio Method类的变量: $getter和$setter 。 将要生成的方法的名称为get<Column>和set<Column> 。 由于setter方法需要一个参数,因此我们需要创建一个Memio Argument类的实例。 然后,通过在$setter变量上调用addArgument()将其传递给setter方法。 下一步是仅通过调用setBody()方法将主体添加到getter和setter方法中。 最后,我们通过在$class变量上调用addMethod()将这些方法添加到$class 。

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.

上面的示例显示了使用Memio的一个重要方面。 请注意,我们总是将代表一小部分代码的对象传递给更高级别的对象。 首先是方法参数( Argument类)。 然后,我们创建一个方法( Method类),并将参数添加到方法中( $method->addArgument() )。 该方法应该放在一个类中,因此我们创建一个类( Object类)并将该方法添加到该类( $class->addMethod() )中。 因此,总体思路是从一小部分代码开始,然后将它们链接到更高级别的容器。

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.

为了表示Memio中的整个代码结构,您还可以将输出类( Object类)放在文件中( File类的实例)。 在您的Memio脚本中包含File类,使您可以在输出的开头生成带有名称空间声明,许可证信息和PHP开头标签的代码。 请参阅文档以检查如何实施,并尝试自己添加适当的代码。 要基于上面的示例获取整个应用程序,只需检查与文章相关的Github存储库 。

下一步 (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.

在我们的示例中,我们仅创建了一个简单的类生成器,该类将数据库表映射为对象。 示例代码可以扩展为更高级的脚本。 例如,您可以使用有关MySQL中列类型的信息,并验证传递给setter方法的变量。 下一步,您可以通过将对象实例转移到MySQL INSERT或UPDATE语句中来生成将对象持久保存在数据库中的代码。

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.

还请记住,可以通过更改默认模板来修改基于Memio的脚本的输出。 例如,如果您要生成符合项目中使用的编码标准的代码,则只需更改模板即可。 然后,将根据您自己的编码样式和约定生成所有自动生成的代码。 模板文档包含有关如何使用自己的文件替换默认模板的所有详细信息。

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!

我鼓励您自己编写一些自动生成的脚本,以检查Memio库的所有功能。 在下面的评论中分享您的结果和想法。 玩得开心!

翻译自: https://www.sitepoint.com/automatic-php-code-generation-memio/

相关资源:PHPMaker 2020(PHP代码自动生成工具) v2020.0.0(附替换补丁)
最新回复(0)