Dodawanie kolumn do siatki klientów za pomocą obserwatora lub przesłanianie siatki klientów

28

Mam problem z dodaniem kolumny do siatki klientów i wyświetlaniem wartości w tej kolumnie.

Oto kod obserwatora, który próbowałem wyświetlić kolumnę: -

if ($block->getType() == 'adminhtml/customer_grid') {
          $customer = $observer->getCustomer();
          $collection = Mage::getResourceModel('customer/customer_collection');
        $block->addColumnAfter('mobile', array(
                'header'    => 'Mobile No.',
                'type'      => 'text',
                'index'     => 'mobile',
            ), 'email');
        }   

Dodaje to kolumnę, ale pod nią nie są wyświetlane żadne wartości.

Kuldeep
źródło
Na jakim wydarzeniu to robisz? Prawdopodobnie kolekcja siatki nie ma ruchomej kolumny i musisz również dodać tę kolumnę do kolekcji. Powinien być dostępny w$block->getCollection()
Zefiryn,
@Zefiryn jak mogę to zrobić? Jak mogę dodać kolumnę mobilną do kolekcji za pomocą obserwatora?
Kuldeep
1
@Kuldeep Druga odpowiedź jest lepsza, ponieważ pozwala uniknąć powielania kodu. Możesz to zaakceptować.
Alex

Odpowiedzi:

25

Aby dodać kolumnę do siatki klientów, musisz przesłonić 2 elementy w bloku Mage_Adminhtml_Block_Customer_Grid.

  • _prepareCollection - aby dodać swój atrybut do kolekcji
  • _prepareColumns - aby dodać kolumnę do siatki.

W tym celu należy utworzyć nowe rozszerzenie. Nazwijmy to Easylife_Customer. Do tego potrzebne będą następujące pliki:
app/etc/module/Easylife_Customer.xml- plik deklaracji

<?xml version="1.0"?>
<config>
    <modules>
        <Easylife_Customer>
            <active>true</active>
            <codePool>local</codePool>
            <depends>
                <Mage_Customer /><!-- your module should depend on Mage_Customer -->
                <Mage_Adminhtml /><!-- your module should depend on Mage_Adminhtml also -->
            </depends>
        </Easylife_Customer>
    </modules>
</config>

app/code/local/Easylife/Customer/etc/config.xml - plik konfiguracyjny

<?xml version="1.0"?>
<config>
    <modules>
        <Easylife_Customer>
            <version>0.0.1</version>
        </Easylife_Customer>
    </modules>
    <global>
        <blocks>
            <adminhtml>
                <rewrite>
                    <customer_grid>Easylife_Customer_Block_Adminhtml_Customer_Grid</customer_grid><!-- rewrite the customer grid -->
                </rewrite>
            </adminhtml>
        </blocks>
    </global>
</config>

app/code/local/Easylife/Customer/Block/Adminhtml/Customer/Grid.php- twoja własna wersja siatki klientów. Przeczytaj moje komentarze w kodzie:

<?php
class Easylife_Customer_Block_Adminhtml_Customer_Grid extends Mage_Adminhtml_Block_Customer_Grid{
    /**
     * override the _prepareCollection to add an other attribute to the grid
     * @return $this
     */
    protected function _prepareCollection(){
        $collection = Mage::getResourceModel('customer/customer_collection')
            ->addNameToSelect()
            ->addAttributeToSelect('email')
            ->addAttributeToSelect('created_at')
            ->addAttributeToSelect('group_id')
            //if the attribute belongs to the customer, use the line below
            ->addAttributeToSelect('mobile')
            //if the attribute belongs to the customer address, comment the line above and use the one below
            //->joinAttribute('mobile', 'customer_address/mobile', 'default_billing', null, 'left')
            ->joinAttribute('billing_postcode', 'customer_address/postcode', 'default_billing', null, 'left')
            ->joinAttribute('billing_city', 'customer_address/city', 'default_billing', null, 'left')
            ->joinAttribute('billing_telephone', 'customer_address/telephone', 'default_billing', null, 'left')
            ->joinAttribute('billing_region', 'customer_address/region', 'default_billing', null, 'left')
            ->joinAttribute('billing_country_id', 'customer_address/country_id', 'default_billing', null, 'left');

        $this->setCollection($collection);
        //code from Mage_Adminhtml_Block_Widget_Grid::_prepareCollection()
        //since calling parent::_prepareCollection will render the code above useless
        //and you cannot call in php parent::parent::_prepareCollection()
        if ($this->getCollection()) {

            $this->_preparePage();

            $columnId = $this->getParam($this->getVarNameSort(), $this->_defaultSort);
            $dir      = $this->getParam($this->getVarNameDir(), $this->_defaultDir);
            $filter   = $this->getParam($this->getVarNameFilter(), null);

            if (is_null($filter)) {
                $filter = $this->_defaultFilter;
            }

            if (is_string($filter)) {
                $data = $this->helper('adminhtml')->prepareFilterString($filter);
                $this->_setFilterValues($data);
            }
            else if ($filter && is_array($filter)) {
                $this->_setFilterValues($filter);
            }
            else if(0 !== sizeof($this->_defaultFilter)) {
                $this->_setFilterValues($this->_defaultFilter);
            }

            if (isset($this->_columns[$columnId]) && $this->_columns[$columnId]->getIndex()) {
                $dir = (strtolower($dir)=='desc') ? 'desc' : 'asc';
                $this->_columns[$columnId]->setDir($dir);
                $this->_setCollectionOrder($this->_columns[$columnId]);
            }

            if (!$this->_isExport) {
                $this->getCollection()->load();
                $this->_afterLoadCollection();
            }
        }

        return $this;
    }

    /**
     * override the _prepareColumns method to add a new column after the 'email' column
     * if you want the new column on a different position just change the 3rd parameter
     * of the addColumnAfter method to the id of your desired column
     */
    protected function _prepareColumns(){
        $this->addColumnAfter('mobile', array(
            'header'    => Mage::helper('customer')->__('Mobile'),
            'index'     => 'mobile'
        ),'email');
        return parent::_prepareColumns();
    }
}

Wyczyść pamięć podręczną i powinieneś być gotowy.

Marius
źródło
Dzięki człowieku, ty rock .. działało jak urok: D .. Dziękuję bardzo.
Kuldeep
Jak znalazłem w tej odpowiedzi , możesz wywołać metodę dziadka według nazwy klasy, w tym przypadku w następujący sposób:Mage_Adminhtml_Block_Widget_Grid::_prepareCollection();
kiatng
To nie nazywa methot dziadka. Nazywasz metodę niestatyczną za atatyczną. To nie w porządku.
Marius
39

Droga obserwatorów:

Zadeklaruj 2 obserwatorów w pliku config.xml: jeden, aby dodać kolumnę do bloku siatki, a drugi, aby załadować dane z odpowiedniego atrybutu:

<adminhtml>
    <events>
        <core_block_abstract_to_html_before>
            <observers>
                <{observer_name}>
                    <type>singleton</type>
                    <class>{namespace}_{module}/observer</class>
                    <method>beforeBlockToHtml</method>
                </{observer_name}>
            </observers>
        </core_block_abstract_to_html_before>
        <eav_collection_abstract_load_before>
            <observers>
                <{observer_name}>
                    <class>{namespace}_{module}/observer</class>
                    <method>beforeCollectionLoad</method>
                </{observer_name}>
            </observers>
        </eav_collection_abstract_load_before>
    </events>
</adminhtml>

Utwórz klasę Observer za pomocą odpowiednich metod:

class {Namespace}_{Module}_Model_Observer
{
    public function beforeBlockToHtml(Varien_Event_Observer $observer)
    {
        $grid = $observer->getBlock();

        /**
         * Mage_Adminhtml_Block_Customer_Grid
         */
        if ($grid instanceof Mage_Adminhtml_Block_Customer_Grid) {
            $grid->addColumnAfter(
                '{column_code}',
                array(
                    'header' => Mage::helper('{Module}_customer')->__('{{column_name}}'),
                    'index'  => '{column_code}'
                ),
                'entity_id'
            );
        }
    }

    public function beforeCollectionLoad(Varien_Event_Observer $observer)
    {
        $collection = $observer->getCollection();
        if (!isset($collection)) {
            return;
        }

        /**
         * Mage_Customer_Model_Resource_Customer_Collection
         */
        if ($collection instanceof Mage_Customer_Model_Resource_Customer_Collection) {
            /* @var $collection Mage_Customer_Model_Resource_Customer_Collection */
            $collection->addAttributeToSelect('{attribute_code}');
        }
    }
}
Arnaud AKA Narno
źródło
1
Zdecydowanie najlepsza opcja. Bez przepisywania
Sylvain Rayé
Niestety nie działa w przypadku eksportu CSV - brakuje tam kolumny.
Alex
Jak by to było na stronie siatki produktów?
frostshoxx
Przepisywanie jest znacznie lepsze niż obserwator
hkguile
Po prostu poleciłbym użycie tego wydarzenia w Mage_Adminhtml_Block_Widget_Grid :: Mage_Adminhtml_Block_Widget_Grid (), który jest bardziej specjalistyczny.
Christophe Ferreboeuf
9

Odpowiadam na komentarz Alexa:

Aby wyeksportować do pliku CSV, również użyj

core_block_abstract_prepare_layout_before

zamiast

core_block_abstract_to_html_before
John MWK
źródło
4

Zakładając, że $blockjest to przypadek Mage_Adminhtml_Block_Customer_Gridwtedy

$block->getCollection()powinien zwrócić kolekcję klientów używaną w siatce, która jest instancją Mage_Customer_Model_Resource_Customer_Collection. Gdy spojrzysz na kod Mage_Adminhtml_Block_Customer_Grid::_prepareCollection(), zobaczysz, jak możesz dodać atrybut do tej kolekcji.

Powinien być (choć nie testowany)

zakładając, że do jednostki klienta dodano atrybut mobilny

$block->getCollection()
      ->addAttributeToSelect('mobile');

lub jeśli komórka jest dodana do atrybutu adresu encji rozliczeniowej

$block->getCollection()
      ->joinAttriubte('mobile','customer_address/mobile','defaul_billing',null,'left');
Zefiryn
źródło
Witaj @Zefiryn, próbowałem obu kodów, które przesłałeś, ale żaden z nich nie działa
Kuldeep
Powiedz mi, na jakim wydarzeniu prowadzisz tego obserwatora
Zefiryn,
Jest to dobre podejście, ale działa tylko podczas eksportowania siatki. Dzieje się tak dlatego, że w końcu Mage_Adminhtml_Block_Widget_Grid::_prepareCollectionto się nazywa: $this->getCollection()->load(). Oznacza to, że wszelkie inne modyfikacje kolekcji są ignorowane. Ale, jak powiedziałem, jest to bardzo dobre podejście do eksportowania siatki. Podczas eksportu loadmetoda jest wywoływana dopiero znacznie później.
Marius
2

Inny sposób:

Przepisz blok siatki klientów za pomocą niestandardowego modułu i użyj setCollection()funkcji, aby pobrać niestandardowy atrybut.

app / code / [local or community] /YourCompany/YourModule/etc/config.xml

<?xml version="1.0"?>
<config>
    <modules>
        <yourcompany_yourmodule>
            <version>0.1.0</version>
        </yourcompany_yourmodule>
    </modules>
    <global>
        <blocks>
            <adminhtml>
                <rewrite>
                    <customer_grid>YourCompany_YourModule_Block_Customer_Grid</customer_grid>
                </rewrite>
            </adminhtml>
        </blocks>
    </global>
</config>

app / code / [local or community] /YourCompany/YourModule/Block/Customer/Grid.php

<?php

class YourCompany_YourModule_Block_Customer_Grid extends Mage_Adminhtml_Block_Customer_Grid
{
    public function setCollection($collection)
    {
        // your field/attribute to fetch, assuming it to be 'mobile'
        $collection->addAttributeToSelect('mobile'); 
        parent::setCollection($collection);
    }

    protected function _prepareColumns()
    {
        parent::_prepareColumns();

        $this->addColumn('mobile', array(
                'header'=> Mage::helper('customer')->__('Mobile'),
                'index' => 'mobile',
                'type'  => 'text',
                'width' => '100px',
        ));

        // show your new column named 'mobile' after ZIP column
        $this->addColumnsOrder('mobile', 'billing_postcode');

        return parent::_prepareColumns();
    }
}
Mukesh Chapagain
źródło
1
Dzięki za kod. Jak teraz wydajemy zamówienie, aby wyświetlić ten atrybut w siatce klientów?
Prince Patel
Możesz uporządkować kolumnę za pomocą addColumnsOrderfunkcji. Sprawdź zaktualizowaną odpowiedź.
Mukesh Chapagain
Użyłem $ this-> addColumnAfter (), ale $ this-> addColumnsOrder () również działa dzięki za twoją odpowiedź.
Prince Patel
IMHO Użyj setCollection () jest właściwie najlepszym rozwiązaniem (nie lubię dodawać obserwatora do wszystkich zdarzeń loadcollection, nie brzmi to zbyt wydajnie ...)
Fra
0

Musiałem usunąć niektóre domyślne kolumny i dodać dodatkowe kolumny w siatce klientów. Postanowiłem skonfigurować kolumny. Najpierw dodałem 2 pola wielokrotnego wyboru w pliku system.xml :

<config>
    <sections>
        <extendedcustomer translate="label" module="extendedcustomer">
            <label>Extended Customer</label>
            <tab>customer</tab>
            <sort_order>100</sort_order>
            <show_in_default>1</show_in_default>
            <show_in_website>1</show_in_website>
            <show_in_store>1</show_in_store>
            <groups>
                <manage_grid translate="label">
                    <label>Manage Customer Grid in Backend</label>
                    <frontend_type>text</frontend_type>
                    <sort_order>10</sort_order>
                    <show_in_default>1</show_in_default>
                    <show_in_website>1</show_in_website>
                    <show_in_store>1</show_in_store>
                    <fields>
                        <remove translate="label">
                            <label>Remove Columns</label>
                            <frontend_type>multiselect</frontend_type>
                            <source_model>extendedcustomer/source_gridColumn</source_model>
                            <sort_order>10</sort_order>
                            <show_in_default>1</show_in_default>
                            <show_in_website>1</show_in_website>
                            <show_in_store>1</show_in_store>
                        </remove>
                        <add translate="label">
                            <label>Add Columns</label>
                            <frontend_type>multiselect</frontend_type>
                            <source_model>extendedcustomer/source_attributeCode</source_model>
                            <sort_order>20</sort_order>
                            <show_in_default>1</show_in_default>
                            <show_in_website>1</show_in_website>
                            <show_in_store>1</show_in_store>
                        </add>                       
                    </fields>
                </manage_grid>
            </groups>
        </extendedcustomer>
    </sections>
</config>

Modele źródłowe są proste:

class SomeCo_ExtendedCustomer_Model_Source_GridColumn
{
    public function toOptionArray()
    {     
        return [
            ['value' => 'name', 'label' => 'Name'],
            ['value' => 'email', 'label' => 'Email'],
            ['value' => 'group', 'label' => 'Group'],
            ['value' => 'billing_telephone', 'label' => 'Telephone'],
            ['value' => 'billing_postcode', 'label' => 'ZIP'],
            ['value' => 'billing_country_id', 'label' => 'Country'],
            ['value' => 'billing_region', 'label' => 'State/Province'],
            ['value' => 'customer_since', 'label' => 'Customer Since'],
            ['value' => 'website_id', 'label' => 'Website'],
            ['value' => 'action', 'label' => 'Action']
        ];
    }
}

Drugi model źródłowy

class SomeCo_ExtendedCustomer_Model_Source_AttributeCode
{
    public function toOptionArray()
    {     
        $collection = Mage::getResourceModel('customer/attribute_collection')
            ->addFieldToSelect(['attribute_code', 'frontend_label'])
            ->addFieldToFilter('frontend_label', ['notnull'=>'notnull'])
            ->addFieldToFilter('is_user_defined', 1);
        $options = [];
        foreach ($collection as $item) {
            $options[] = [
                'value'     => $item->getData('attribute_code'),
                'label'     => $item->getData('frontend_label')
            ];
        }
        return $options;
    }
}

Następnie zastąp klasę siatki:

class SomeCo_ExtendedCustomer_Block_Adminhtml_Customer_Grid extends Mage_Adminhtml_Block_Customer_Grid
{
    public function __construct()
    {
        parent::__construct();
        if ($remove = Mage::getStoreConfig('extendedcustomer/manage_grid/remove')) {
            $remove = explode(',', $remove);
        } else {
            $remove = false;
        }
        $this->setRemoveList($remove);

        if ($add = Mage::getStoreConfig('extendedcustomer/manage_grid/add')) {
            $add = explode(',', $add);
        } else {
            $add = false;
        }
        $this->setAddList($add);
    }

    protected function _prepareCollection()
    {
        if ($remove = $this->getRemoveList()) {
            $collection = Mage::getResourceModel('customer/customer_collection');
            if (!in_array('name', $remove)) {
                $collection->addNameToSelect();
            }
            foreach (['postcode', 'city', 'telephone', 'region', 'country_id'] as $suffix) {
                if (!in_array('billing_'.$suffix, $remove)) {
                    $collection->joinAttribute('billing_'.$suffix, 'customer_address/'.$suffix, 'default_billing', null, 'left');
                }
            }
        } else {
            $collection = Mage::getResourceModel('customer/customer_collection')
                ->addNameToSelect()
                //->addAttributeToSelect('email') // static attributes are added by default
                //->addAttributeToSelect('created_at')
                //->addAttributeToSelect('group_id')
                ->joinAttribute('billing_postcode', 'customer_address/postcode', 'default_billing', null, 'left')
                ->joinAttribute('billing_city', 'customer_address/city', 'default_billing', null, 'left')
                ->joinAttribute('billing_telephone', 'customer_address/telephone', 'default_billing', null, 'left')
                ->joinAttribute('billing_region', 'customer_address/region', 'default_billing', null, 'left')
                ->joinAttribute('billing_country_id', 'customer_address/country_id', 'default_billing', null, 'left');
        }

        if ($add = $this->getAddList()) {
            $collection->addAttributeToSelect($add);
        }

        $this->setCollection($collection);

        return Mage_Adminhtml_Block_Widget_Grid::_prepareCollection(); // call grandParent
    }

    protected function _prepareColumns()
    {
        $this->addColumn('entity_id', array(
            'header'    => Mage::helper('customer')->__('ID'),
            'width'     => '50px',
            'index'     => 'entity_id',
            'type'  => 'number',
        ));

        $remove = $this->getRemoveList();

        if (!$remove || !in_array('name', $remove)) {           
            $this->addColumn('name', array(
                'header'    => Mage::helper('customer')->__('Name'),
                'index'     => 'name'
            ));
        }

        if ($add = $this->getAddList()) {
            $collection = Mage::getResourceModel('customer/attribute_collection')
                ->addFieldToSelect(['attribute_code', 'frontend_label', 'source_model'])
                ->addFieldToFilter('attribute_code', ['in' => $add]);
            foreach ($collection as $item) {
                if ($source = $item->getSourceModel()) {
                    $this->addColumn($item->getAttributeCode(), array(
                        'header'    =>  $item->getFrontendLabel(),
                        'width'     =>  '100',
                        'index'     =>  $item->getAttributeCode(),
                        'type'      =>  'options',
                        'options'   =>  Mage::getSingleton($source)->toOptionHash(false)
                    ));
                } else {
                    $this->addColumn($item->getAttributeCode(), array(
                        'header'    => $item->getFrontendLabel(),
                        'width'     => '150',
                        'index'     => $item->getAttributeCode()
                    ));
                }
            }
        }

        if (!$remove || !in_array('email', $remove)) {            
            $this->addColumn('email', array(
                'header'    => Mage::helper('customer')->__('Email'),
                'width'     => '150',
                'index'     => 'email'
            ));
        }

        if (!$remove || !in_array('group', $remove)) {
            $groups = Mage::getResourceModel('customer/group_collection')
                ->addFieldToFilter('customer_group_id', array('gt'=> 0))
                ->load()
                ->toOptionHash();

            $this->addColumn('group', array(
                'header'    =>  Mage::helper('customer')->__('Group'),
                'width'     =>  '100',
                'index'     =>  'group_id',
                'type'      =>  'options',
                'options'   =>  $groups,
            ));
        }

        if (!$remove || !in_array('billing_telephone', $remove)) {
            $this->addColumn('Telephone', array(
                'header'    => Mage::helper('customer')->__('Telephone'),
                'width'     => '100',
                'index'     => 'billing_telephone'
            ));
        }

        if (!$remove || !in_array('billing_postcode', $remove)) {
            $this->addColumn('billing_postcode', array(
                'header'    => Mage::helper('customer')->__('ZIP'),
                'width'     => '90',
                'index'     => 'billing_postcode',
            ));
        }

        if (!$remove || !in_array('billing_country_id', $remove)) {
            $this->addColumn('billing_country_id', array(
                'header'    => Mage::helper('customer')->__('Country'),
                'width'     => '100',
                'type'      => 'country',
                'index'     => 'billing_country_id',
            ));
        }

        if (!$remove || !in_array('billing_region', $remove)) {
            $this->addColumn('billing_region', array(
                'header'    => Mage::helper('customer')->__('State/Province'),
                'width'     => '100',
                'index'     => 'billing_region',
            ));
        }

        if (!$remove || !in_array('customer_since', $remove)) {
            $this->addColumn('customer_since', array(
                'header'    => Mage::helper('customer')->__('Customer Since'),
                'type'      => 'datetime',
                'align'     => 'center',
                'index'     => 'created_at',
                'gmtoffset' => true
            ));
        }

        if (!$remove || !in_array('website_id', $remove)) {
            if (!Mage::app()->isSingleStoreMode()) {
                $this->addColumn('website_id', array(
                    'header'    => Mage::helper('customer')->__('Website'),
                    'align'     => 'center',
                    'width'     => '80px',
                    'type'      => 'options',
                    'options'   => Mage::getSingleton('adminhtml/system_store')->getWebsiteOptionHash(true),
                    'index'     => 'website_id',
                ));
            }
        }

        if (!$remove || !in_array('action', $remove)) {
            $this->addColumn('action',
                array(
                    'header'    =>  Mage::helper('customer')->__('Action'),
                    'width'     => '100',
                    'type'      => 'action',
                    'getter'    => 'getId',
                    'actions'   => array(
                        array(
                            'caption'   => Mage::helper('customer')->__('Edit'),
                            'url'       => array('base'=> '*/*/edit'),
                            'field'     => 'id'
                        )
                    ),
                    'filter'    => false,
                    'sortable'  => false,
                    'index'     => 'stores',
                    'is_system' => true,
            ));
        }

        $this->addExportType('*/*/exportCsv', Mage::helper('customer')->__('CSV'));
        $this->addExportType('*/*/exportXml', Mage::helper('customer')->__('Excel XML'));
        return Mage_Adminhtml_Block_Widget_Grid::_prepareColumns();
    }
}
kiatng
źródło