【问题标题】:Symfony3 Datatable unable to renderSymfony3 数据表无法呈现
【发布时间】:2017-02-01 22:49:39
【问题描述】:

在 MySQL 数据库中,我为 IPv4/IPv6 地址存储了一个 VARBINARY(16)。为了在表单上显示它,我创建了一个 DataTransformer 以使用内置的 inet_ptoninet_ntop 函数。

我想在数据表中显示它,因此可以通过 IP 地址进行搜索。不幸的是,通过使用我的典型数据表设置,我得到了 500 个服务器错误。

通过使用浏览器开发工具,我能够确定 AJAX 调用的结果是获取部分数据,实际 IP 地址被列为资源,而不是真实数据。

错误提示:无法标准化意外值:NULL

在堆栈跟踪中,我看到:

at Serializer ->normalize (resource, 'json', array()) 
in vendor/symfony/symfony/src/Symfony/Component/Serializer/Serializer.php at line 152

at Serializer ->normalize (array('id' => '5', 'ipAddress' => resource, 'sg_datatables_editable' => array(false), 'sg_datatables_actions' => array(array('network_ipaddress_show' => true))), 'json', array())
in vendor/symfony/symfony/src/Symfony/Component/Serializer/Serializer.php at line 152

at Serializer ->normalize (array(array('id' => '5', 'ipAddress' => resource, 'sg_datatables_editable' => array(false), 'sg_datatables_actions' => array(array('network_ipaddress_show' => true))), array('id' => '6', 'ipAddress' => resource, 'sg_datatables_editable' => array(false), 'sg_datatables_actions' => array(array('network_ipaddress_show' => true)))), 'json', array()) 
in vendor/symfony/symfony/src/Symfony/Component/Serializer/Serializer.php at line 152

at Serializer ->normalize (array('draw' => '1', 'recordsTotal' => '2', 'recordsFiltered' => '2', 'data' => array(array('id' => '5', 'ipAddress' => resource, 'sg_datatables_editable' => array(false), 'sg_datatables_actions' => array(array('network_ipaddress_show' => true))), array('id' => '6', 'ipAddress' => resource, 'sg_datatables_editable' => array(false), 'sg_datatables_actions' => array(array('network_ipaddress_show' => true))))), 'json', array()) 
in vendor/symfony/symfony/src/Symfony/Component/Serializer/Serializer.php at line 115

at Serializer ->serialize (array('draw' => '1', 'recordsTotal' => '2', 'recordsFiltered' => '2', 'data' => array(array('id' => '5', 'ipAddress' => resource, 'sg_datatables_editable' => array(false), 'sg_datatables_actions' => array(array('network_ipaddress_show' => true))), array('id' => '6', 'ipAddress' => resource, 'sg_datatables_editable' => array(false), 'sg_datatables_actions' => array(array('network_ipaddress_show' => true))))), 'json') 
in vendor/sg/datatablesbundle/Sg/DatatablesBundle/Datatable/Data/DatatableQuery.php at line 743

看到 JSON 调用,我实现了 JsonSerializable 接口,但似乎不是那样拉的。

虽然可以选择将 inet_pton 或 inet_ntop 直接放在实体中,但我相信我会失去验证。

我可以实现什么接口来允许 Datatables 提取我的 IPAddress 实体,并正确显示 IP 地址?

请注意,数据不会从实体 (VARBINARY) 转换为数据表所需的可读字符串。堆栈跟踪显示它是一个“资源”。

添加代码:

我的实体:

<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use JsonSerializable;

/**
 * @ORM\Table(name="ip_address")
 */
class IPAddress implements JsonSerializable
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var mixed
     * @ORM\Column(name="ip_address", type="binary", length=16, nullable=false, unique=true)
     */
    private $ipAddress;

    /**
     * Set IP Address
     * @param mixed $ipAddress
     * @return IPAddress
     */
    public function setIpAddress($ipAddress)
    {
        $this->ipAddress = $ipAddress;
        return $this;
    }
    /**
     * Get IP Address
     * @return mixed
     */
    public function getIpAddress()
    {
        return $this->ipAddress;
    }

    public function jsonSerialize()
    {
        return array(
            'ipAddress' => inet_pton($this->ipAddress),
        );
    }

数据表类:

<?php

namespace AppBundle\Datatables;
use Sg\DatatablesBundle\Datatable\View\AbstractDatatableView;
use Sg\DatatablesBundle\Datatable\View\Style;

/**
 * Class IPAddressDatatable
 * @package AppBundle\Datatables
 */
class IPAddressDatatable extends AbstractDatatableView
{
    /**
     * {@inheritdoc}
     */
    public function buildDatatable(array $options = array())
    {
        $this->features->set(array(
            'auto_width' => true,
            'defer_render' => false,
            ... other default features not listed ...
            'delay' => 0,
            'extensions' => array()
        ));

        $this->ajax->set(array(
            'url' => $this->router->generate('network_ipaddress_results'),
            'type' => 'GET'
        ));

        $this->options->set(array(
            'display_start' => 0,
            'defer_loading' => -1,
            ... other default options not listed ...
            'use_integration_options' => false,
            'force_dom' => false
        ));

        $this->columnBuilder
            ->add('ipAddress', 'column', array(
                'title' => 'IP Address',
                'width' => '85%',
            ))
            ->add(null, 'action', array(
                'title' => '',
                'width' => '15%',
                'actions' => array(
                    array(
                        'route' => 'network_ipaddress_show',
                        'route_parameters' => array(
                            'plan_id' => 'id'
                        ),
                        'label' => $this->translator->trans('datatables.actions.show'),
                        'icon' => 'fi-eye icon-size-14',
                        'attributes' => array(
                            'rel' => 'tooltip',
                            'title' => $this->translator->trans('datatables.actions.show'),
                            'class' => 'tiny button',
                            'role' => 'button'
                        ),
                    ),
                ),
            ));
    ;
    }

    ... getEntity and getName not shown for brevity ...
}

控制器(至少是相关部分):

/**
 * Lists all IP Addresses.
 *
 * @Route("/", name="network_ipaddress_index")
 * @Method("GET")
 * @return IPAddressController
 */
public function indexAction()
{
    $datatable = $this->get('app.datatable.ipaddress');
    $datatable->buildDatatable();

    return $this->render(':network:ipaddress_datatable.html.twig', array(
        'datatable' => $datatable,
    ));
}

/**
 * Returns a response, only used for datatables
 *
 * @Route("/results", name="network_ipaddress_results")
 * @Method("GET")
 * @return IPAddressController
 */
public function indexResultsAction()
{
    $datatable = $this->get('app.datatable.ipaddress');
    $datatable->buildDatatable();

    // I believe that the entity data would have to be translated here into printable a format

    $query = $this->get('sg_datatables.query')->getQueryFrom($datatable);

    return $query->getResponse();
}

【问题讨论】:

  • 除非您发布导致错误的代码,否则不要指望太多帮助...
  • 我添加了我的代码。实体类和数据表类非常通用,非常类似于github.com/stwe/DatatablesBundle 提供的演示应用程序。我遇到的问题是实体有一个我试图在数据表中显示的 VARBINARY 列,并且数据表正在获取资源 ID,而不是实际值。它需要获取该资源并使用 stream_get_contents 来获取可显示的内容(但即使这样也需要由 inet_pton 修改)。

标签: php mysql datatable symfony ipv6


【解决方案1】:

事实证明,stwe/DatatablesBundle 中有一个可用的闭包预渲染。

所以,上面Datatables类中需要的函数:

/**
 * {@inheritdoc}
 */
public function getLineFormatter()
{
    $formatter = function($line){
        $str = stream_get_contents($line['ipAddress']);
        if( strlen( $str ) == 16 OR strlen( $str ) == 4 ){
            $line['ipAddress'] = inet_ntop( pack( "A".strlen( $str ) , $str ) );
        }
        return $line;
    };
    return $formatter;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多