繁体   English   中英

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

[英]What is the most maintainable approach to generating Javascript/ExtJS code from PHP?

我正在创建一个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;
}

一些使该代码难以维护的特殊问题是:

  • 一个简单的事实,即在属性列表中,只有最后一项没有逗号 到目前为止,我已经能够在列表的末尾放置必需的属性,以便始终包含不带逗号的项目。

在此处输入图片说明

  • 某些功能(例如是否在网格中添加复选框) 需要在javascript代码的四个不同位置插入代码 ,我可以想象有些功能需要对现有代码进行重组,因此如果该功能是打开时,周围的代码需要例如包含在对象的另一部分中

因此,在某些时候,我想重构创建Javascript的方式。

我目前看到的只有一个选项真的 ,创造如CodeFactory类,其中包含如ExtJsVariable到我添加包含对象本身递归,对象的类型可以是例如对象simpleArrayanonymousFunction等,然后创建代码,我会输出$codeFactory->render()它将基于所有内部对象为我提供代码:

在此处输入图片说明

还有什么其他选项或代码生成框架可以用来使从PHP生成此Javascript / ExtJS代码更可维护和更直接?

最好的方法是尽可能避免动态生成JS,并将所有Javascript保留在静态JS文件中(工厂,可能是您所使用的构建器)。 并向它们提供从服务器生成的JSON数据。 这将大大改善结构,并使您的应用程序更易于维护。 您可能需要阅读有关Factory和Builder模式的信息。

实际上,我一直在尝试通过类似的方法从PHP或从CakePHP创建ExtJS代码。

在我公司中,我负责创建可加快应用程序生产速度的应用程序框架,因此实际上我提出了我们的第一代框架,该框架类似于您的想法:通过PHP生成代码。

然后我很快意识到这对于服务器来说是沉重的,而且很慢。 您收到的每个请求都需要重新生成代码,这是不切实际的。 在我推出具有缓存功能的第二代后不久。 生成的JS代码被缓存到静态文件中,并在需要时动态包含在内。 缓存的原因是因为大多数时候JS代码是静态的,更改是内容,存储等。

所以这种方法可以工作几个月,直到我终于意识到这不是正确的方法,例如,

  • 无法通过这种方式生成TreePanel ,尤其是对于动态菜单。
  • ACL无法干扰缓存的代码
  • 网格中不能有动态列
  • 我的框架设计糟糕,需要在看到结果之前先缓存代码-开发缓慢。
  • 很难维护,很难打电话。 添加一个配置或删除一个配置等简单的事情可能很乏味。 就像使用FormHelper来完成简单的东西一样乏味。

因此,然后我完全重写了我的代码库,重新设计了所有内容,直到提出了这个当前漂亮的ExtJS + CakePHP框架,该框架:

  • 创建了通用的GridPanel / Store / View / Pagination / Editor组件,并且只需进行一些简单的配置即可获得一个完整的REST网格,该网格可以连接到Cake的控制器之一。 在Cake中,您包含了一个特别设计的组件,只需几行代码就可以创建一个完整的REST网格。
  • 特殊设计的视口,提供类似的外观和感觉,并具有特殊设计的TreePanel(菜单),TabPanel(内容)
  • 以及许多其他有用的通用组件,例如向导,FieldEditor,UserImport ...等。
  • 并且由于它们都是可扩展的ExtJS组件,因此您可以使用它,对其进行扩展,并完全根据需要对其进行自定义。

抱歉,这听起来不对劲,但是就我个人而言,我已经经历了这一点,对于使用PHP生成代码的结果,我真的感到不满意。 基本上,您最终会使整个过程变得复杂,或者使事情变慢。

抱歉,我的英语不好。 并感谢您阅读本文。

而且我不能共享我的代码,也不能将其开源,因为它是公司财产的一部分。

我也会提出一些建议,因为我也做了一些建议。

首先,尽可能多地移入库类中;其次,您可以创建一个PHP数据结构,并使用json_encode将其转换为JSON。

最后,保持简单!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM