Magento 2 - campo da grade de administração personalizada - erro ao classificar ou filtrar

9

Adicionei coluna personalizada à grade do administrador, assim

<column name="customer_name" class="Vendor\Module\Ui\Component\Listing\Columns\CustomerName">
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="filter" xsi:type="string">text</item>
                <item name="editor" xsi:type="string">text</item>
                <item name="sortable" xsi:type="string">true</item>
                <item name="label" xsi:type="string" translate="true">Customer Name</item>
                <item name="sortOrder" xsi:type="number">30</item>
            </item>
        </argument>
    </column>

Na minha classe CustomerName, crio valores para esta coluna:

public function prepareDataSource(array $dataSource)
{
    $fieldName = $this->getData('name');
    foreach ($dataSource['data']['items'] as & $item) {
        $customer = $this->customerRepository->getById($item['customer_id']);
        $name = $customer ? $customer->getFirstName().' <'.$customer->getEmail().'>' : '';
        $item[$fieldName] = $name;
    }
    return $dataSource;
}

É exibido na grade conforme o esperado. Mas quando tento classificar por esta coluna ou filtro - ocorre um erro

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'customer_name' in 'order clause'

Como posso consertar isso?

ATUALIZAR

Agora, tento resolver esse problema excluindo a classe CustomerName (e removendo a referência na tag da coluna em xml). Em vez disso, adicionei a função _renderFiltersBefore () na minha classe de coleção

 protected function _renderFiltersBefore() {
     $joinTable = $this->getTable('customer_entity');
     $this->getSelect()->join($joinTable.' as customer_entity','main_table.customer_id = customer_entity.entity_id', array('*'));
     $this->getSelect()->columns('CONCAT(firstname," <",email,">") as customer_name');
     parent::_renderFiltersBefore();
}

Agora a classificação está funcionando, mas a filtragem não (obtenha o mesmo erro)

Anna
fonte

Respostas:

13

Existe um método de fábrica que você pode usar, e este é o addFilterToMap(). Onde o filtro de renderização Magento 2 apenas substitui os assuntos das condições com base nos campos mapeados

você pode chamá-lo tanto em _initSelect ou _renderFiltersBefore método.

para uma coluna simples que já existe na seleção (bom para resolver erros ambíguos)

$this
     ->addFilterToMap('customer_id', 'ce.entity_id');

mas, no seu caso, precisa mapear uma expressão como

$this
    ->addFilterToMap(
       'customer_name ', 
       new \Zend_Db_Expr('CONCAT(ce.firstname," <",ce.email,">")')
    ); 

então a parte da condição da consulta será em ... WHERE (CONCAT(ce.firstname," <",ce.email,">") LIKE '%@yippie.com%') ... vez de ... WHERE (customer_name LIKE '%@yippie.com%') ...

Também é possível usar outro método de fábrica relacionado à coleção para usar expressões em SELECTparte da consulta

$this
    ->addExpressionFieldToSelect(
        'firstname',
        new \Zend_Db_Expr('CONCAT(ce.firstname," <",ce.email,">")'),
        []
    )

ao invés de

$this->getSelect()->columns('CONCAT(ce.firstname," <",ce.email,">") as firstname');
Mammouth
fonte
Muito obrigado! Estava lutando com isso por meio dia. Onde você encontrou / aprendeu isso? Certamente, não nos documentos?
Jānis Elmeris
como a postagem original mencionou: teve que adicionar uma coluna personalizada à grade do administrador - com opções de filtro e classificação. Custo cerca de 1,5 dias para descobrir isso (OFC com menos pegada)
Mammouth
Estou tentando exibir os increment_ids da fatura e do pedido de venda na minha grade de administração do módulo personalizado com o ID de incremento do pedido de venda redefinido como 'ordincrementid'. Ainda assim, eu tinha usado o addFilterToMap (); Não consigo filtrar o pedido de venda increment_id. Ele retornando esse erro => Coluna 'increment_id' na cláusula where é ambígua
Ask Bytes
6

Demorou algum tempo, mas eu descobri isso

Na minha listagem xml:

<column name="firstname">
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="filter" xsi:type="string">text</item>
                <item name="editor" xsi:type="string">text</item>
                <item name="sortable" xsi:type="string">true</item>
                <item name="label" xsi:type="string" translate="true">Customer Name</item>
                <item name="sortOrder" xsi:type="number">30</item>
            </item>
        </argument>
    </column>

Em Fornecedor \ Módulo \ Modelo \ ResourceModel \ SomeCustomModel \ Grid:

/**
 * adding email to customer name column
 */
protected function _initSelect()
{
    parent::_initSelect();
    $this->getSelect()->joinLeft(
        ['ce' => $this->getTable('customer_entity')],
        'main_table.customer_id = ce.entity_id',
        ['*']
    );

    $this->getSelect()->columns('CONCAT(ce.firstname," <",ce.email,">") as firstname');
    return $this;
}

Em Fornecedor \ Módulo \ Modelo \ ResourceModel \ SomeCustomModel

/**
 * addding ability to filter by column with customer name and email
 */
protected function _renderFiltersBefore()
{
    $wherePart = $this->getSelect()->getPart(\Magento\Framework\DB\Select::WHERE);
    foreach ($wherePart as $key => $cond) {
        $wherePart[$key] = str_replace('`firstname`', 'CONCAT(firstname," <",email,">")', $cond);
    }
    $this->getSelect()->setPart(\Magento\Framework\DB\Select::WHERE, $wherePart);
    parent::_renderFiltersBefore();
}
Anna
fonte