从PHP生成Javascript/ExtJS代码最易维护的方法是什么?

4
我正在创建一个PHP框架,允许PHP开发人员仅使用PHP类创建ExtJS前端,例如创建网格如下所示:
$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;
}

目前,有一些问题使得这段代码变得过于复杂难以维护:

  • 属性列表中,只有最后一个项目没有逗号,这使得列表的处理变得困难。到目前为止,我已经将必需的属性放在列表的末尾,以确保不带逗号的项始终被包含。

enter image description here

  • 某些功能(例如将复选框添加到网格中或否)需要在javascript代码的四个不同位置插入代码,我可以想象还有其他功能需要重构现有代码,因此如果启用该功能,则周围的代码需要被包含在对象的另一个部分中。

因此,我希望在某个时候进行重构,改进我的Javascript创建方式。

目前我只看到了一个选择,那就是创建一个CodeFactory类,其中包含ExtJsVariable,我可以向其中添加包含递归对象本身的对象,这些对象可以是simpleArrayanonymousFunction等类型,然后通过输出$codeFactory->render()来生成代码,该方法将基于其所有内部对象生成代码:

enter image description here

还有哪些选项或代码生成框架可以使PHP生成此Javascript/ExtJS代码更易于维护和简单明了?


1
也许 http://www.ext4yii.com/ 可以为您提供更多信息。 - Gajahlemu
3个回答

2

尽可能避免动态生成JS,将所有Javascript放在静态JS文件中(工厂和生成器在你的情况下最有可能)。并通过服务器生成JSON数据供其使用。这样可以严格改善结构,使应用程序更易于维护。您可能需要了解工厂模式和生成器模式。


0
事实上,我一直在用类似的方法从PHP(或者更具体地说,CakePHP)创建ExtJS代码。
在我的公司,我负责创建应用程序框架,以加速应用程序的生产。因此,我提出了我们的第一代框架,与您的想法相似:通过PHP生成代码。
很快,我意识到这会给服务器带来很大的负担,使得访问速度变慢。每次请求都需要重新生成代码,这是不切实际的。之后不久,我推出了具有缓存能力的第二代框架。生成的JS代码被缓存在静态文件中,并在需要时动态包含。缓存的原因是大多数情况下JS代码都是静态的,只有内容、存储等方面发生变化。
所以这种方法运行了几个月,直到我最终意识到这并不是正确的方式,例如,
  • 无法通过这种方式生成TreePanel,特别是带有动态菜单的情况。
  • ACL不能干扰缓存代码。
  • 网格中不能有动态列。
  • 我的框架设计得很糟糕,需要在看到结果之前缓存代码 - 开发速度慢。
  • 难以维护,难以调用。像添加一个配置或删除一个配置这样的简单事情可能会很繁琐。就像使用FormHelper完成简单的事情一样繁琐。

因此,我完全重写了我的代码库,重新设计了一切,直到我想出了这个当前美丽的ExtJS + CakePHP框架,它具有以下特点:

创建了通用的GridPanel/Store/View/Pagination/Editor组件,只需进行简单的配置,就可以获得一个完整的REST Grid,连接到Cake的控制器之一。在Cake中,您可以包含特别设计的组件之一,并仅使用几行代码即可创建一个完整工作的REST网格。
特别设计的Viewport提供类似的外观和感觉,配合特别设计的TreePanel(菜单)、TabPanel(内容)等。
还有许多其他通用的、有用的组件被打包在一起,如Wizard、FieldEditor、UserImport等。
由于它们都是可扩展的ExtJS组件,您可以使用它、扩展它、完全定制它,以满足您的任何需求。
很抱歉如果这听起来对您不太对劲,但就我个人而言,我经历过这个,对从PHP生成代码的结果真的不满意。您基本上会使整个过程变得复杂化或减慢速度。
顺便说一句,对我的糟糕英语表示歉意。感谢您阅读此文章。
由于它是公司的财产的一部分,因此我无法分享我的代码也无法开源它。

0

我会提出一些建议,因为我也做过类似的事情。

首先,尽量将尽可能多的内容移入库类中。 其次,你可以创建一个PHP数据结构,并使用json_encode将其转换为JSON格式。

最后,保持简单!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接