定制 popov/zfc-data-grid-plugin 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

popov/zfc-data-grid-plugin

Composer 安装命令:

composer require popov/zfc-data-grid-plugin

包简介

ZF module manager which extend possibility of ZfcDatagrid

README 文档

README

Welcome to the official ZfcDataGrid documentation. This documentation will help you to quickly understand how to use ZfcDataGrid.

If you are looking for some information that is not listed in the documentation, please open an issue!

ZF DataGrid Plugin Module based on ZfcDatagrid and is a kind of superstructure. Its main goal to reduce using complexity and improve code readability.

This module register new data_grid_plugins global config key and add ColumnFactory.

Working principle is using ZF2 way like Zend\Form which use array configuration for create form elements.

Important! DataGridPluginManager set $shareByDefault = false, this allow avoid redundant classes declaration in configuration.

Usage

Register Plugin. For this move content of vendor/popovserhii/zfc-data-grid-plugin/config/application.config.php.sample in global config/application.config.php

In general you create new Grid class which will be response for concrete Grid in your ecosystem.

namespace Popov\Invoice\Block\Grid;

use Popov\ZfcDataGrid\Block\AbstractGrid;

class InquiryGrid extends AbstractGrid
{
    public function init()
    {
        $grid = $this->getDataGrid();
        $grid->setId('invoice');
        $grid->setTitle('Invoices');
        $grid->setRendererName('jqGrid');
        
        // native configuration
        #$colId = new Column\Select('id', 'invoice');
        #$colId->setIdentity();
        #$grid->addColumn($colId);
        
        // array configuration
        $colId = $this->add([
            'name' => 'Select',
            'construct' => ['id', 'invoice'],
            'identity' => true,
        ])->getDataGrid()->getColumnByUniqueId('invoice_id');
        
        // native configuration
        #$col = new Column\Select('code', 'invoice');
        #$col->setLabel('Invoice code');
        #$col->setIdentity(false);
        #$grid->addColumn($col);
        
        // array configuration
        $this->add([
            'name' => 'Select',
            'construct' => ['code', 'invoice'],
            'label' => 'Код инвойса',
            'identity' => false,
        ]);
        
        // native configuration
        #$colType = new Type\DateTime();
        #$col = new Column\Select('createdAt', 'invoice');
        #$col->setLabel('Date Create');
        #$col->setTranslationEnabled();
        #$col->setType($colType);
        #$col->setWidth(2);
        #$grid->addColumn($col);
        
        // array configuration
        $this->add([
            'name' => 'Select',
            'construct' => ['createdAt', 'invoice'],
            'label' => 'Date Create',
            'translation_enabled' => true,
            'width' => 2,
            'type' => ['name' => 'DateTime'],
        ]);
        
        // native configuration
        #$col = new Column\Select('name', 'contractor');
        #$col->setLabel('Contractor');
        #$col->setTranslationEnabled();
        #$col->setWidth(3);
        #$col->setUserSortDisabled(true);
        #$col->setUserFilterDisabled(true);
        #$grid->addColumn($col);
        
        // array configuration
        $this->add([
            'name' => 'Select',
            'construct' => ['name', 'contractor'],
            'label' => 'Contractor',
            'width' => 3,
            'user_sort_disabled' => true,
            'user_filter_disabled' => true,
        ]);
        
        // native configuration
        #$bg = new Style\BackgroundColor([224, 226, 229]);
        #$fmtr = new Column\Formatter\Link();
        #$fmtr->setAttribute('class', 'pencil-edit-icon');
        #$fmtr->setLink('/invoice/view/' . $fmtr->getColumnValuePlaceholder($colId));
        #$actions = new Column\Action('edit');
        #$actions->setLabel(' ');
        #$actions->setTranslationEnabled();
        #$actions->setFormatters([$fmtr]);
        #$actions->addStyle($bg);
        #$actions->setWidth(1);
        #$grid->addColumn($actions);
        
        // array configuration
        $this->add([
            'name' => 'Action',
            'construct' => ['edit'],
            'label' => ' ',
            'width' => 1,
            'styles' => [
                [
                    'name' => 'BackgroundColor',
                    'construct' => [[224, 226, 229]],
                ],
            ],
            'formatters' => [
                [
                    'name' => 'Link',
                    'attributes' => ['class' => 'pencil-edit-icon'],
                    // next two line are identical
                    //'link' => ['href' => '/invoice/view/%s', 'placeholder_column' => 'invoice_id'],
                    'link' => ['href' => '/invoice/view/%s', 'placeholder_column' => $colId], // special config
                ],
            ],
        ]);
        
        $formatter = <<<FORMATTER_JS
      function (value, options, rowObject) {
        return '<div class="input-btn-group">'
        	+ '<button class="btn btn-default btn-xs barcode-print" title="{$this->__('Print Bar code')}">' + value + '</button>'
          + '</div>';
      }
FORMATTER_JS;
        
        // native configuration
        #$formatterLink = new Formatter\Barcode();
        #$formatterLink->setSourceAttr('data-barcode');
        #$formatterLink->setAttribute('class', 'barcode-icon');
        #$formatterLink->setBasedOn($grid->getColumnByUniqueId('product_id'));
        #$actions = new Column\Action('barcode');
        #$actions->setLabel(' ');
        #$actions->setTranslationEnabled();
        #$actions->setFormatters([$formatterLink]);
        #$actions->setRendererParameter('formatter', $formatterJs, 'jqGrid');
        #$actions->setWidth(1);
        #$grid->addColumn($actions);
        
        // array configuration
        $this->add([
            'name' => 'Action',
            'construct' => ['barcode'],
            'label' => ' ',
            'translation_enabled' => true,
            'width' => 1,
            'renderer_parameter' => ['formatter', $formatter, 'jqGrid'],
            'formatters' => [
                [
                    'name' => 'Barcode',
                    'source_attr' => 'data-barcode',
                    //'placeholder_column' => $grid->getColumnByUniqueId('product_id'),
                    'attributes' => [
                        'class' => 'barcode-icon',
                    ],
                ],
            ],
        ]);
    }
}

Columns

Columns Introduction

The column definition is a central part of ZfcDataGrid, they are used to tell the grid what columns to display and how to display them.

Column Types

Select

A minimal column definition looks like this:

$this->add([
    'name' => 'Select',
    'construct' => ['name', 'product'],
    'label' => 'Name',
]);
GROUP_CONCAT
Doctrine

Sometimes we need use built-in database functions for aggregate result. For this purpose we need give \Zend\Db\Sql\Expression or \Doctrine\ORM\Query\Expr\Func as argument to Select column.

$this->add([
	'name' => 'Select',
	'construct' => [new \Doctrine\ORM\Query\Expr\Select("GROUP_CONCAT(serial.number)"), 'serial_all'], // Doctrine usage
	// or 
	'construct' => [new \Doctrine\ORM\Query\Expr\Func('GROUP_CONCAT', ['serial.number']), 'serial_all'], // Doctrine usage
	'label' => 'Serial Number',
]);

Advanced Usage
Doctrine DOES NOT support expression below and throw Exception [Syntax Error] line 0, col 218: Error: Unexpected 'NULL':

$this->add([
	'name' => 'Select',
	// @see https://github.com/doctrine/orm/issues/5801
	'construct' => [new Expr\Func('GROUP_CONCAT', ['CASE WHEN serial.cartItem > 0 THEN serial.number ELSE NULL END']), 'serial_id'],
]);

Insteat of example above you can use NULLIF operator (which is supported):

$this->add([
   'name' => 'Select',
   'construct' => [new Expr\Select('GROUP_CONCAT(CASE WHEN serial.cartItem > 0 THEN serial.number ELSE NULLIF(1,1) END)'), 'serial_id'],
]);

Notice: Some functions like GROUP_CONCAT is represented only in one database so Doctrine don't support it by default so you need include relative package to you project.

ZendTable
$this->add([
	'name' => 'Select',
	'construct' => [new \Zend\Db\Sql\Expression ('GROUP_CONCAT(serial.number)'), 'serial_all'],
	'label' => 'Serial number',
]);

Column Data Types

Number

The Number (original: Type\Number) column data types is used to format numbers using the PHP NumberFormatter, and so you can use the NumberFormatter properties in this data type, to do so you create a Number object which can takes the following parameters in order:

  • Format Style: default NumberFormatter::DECIMAL
  • Format Type: default NumberFormatter::TYPE_DEFAULT
  • Locale: Default Locale::getDefault()

You can also do the following for this type:

  • 'type' => ['prefix' => 'prefix']
  • 'type' => ['suffix' => 'suffix']
  • 'type' => ['attribute' => ['attrName', 'attrValue']]

A usage Example of this column data type is the following:

$this->add([
    'name' => 'Select',
    'construct' => ['weight', 'product'],
    'label' => 'Weight',
    'type' => [
        'name' => 'Number',
        'attribute' => [\NumberFormatter::FRACTION_DIGITS, 2],
        'suffix' => ' kg'
    ],
]);

Column Data Styles

Align

The Align is used to change text direction of rows or columns of the grid, to create the Align do the following:

$this->add([
    'name' => 'Select',
    'construct' => ['price', 'product'],
    'label' => 'Asin',
    'styles' => [[
        'name' => 'Align',
        'construct' => ['right'],
    ]],
]);

or

$this->add([
    'name' => 'Select',
    'construct' => ['price', 'product'],
    'label' => 'Asin',
    'styles' => [[
        'name' => 'Align',
        'construct' => [\ZfcDatagrid\Column\Style\Align::$RIGHT],
    ]],
]);

If you set column type as Number the text direction automatically will be changed to right

$this->add([
    'name' => 'Select',
    'construct' => ['price', 'product'],
    'label' => 'Asin',
    'type' => [
        'name' => 'Number'
    ],
]);

BackgroundColor

The BackgroundColor is used to change background color of rows or columns of the grid, to create a BackgroundColor do the following:

$this->add([
    'name' => 'Select',
    'construct' => ['temperature', 'planet'],
    'label' => 'Temperature',
    'styles' => [[
        'name' => 'BackgroundColor',
        'constuct' => [200, 200, 200]
    ]],
]);

where the parameters are the color red green blue values.

To see how to apply style on rows or columns see the [Applying Style](#Applying Style) section.

Bold

The Bold style simply make the text bold, you can create a bold style like this:

$this->add([
    'name' => 'Select',
    'construct' => ['name', 'product'],
    'label' => 'Name',
    'styles' => [[
        'name' => 'Bold'
    ]],
]);

To see how to apply style on rows or columns see the [Applying Style](#Applying Style) section.

Color

The Color is used to change the color of rows or columns of the grid, to create a Color do the following::

$this->add([
    'name' => 'Select',
    'construct' => ['name', 'product'],
    'label' => 'Name',
    'styles' => [[
        'name' => 'Color',
        'consturct' => [200, 200, 200]
    ]],
]);

where the parameters are the color red green blue values.

To see how to apply style on rows or columns see the [Applying Style](#Applying Style) section.

Italic

The Italic style simply make the text italic, you can create an Italic style like this:

$this->add([
    'name' => 'Select',
    'construct' => ['name', 'product'],
    'label' => 'Name',
    'styles' => [[
        'name' => 'Italic'
    ]],
]);

where the parameters are the color red green blue values.

To see how to apply style on rows or columns see the [Applying Style](#Applying Style) section.

Strikethrough

The Strikethrough style simply make the text strikethrough, you can create a bold style like this:

$this->add([
    'name' => 'Select',
    'construct' => ['name', 'product'],
    'label' => 'Name',
    'styles' => [[
        'name' => 'Strikethrough'
    ]],
]);

To see how to apply style on rows or columns see the [Applying Style](#Applying Style) section.

CSSClass

The CSSClass is used to set additional classes attribute of rows or cells of the grid, to create a CSSClass do the following::

$this->add([
    'name' => 'Select',
    'construct' => ['name', 'product'],
    'label' => 'Name',
    'styles' => [[
        'name' => 'CSSClass',
        'class' => ['text-upper', 'product-name']
    ]],
]);

Applying Style

  • Apply only when the value of the column :product_price: = 50
$this->add([
    'name' => 'Select',
    'construct' => ['price', 'product'],
    'label' => 'Price',
    'styles' => [
        [
            'name' => 'Color',
            'construct' => [\ZfcDatagrid\Column\Style\Color::$RED],
            'byValue' => [[':product_price:', 50, \ZfcDatagrid\Filter::EQUAL]]
        ],
    ],
]);

You can add multiple conditions for the style using ByValue, and you can set the operator between the multiple conditions to be 'OR' or 'AND' like the following:

  • Apply only when the value of the column ':product_price:' between 20 and 40 (inclusive)
$this->add([
    'name' => 'Select',
    'construct' => ['price', 'product'],
    'label' => 'Price',
    'styles' => [
        [
            'name' => 'Color',
            'construct' => [\ZfcDatagrid\Column\Style\Color::$RED],
            'byValueOperator' => 'AND',
            'byValue' => [
                [':product_price:', 20, \ZfcDatagrid\Filter::GREATER_EQUAL],
                [':product_price:', 40, \ZfcDatagrid\Filter::LESS_EQUAL]
            ]
        ],
    ],
]);
  • Apply only when the value of the column ':order_quantity:' is greater or equal than the value of the column ':product_stock:'
$this->add([
    'name' => 'Select',
    'construct' => ['quantity', 'order'],
    'label' => 'Price',
    'styles' => [
        [
            'name' => 'Color',
            'construct' => [\ZfcDatagrid\Column\Style\Color::$GREEN],
            'byValue' => [[':order_quantity:', ':product_stock:', \ZfcDatagrid\Filter::LESS_EQUAL]]
        ],
    ],
]);

Notice. This functionality is not full tested!

Column Data Formatters

Link

The Link formatters displays a column content as an HTML link with value and href is the column content, to use it do the following:

$this->add([
    'name' => 'Select',
    'construct' => ['asin', 'product'],
    'label' => 'Asin',
    'formatters' => [[
        'name' => 'Link',
        'link' => ['href' => '//www.amazon.de/dp/%s', 'placeholder_column' => 'product_asin']
    ]],
]);

You also can pass Column object as 'placeholder_column'

$colId = $this->add([
    'name' => 'Select',
    'construct' => ['id', 'product'],
    'identity' => true,
])->getDataGrid()->getColumnByUniqueId('product_id');
        
$this->add([
    'name' => 'Select',
    'construct' => ['asin', 'product'],
    'label' => 'Asin',
    'formatters' => [[
        'name' => 'Link',
        'link' => ['href' => '//www.amazon.de/dp/%s', 'placeholder_column' => $colId]
    ]],
]);

The link formatter also support multiple placeholders for build url

$this->add([
    'name' => 'Select',
    'construct' => ['asin', 'product'],
    'label' => 'Asin',
    'formatters' => [[
        'name' => 'Link',
        'link' => ['href' => '//%s/dp/%s', 'placeholder_column' => ['marketplace_host', 'product_asin']]
    ]],
]);

Inline

Inline Formatter allow to show text in one line. This will be replace all <br>, \n and some other filtration for full compatibility with jqGrid.

$this->add([
    'name' => 'Select',
    'construct' => ['description', 'product'],
    'label' => 'Description',
    'formatters' => [[
        'name' => 'Inline',
    ]],
]);

ExternalLink

ExternalLink Formatter allow use full URL without inner rawurlencode preparation.

Preference is given to Link Formatter. Use in extreme cases.

$this->add([
    'name' => 'Select',
    'construct' => ['url', 'customer'],
    'label' => 'Customer Url',
    'hidden' => true
]);
$this->add([
    'name' => 'Select',
    'construct' => ['name', 'customer'],
    'label' => 'Customer Name',
    'formatters' => [[
        'name' => 'ExternalLink',
        'link' => ['href' => '%s', 'placeholder_column' => 'customer_url']
    ]],
]);

DropDown in search panel

Simple

Just put array with options to filter_select_options. Be carefully options are doubled wrapped with array.

$this->add([
    'name' => 'Select',
    'construct' => ['accepted', 'question'],
    'label' => 'Accepted',
    'width' => 1,
    'filter_select_options' => [[
        0 => 'No',
        1 => 'Yes'
    ]],
]);

Doctrine

filter_select_options config is based on DoctrineModule for Zend\Form (some options need implementation).

$this->add([
    'name' => 'Select',
    'construct' => ['value', 'handbook'],
    'label' => 'MarketOrder Type',
    'filter_select_options' => [
        'options' => [
            'object_manager' => $this->getObjectManager(),
            'target_class' => Handbook::class,
            'identifier' => 'value',
            'property' => 'value',
            'is_method' => true,
            'find_method' => [
                'name' => 'findAllByTypeId',
                'params' => [
                    'type' => 'purposeBid',
                    'field' => 'type'
                ],
            ],
        ],
    ],
]);

DropDown in Edit Record

Doctrine

It's similar to filter_select_options. column_select_options adds dropdown with selected data to Edit Record form.

$this->add([
    'name' => 'Select',
    'construct' => ['value', 'handbook'],
    'label' => 'MarketOrder Type',
    'column_select_options' => [
        'options' => [
            'object_manager' => $this->getObjectManager(),
            'target_class' => Handbook::class,
            'identifier' => 'value',
            'property' => 'value',
            'is_method' => true,
            'find_method' => [
                'name' => 'findAllByTypeId',
                'params' => [
                    'type' => 'purposeBid',
                    'field' => 'type'
                ],
            ],
        ],
    ],
]);

DatePicker in search panel

At this moment DatePicker require partial settings. You must carefully monitor the date formats.

$this->add([
    'name' => 'Select',
    'construct' => ['createdAt', 'question'],
    'label' => 'Date Create',
    'translation_enabled' => false,
    'width' => 1,
    'filter_default_operation' => Filter::LIKE_RIGHT, // LIKE "2018-03-16%"
    'type' => [
        'name' => 'DateTime',
        //'output_pattern' => 'yyyy-MM-dd HH:mm:ss',
        'output_pattern' => 'yyyy-MM-dd',
        'source_dateTime_format' => 'Y-m-d' // this date format will be used in WHERE statment
    ],
    'renderer_parameters' => [
        #['editable', true, 'jqGrid'],
        ['formatter', 'date', 'jqGrid'], // it is important for datepicker
        ['formatoptions', ['srcformat' => 'Y-m-d', 'newformat' => 'Y-m-d'], 'jqGrid'],
        ['searchoptions', ['sopt' => ['eq']], 'jqGrid'],
    ],
]);

Notice. Intl use default ISO date format (RFC 822). Detailed format explanation you can find in ZF documentation.

Grid Data Sorting

Default grid data sort can be set with sort_default option. ASC sort order will be applied to column position only if any other user filters did not apply before.

$this->add([
    'name' => 'Select',
    'construct' => ['position', 'product'],
    'label' => 'Position',
    'sort_default' => [1, 'ASC']
]);

Also several default sort orders can be set, simply apply sort_default to relative columns

$this->add([
    'name' => 'Select',
    'construct' => ['inStock', 'product'],
    'label' => 'Position',
    'sort_default' => [1, 'DESC']
]);
$this->add([
    'name' => 'Select',
    'construct' => ['position', 'product'],
    'label' => 'Position',
    'sort_default' => [2, 'ASC']
]);

Grid Data Filtering

Default grid data sort can be set with filter_default_operation option.

like filter will be applied by default if any other user filters did not apply before.

Notice! There is issue which don't allow apply filter from client side.

$this->add([
    'name' => 'Select',
    'construct' => ['sku', 'product'],
    'label' => 'SKU',
    'filter_default_operation' => \ZfcDatagrid\Filter::EQUAL
]);

Buttons

Buttons Introduction

Custom buttons for ZfcDataGrid.

Column Chooser

Object notation:

$button = new ColumnChooserButton();
        $button->setTitle('Choose columns');
        $button->setCaption('Choose');
        $button->setOptions([
                'width' => 500,
                'height' => 300,
        ]);

Config notation:

$this->addButton([
            'name' => 'ColumnChooser',
            'title' => 'Choose columns',
            'caption' => 'Choose',
            'options' => [
                [
                    'width' => 500,
                    'height' => 300,
                ],
            ],
        ]);

popov/zfc-data-grid-plugin 适用场景与选型建议

popov/zfc-data-grid-plugin 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 227 次下载、GitHub Stars 达 3, 最近一次更新时间为 2018 年 05 月 25 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「grid」 「zfc-datagrid」 「agere」 「zfc-datagrid factory」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 popov/zfc-data-grid-plugin 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 popov/zfc-data-grid-plugin 我们能提供哪些服务?
定制开发 / 二次开发

基于 popov/zfc-data-grid-plugin 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 227
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 3
  • 点击次数: 18
  • 依赖项目数: 1
  • 推荐数: 0

GitHub 信息

  • Stars: 3
  • Watchers: 2
  • Forks: 1
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2018-05-25