Я создаю среду PHP, которая позволяет разработчику PHP создавать интерфейс ExtJS только с классами PHP, например, создание сетки выглядит следующим образом:
$grid_import = new Backend_Layout_Grid('smart_worksheets');
$grid_import->set_width(1300);
$grid_import->set_rows_selectable(true);
$grid_import->set_title(__('backend.application.import.grid.title'));
$grid_import->set_margin('10px'); //CSS syntax, e.g. also "10px 0 0 0"
$grid_import->add_column(array('id_code'=>'name', 'label'=> __('backend.application.import.worksheetstoimport'), 'width'=>'300'));
$grid_import->add_column(array('id_code'=>'kind', 'label'=> __('backend.application.import.kind'), 'width'=>'50'));
$grid_import->add_column(array('id_code'=>'file_size', 'label'=> __('backend.application.import.sizebyte'), 'datatype' => 'int'));
$grid_import->add_column(array('id_code'=>'when_file_copied', 'label'=> __('backend.application.import.whenfilecopied'), 'datatype' => 'datetime', 'width'=>'150'));
$grid_import->add_column(array('id_code'=>'table_name', 'label'=> __('backend.application.import.mysqltablename'), 'width'=>'300'));
$grid_import->add_column(array('id_code'=>'when_table_created', 'label'=> __('backend.application.import.whentablecreated'), 'width'=>'160'));
$grid_import->add_column(array('id_code'=>'status', 'label'=> __('backend.application.import.status'), 'width'=>'300'));
$grid_import->set_doubleclick_target_uri('backend/application/importmanager/single', 0);
if (count($smart_worksheets) > 0)
{
$row_index = 0;
foreach ($smart_worksheets as $smart_worksheet)
{
$show_row = array(
'name' => $smart_worksheet['name'],
'kind' => $smart_worksheet['kind'],
'file_size' => $smart_worksheet['file_size'],
'when_file_copied' => $smart_worksheet['when_file_copied'],
'table_name' => $smart_worksheet['table_name'],
'when_table_created' => __($smart_worksheet['when_table_created']),
'status' => __($smart_worksheet['status'])
);
$grid_import->add_row($show_row);
if(in_array($smart_worksheet['status'], array('backend.application.import.status.needtoimport', 'backend.application.import.status.needtoreimport'))) {
$grid_import->add_row_format($row_index, Backend_Layout_Grid::ROW_FORMAT_RED);
}
if(in_array($smart_worksheet['status'], array('backend.application.import.status.isuptodate'))) {
$grid_import->add_row_format($row_index, Backend_Layout_Grid::ROW_FORMAT_GREEN);
}
if(intval($smart_worksheet['file_size']) > 4000000 AND (in_array($smart_worksheet['kind'], array('XLS','XLSX'))))
{
$grid_import->add_row_format($row_index, Backend_Layout_Grid::ROW_FORMAT_GRAY);
}
$row_index++;
}
}
Backend_Layout_Window::instance()->add_item($grid_import);
Пока это работает хорошо, нопоскольку я просто выводил код javascript построчно, чем больше функций я встраиваю в класс, тем сложнее логика if / then при построении необработанного текста Javascript, вот типичный метод , которыйгенерирует код Javascript:
public function render_main_code_block()
{
$retval = '';
$retval .= $this->render_data_variable();
$retval .= $this->render_array_reader_block();
$retval .= $this->render_grid_panel_block();
if($this->rows_selectable)
{
$retval .= self::render_line("````}),");
$retval .= self::render_line("````sm: sm,");
}
$retval .= self::render_line("````viewConfig: {");
if ($this->percentage_columns)
{
$retval .= self::render_line("``````forceFit: true,"); // true = percentage column width (add up to 100)
}
else
{
$retval .= self::render_line("``````forceFit: false,");
}
$retval .= self::render_line("``````getRowClass: function(record, rowIndex, rp, ds){");
if (count($this->row_formats) > 0)
{
foreach ($this->row_formats as $row_index => $row_format)
{
$retval .= self::render_line("````````if(rowIndex == ".$row_index."){");
$retval .= self::render_line("``````````return '".$row_format."';");
$retval .= self::render_line("````````}");
}
}
$retval .= self::render_line("````````return '';");
$retval .= self::render_line("``````}");
$retval .= self::render_line("````},");
$retval .= self::render_line("````title: '$this->title',");
if ( ! is_null($this->width))
{
$retval .= self::render_line("````width: $this->width,");
}
$retval .= $this->render_double_click_handler();
$retval .= self::render_line("````autoHeight: true,");
$retval .= self::render_line("````frame: true");
$retval .= self::render_line("``});");
$retval .= self::render_line("");
$retval .= self::render_line("``replaceComponentContent(targetRegion, ".$this->script_variable_name.");");
$retval .= self::render_line("``".$this->script_variable_name.".getSelectionModel().selectFirstRow();");
// for word wrapping in columns
$retval .= self::render_line("``function columnWrap(val){");
$retval .= self::render_line("````return '<div style=\"white-space:normal !important;\">'+ val +'</div>';");
$retval .= self::render_line("``}");
return $retval;
}
Некоторые конкретные проблемы, из-за которых этот код становится слишком сложным для обслуживания:
- простой факт, что в списках свойств только последний элемент не имеет запятой .До сих пор я был в состоянии поместить обязательные свойства в конец списка, чтобы элемент без запятой всегда был включен.
- и некоторые функции (такие как добавление флажков в сетку или нет) требуют вставки кода в до четырех различных местах в коде javascript , и я могу представить, что есть функции, которые потребуют реструктуризации существующего кода, поэтому, если функция включена, окружающий код должен, например, содержаться в другом разделе объекта
Так что в какой-то момент я хочу рефакторинг так, как я создаюJavascript.
В настоящее время я вижу только один вариант , например, для создания класса CodeFactory
, который содержит, например, ExtJsVariable
, к которому я добавляю объекты, которые сами содержат объекты рекурсивно, объектыможет иметь тип, например, simpleArray
или anonymousFunction
и т. д., а затем для создания кода я бы вывел $codeFactory->render()
, который дал бы мне код, основанный на всех его внутренних объектах:
Какие еще варианты или структуры генерации кода я мог бы использовать, чтобы сделать генерацию этого кода Javascript / ExtJS из PHP более понятной и понятной?