Как многим уже известно Zend_CodeGenerator появился в бете 1.8 Zend_Framework
Я хотел было потерпеть до релиза версии 1.8, но не удержался и решил всё таки попробавть «на зубок».
Мы будем генерировать класс формы на основе mysql таблицы.
Это действительно очень удобно и избавляет нас от порой рутинной работы.
Для начала нужно рассмотрим классы которые будем использовать.
Для создания php файла сущетвует класс
Его конструктор принимает массив в котором указываются классы находящиеся в этом файле. Например это можно сделать так:
Где $class это экземпляр класса
Zend_CodeGenerator_Php_Class()
Классов может быть несколько для того чтобы сгенерировать несколько классов стоит указать их в массиве.
Но в стандартах кодирования для Zend_Framework сказано:
Это дело субъективное и я бы всё таки сгенерировал по одному файлу на каждый класс,
Так более чётко прослеживается структура приложения.
Итак создадим новый класс:
первый метод который нам понадобится это setName()
входящим параметром для него будет являться строка с наванием класса.
Для того чтобы указать от какого класса будет наследоватся генерируемый класс используем метод
Затем нам может понадобиться док блок,
В массиве, который являеться входящим параметром мы указываем
‘shortDescription' – краткое описание класса
'longDescription' полное описание класса
Во вложенном массиве tags мы можем указать теги для докблока
‘name’ – название тега
‘description’ – текст следующий после него
Затем нам нужно объявить переменные использумые в этом классе
Это метод setProperties() входящий дня него параметр это массив переменных, каждая новая переменная будет описанна в новом массиве
в которм следуе указать свойства переменной
Или их можно описать через класс Zend_CodeGenerator_Php_Parameter
Предположим что нам нужны 2 переменные:
Или
Name – это название переменной
Visibility – модификатор доступа
Default value – значние по умолчанию, если не указать этот параметр то переменная будет равна null
Теперь наш класс может выглядеть так:
Конечно же нам понадобится описать методы этого класса
Для установки метода служит метод
Отличие лишь в количестве методов которые мы хотим установить,
Если вы выбрали первый путь то это может выглядеть это будет вот так:
Если второй то можно и так:
здесь 'name' — имя метода
‘parameters' — это входящие параметры каждый новый параметр описывается новым массивом, здесь всё точно так же как и для переменных внутри класса и вы так же можете использовать класс Zend_CodeGenerator_Php_Parameter()
‘body’ – это тело метода куда мы помещаем код который будет выполняться внутри метода в дном случае это, '$var = 'hello world';'. "\n". 'return $var', здесь стоит заметить что код автоматически не форматируется потому приходится использовать "\n" и "\t"
Докблоки в методах указываются точто так же как и для классов.
В конце всё что остаётся сделать это сгенерировать код и записать его в файл
Для этого используем стандартную фукцию php — file_put_contents и метод generate();
Который присутсвует во всех вышеописанных мною классов в Zend_CodeGenerator
Если вам будет удобнее то можно сгенерировать каждый элемент частями и по отдельности записать в файл.
Далее я приведу довольно яркий пример — класс который генерирует формы.
Вообще здесь есть куда разгулятся, например если тип данных в mysql — DATE то можно привязать вот это, оформив как декоратор, или сделать различные валидаторы для каждого типа данных. Полёт фантазии — не ограничен.
По мимо форм можно сгерировать практически всё что угодно — контроллры, модели тем самым избавив себя от лишней работы.
Или использовать Zend_Tool + Zend_Application для генерации структуры сайта и некоторых его классов из под консоли вашей операционной системы.
Конечно, код сгенерированный подобным образом требует доработки напильником, но всё же это займёт меньше времени чем писать его с самого начала.
Усиленно ждём релиза 1.8 версии, а пока разбираемся с нововведениями. Мне кажется, что разработчики Zend Framework в релизной версии сделают FormGenerator и ещё много всяких вкусностей.
P.S: Автор статьи Gibbzy.
Я хотел было потерпеть до релиза версии 1.8, но не удержался и решил всё таки попробавть «на зубок».
Мы будем генерировать класс формы на основе mysql таблицы.
Это действительно очень удобно и избавляет нас от порой рутинной работы.
Для начала нужно рассмотрим классы которые будем использовать.
Для создания php файла сущетвует класс
Zend_CodeGenerator_Php_File();
Его конструктор принимает массив в котором указываются классы находящиеся в этом файле. Например это можно сделать так:
$file = new Zend_CodeGenerator_Php_File(array('classes' => array($class)));
Где $class это экземпляр класса
Zend_CodeGenerator_Php_Class()
Классов может быть несколько для того чтобы сгенерировать несколько классов стоит указать их в массиве.
Но в стандартах кодирования для Zend_Framework сказано:
“Только один класс разрешен внутри одного PHP-файла.
Размещение дополнительно кода в файле с классом разрешено, но не приветствуется. В таких файлах, две пустые строки должны разделять класс и дополнительный PHP-код.”
Это дело субъективное и я бы всё таки сгенерировал по одному файлу на каждый класс,
Так более чётко прослеживается структура приложения.
Итак создадим новый класс:
$class = new Zend_CodeGenerator_Php_Class();
первый метод который нам понадобится это setName()
входящим параметром для него будет являться строка с наванием класса.
$class -> setName('MyClass')
Для того чтобы указать от какого класса будет наследоватся генерируемый класс используем метод
$class ->setExtendedClass('Myclass2')
Затем нам может понадобиться док блок,
$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.
В массиве, который являеться входящим параметром мы указываем
‘shortDescription' – краткое описание класса
'longDescription' полное описание класса
Во вложенном массиве tags мы можем указать теги для докблока
‘name’ – название тега
‘description’ – текст следующий после него
Затем нам нужно объявить переменные использумые в этом классе
Это метод setProperties() входящий дня него параметр это массив переменных, каждая новая переменная будет описанна в новом массиве
в которм следуе указать свойства переменной
Или их можно описать через класс Zend_CodeGenerator_Php_Parameter
Предположим что нам нужны 2 переменные:
$vars = array(
array(
'name' => ‘name,
'visibility' => 'public',
'defaultValue' => ‘0’,
)
array(
'name' => ‘_table’,
'visibility' => 'protected',
'defaultValue' => ‘1’,
)
);
Или
$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 – это название переменной
Visibility – модификатор доступа
Default value – значние по умолчанию, если не указать этот параметр то переменная будет равна null
Теперь наш класс может выглядеть так:
$class = new Zend_CodeGenerator_Php_Class();
$class -> setName('MyClass extends MyClass2') -> setProperties($vars) -> setDocblock($docblock);
Конечно же нам понадобится описать методы этого класса
Для установки метода служит метод
setMethod()
или setMethods()
Отличие лишь в количестве методов которые мы хотим установить,
setMethod()
принимает или экзепляр класса Zend_CodeGenerator_Php_Method или массив который описывает метод, setMethods()
принимает массив в котором содержатся объекты метода, или набор массивов.Если вы выбрали первый путь то это может выглядеть это будет вот так:
$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);
Если второй то можно и так:
$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',
)),
),
)),
)
здесь 'name' — имя метода
‘parameters' — это входящие параметры каждый новый параметр описывается новым массивом, здесь всё точно так же как и для переменных внутри класса и вы так же можете использовать класс Zend_CodeGenerator_Php_Parameter()
‘body’ – это тело метода куда мы помещаем код который будет выполняться внутри метода в дном случае это, '$var = 'hello world';'. "\n". 'return $var', здесь стоит заметить что код автоматически не форматируется потому приходится использовать "\n" и "\t"
Докблоки в методах указываются точто так же как и для классов.
В конце всё что остаётся сделать это сгенерировать код и записать его в файл
$code = $file->generate();
file_put_contents('file.php', $code);
Для этого используем стандартную фукцию php — file_put_contents и метод generate();
Который присутсвует во всех вышеописанных мною классов в Zend_CodeGenerator
Если вам будет удобнее то можно сгенерировать каждый элемент частями и по отдельности записать в файл.
Далее я приведу довольно яркий пример — класс который генерирует формы.
<?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.
Вообще здесь есть куда разгулятся, например если тип данных в mysql — DATE то можно привязать вот это, оформив как декоратор, или сделать различные валидаторы для каждого типа данных. Полёт фантазии — не ограничен.
По мимо форм можно сгерировать практически всё что угодно — контроллры, модели тем самым избавив себя от лишней работы.
Или использовать Zend_Tool + Zend_Application для генерации структуры сайта и некоторых его классов из под консоли вашей операционной системы.
Конечно, код сгенерированный подобным образом требует доработки напильником, но всё же это займёт меньше времени чем писать его с самого начала.
Усиленно ждём релиза 1.8 версии, а пока разбираемся с нововведениями. Мне кажется, что разработчики Zend Framework в релизной версии сделают FormGenerator и ещё много всяких вкусностей.
P.S: Автор статьи Gibbzy.