📜 ⬆️ ⬇️

Zend_CodeGenerator Review

As many already know, Zend_CodeGenerator has appeared in beta 1.8 Zend_Framework
I wanted to be patient before the release of version 1.8, but I could not resist and decided to still try on the teeth.
We will generate a form class based on the mysql table.
It is really very convenient and saves us from sometimes routine work.

First we need to consider the classes that we will use.

To create a php file there is a class
Zend_CodeGenerator_Php_File();
Its constructor accepts an array in which the classes in this file are specified. For example, you can do this:

$file = new Zend_CodeGenerator_Php_File(array( 'classes' => array($ class )));

')
Where $ class is an instance of a class.
Zend_CodeGenerator_Php_Class ()

There may be several classes in order to generate several classes; you should specify them in an array.

But the coding standards for Zend_Framework say:
“Only one class is allowed inside a single PHP file.
Placing additional code in the file with the class is allowed, but not welcome. In such files, two blank lines must separate the class and the additional PHP code. ”

This is a subjective matter and I would still generate one file for each class,
So more clearly traced the structure of the application.

So create a new class:
$ class = new Zend_CodeGenerator_Php_Class();


The first method we need is setName ().
the input parameter for it will be a string with a class.
$class -> setName('MyClass')
In order to specify from which class the generated class will be inherited we use the method

$ class ->setExtendedClass( 'Myclass2' )


Then we may need a dock block,

$docblock = new Zend_CodeGenerator_Php_Docblock(array(
'shortDescription' => ' ' ,
'longDescription' => ' Zend_CodeGenerator' ,
'tags' => array(
array(
'name' => 'version' ,
);


* This source code was highlighted with Source Code Highlighter .

In the array, which is the input parameter, we specify
'shortDescription' - a brief description of the class
'longDescription' full class description

In the tags array, we can specify tags for the docblock.
'name' - tag name
'description' - the text following it

Then we need to declare the variables used in this class.
This is the setProperties () method. Its day parameter is an array of variables, each new variable will be described in a new array.
In which to specify the properties of the variable
Or they can be described through the class Zend_CodeGenerator_Php_Parameter

Suppose we need 2 variables:

$vars = array(
array(
'name' => 'name,
'visibility' => 'public' ,
'defaultValue' => '0',
)
array(
'name' => '_table',
'visibility' => 'protected' ,
'defaultValue' => '1',
)
);



Or
$var1 = Zend_CodeGenerator_Php_Parameter(
array(
'name' => ' var ',
'visibility' => 'public' ,
'defaultValue' => '0',
)
);
$var2 = Zend_CodeGenerator_Php_Parameter(
array(
'name' => 'var2',
'visibility' => 'protected' ,
'defaultValue' => '1',
)
);
$vars = array($var1, var2);



Name is the name of the variable.
Visibility - access modifier
Default value - the default values, if you do not specify this parameter, then the variable will be equal to null

Now our class might look like this:
$ class = new Zend_CodeGenerator_Php_Class();
$ class -> setName( 'MyClass extends MyClass2' ) -> setProperties($vars) -> setDocblock($docblock);



Of course, we will need to describe the methods of this class.
To set the method is the method
setMethod() or
setMethods()
The only difference is in the number of methods we want to set, setMethod() accepts either an instance of the Zend_CodeGenerator_Php_Method class or an array that describes a method, setMethods() accepts an array that contains method objects, or a set of arrays.

If you chose the first path, then it might look like this:
$method = Zend_CodeGenerator_Php_Method(array(
'name' => 'myMethod' ,
'body' => 'echo "hello CodeGenerator"' ,
'docblock' => new Zend_CodeGenerator_Php_Docblock(array(
'shortDescription' => ' ' ,
'tags' => array(
new Zend_CodeGenerator_Php_Docblock_Tag_Return(array(
'datatype' => 'string|null' ,
)),
),
)),
)),
));

$ class ->setMethod($method);



If the second is possible and so:

$ class -> setMethods(array(
array(
'name' => 'myMethod' ,
'parameters' => array(
array( 'name' => 'myVar),
),
'
body ' => ' $ var = 'hello world' ; ' . "\n" . ' return $ var ',
'
docblock ' => new Zend_CodeGenerator_Php_Docblock(array(
'
shortDescription ' => ' ',
'
tags ' => array(
new Zend_CodeGenerator_Php_Docblock_Tag_Param(array(
'
paramName ' => ' bar ',
'
datatype ' => ' string '
)),
new Zend_CodeGenerator_Php_Docblock_Tag_Return(array(
'
datatype ' => ' string ',
)),
),
)),
)



here 'name' is the name of the method
'parameters' are incoming parameters, each new parameter is described by a new array, everything is exactly the same as for variables inside a class, and you can also use the Zend_CodeGenerator_Php_Parameter () class
'body' is the body of the method where we put the code that will be executed inside the method in the bottom case it is, '$ var =' hello world ';'. "\ n". 'return $ var', here it is worth noting that the code is not automatically formatted because you have to use "\ n" and "\ t"
Docblocks in methods are specified the same as for classes.

In the end, all that remains to be done is to generate the code and write it to a file.
$code = $file->generate();
file_put_contents( 'file.php' , $code);



To do this, we use the standard php function - file_put_contents and the generate () method;
Which is present in all the classes I described above in Zend_CodeGenerator
If it is more convenient for you, you can generate each element in parts and write it to a file separately.

Next, I will give a rather vivid example - a class that generates forms.

<?php
class FormGenerator
{
/**
* mysql
* - input type
* */
protected $_values = array(
'text' => 'Textarea' ,
'int' => 'Text' ,
'varchar' => 'Text' ,
'tinyint' => 'CheckBox' ,
'date' => 'Text' ,
'float' => 'Text' ,
'mediumint' => 'Text' ,
);
/**
*
* - Zend_Db_Table
* */
public function generateForm(Zend_Db_Table $table)
{
//
$tableInfo = $table->info();

//
$className = 'Form_' . ucfirst($tableInfo[ 'name' ]);

//
$folder = $_SERVER[ 'DOCUMENT_ROOT' ] . '/application/models/Form/' ;

//
$formClass = new Zend_CodeGenerator_Php_Class();
$formClass->setName($className);
$formClass->setExtendedClass( 'Zend_Form' );

// init
$initMethodBody = 'parent::init();
$helper = new Zend_View_Helper_Url();
'
. "\n\t\t" ;

// generateElement()
foreach ($tableInfo[ 'metadata' ] as $field){
Zend_Debug::dump($field);
$initMethodBody .= $ this ->generateElement($field[ 'COLUMN_NAME' ], $field[ 'DATA_TYPE' ]);
}

// submit
$initMethodBody .= $ this ->generateSumitElement($tableInfo[ 'name' ]);
$initMethod = new Zend_CodeGenerator_Php_Method(
array(
'name' => 'init' ,
'body' =>$initMethodBody
));

//
$formClass->setMethod($initMethod);

//
$file = new Zend_CodeGenerator_Php_File(array(
'classes' => array($formClass)
));

//
$code = $file->generate();

//
if (!file_exists($folder)) {
mkdir($folder);
}
//
file_put_contents($folder.ucfirst($tableInfo[ 'name' ]) . '.php' , $code);
}

/**
*
* - mysql
*
* */
public function generateElement($name, $type)
{
$element = '$' . $name . ' = new Zend_Form_Element_' . $ this ->_values[$type]. "(\n\t\t"
. "'$name'," . " \n\t\t"
. "array("
. "'label' => '$name')); \n\t\t" ;
// Digits
if ($type == 'int' || $type == 'tinyint' || $type == 'mediumint' ) {
$element .= '$' . $name . '->addValidator("Digits", true);' . "\n\t\t" ;
}

// StripTags
if ($ this ->_values[$type] == 'Textarea' || $ this ->_values[$type] == 'Text' ){
$element .= '$' . $name . '->addFilter("StripTags");' . "\n\t\t" ;
}
// StringTrim
$element .= '$' . $name . '->addFilter("StringTrim");' . "\n\t\t"
. '$this->addElement($' . $name . ');' . "\n\n\t\t" ;
return $element;
}

/**
* submit
*/
public function generateSumitElement($name)
{
$element = '$submit_' . $name . ' = new Zend_Form_Element_Submit('
. "'submit_$name'" . "); \n\t\t"
. '$this->addElement($submit_' . $name . ');' ;
return $element;
}
}

* This source code was highlighted with Source Code Highlighter .


In general, there is a place where they can go wild, for example, if the data type in mysql is DATE, then you can bind it here, decorating it as a decorator, or make different validators for each data type. Flight of fancy - not limited.

In addition to forms, you can generate almost anything - controllers, models, thereby saving yourself from unnecessary work.
Or use Zend_Tool + Zend_Application to generate the site structure and some of its classes from under the console of your operating system.
Of course, the code generated in this way requires completion with a file, but still it will take less time than writing it from the very beginning.
We are looking forward to the release of version 1.8, but for now we are dealing with innovations. It seems to me that the developers of the Zend Framework in the release version will make a FormGenerator and many more goodies.

PS: The author of the article is Gibbzy .

Source: https://habr.com/ru/post/57609/


All Articles