Как стать автором
Обновить

Комментарии 14

Стоит отметить, что пути к классам в статье указаны для мадженты установленной через composer. Для всех остальных случаев установки vendor/magento/module-customer надо заменить на app/code/Magento/Customer
ох уж это магенто

даже в bitrix меньше телодвижений.

Хотел бы подчеркнуть такой момент — все эти телодвижения приводят к тому, что колонки в грид добавляются независимо. Т.е., разработчика модуля не заботит, какие еще модули будут стоять в приложении, и на какие еще таблицы пойдут JOIN'ы.

> что колонки в грид добавляются независимо. Т.е., разработчика модуля не заботит, какие еще модули будут стоять в приложении, и на какие еще таблицы пойдут JOIN'ы.

вот это прям фича из фичей.

в любой нормальной CMS например в bitrix это достигается добавлением нового свойства через админку, без написания такой кучи кода — без программирования вообще.
и вывод поля в формах и списках админки настраивается через админку.

в wordpress к слову аналогично. разве что надо вывод в списках добавить, написав строк десять кода.

и вот у меня возникает резонный вопрос — зачем в магенто столько кода надо писать для реализации элементарной вещи?
Так в статье большой кастыль. Достаточно добавить атрибут через инстал скрипт, и конфигурацию 10 строк кода и всё работает. А тут автор забил на орм(как это многие делают, думая что я умнее тех чуваков которые 5 лет какую то орм разрабатывали), придумал кастыль с фильтрацией так как теперь табличка main_table.user получилось а не user просто и сменился index.

ORM в Magento? Его там нет и никогда не было.

http://devdocs.magento.com/guides/m1x/magefordev/mage-for-dev-5.html ха насмешили. Вы наверное с bitrix'a на magento пересели или незнаете что такое ORM она всегда там была. А прямые самосконструированные запросы зло.

Я пересел на Magento с Java, на которой имел дело и с Hibernate, и с DataNucleus. То, что в статье говорится "It should be no surprise that Magento takes the ORM approach", не является основанием для заявления, что ORM в Magento присутствует. Для разминки изобразите средствами "Magento ORM" сущность с составным первичным ключом (состоящим из двух полей таблицы в БД), а затем попробуйте средствами "Magento ORM" извлечь коллекцию таких объектов. Для Hibernate и DataNucleus данная задача является тривиальной.


Ваша критика статьи станет конструктивной тогда, когда вы предложите свое решение описанной задачи, а не пронесетесь вихрем по комментам с шашкой наголо "так никто не делает, там делов-то на пару строк кода".

один простой метод `addUniqueField`… И у вас какой то аргумент уж слишком похож на `пила по дереву не пила по тому что она не пилит метал, я же пилой по металу пользовался` ORM — штука которая представляет запросы к б.д. на объктно ориентированном диалекте.
ORM — штука которая представляет запросы к б.д. на объктно ориентированном диалекте.

Ну и как будет выглядеть запрос на выборку объектов с составным первичным ключом в Magento ORM? А на обновление объекта?

Кстати, можете еще попробовать вытащить данные (email & full name) по всем клиентам, которые совершили транзакции (sales_payment_transaction, нужны данные из поля tnx_id), которые соответствуют определенным методам платежа (sales_order_payment.method) по заказам, созданным в определенный промежуток времени, используя всю мощь Magento ORM.

protected function _replaceAllAliasesInWhere($where)
{
    $result = [];
    foreach ($where as $item) {
        $item = $this->_replaceAliaseInWhere($item, self::AS_FLD_CUSTOMER_DEPTH, self::AS_TBL_CUST, 'depth');
        $item = $this->_replaceAliaseInWhere($item, self::AS_FLD_PARENT_ID, self::AS_TBL_CUST, 'parent_id');
        $result[] = $item;
    }
    return $result;
}

protected function _replaceAliaseInWhere($where, $fieldAlias, $tableAlias, $fieldName)
{
    $search = "`$fieldAlias`";
    $replace = "`$tableAlias`.`$fieldName`";
    $result = str_replace($search, $replace, $where);
    return $result;
}

это всё заменяеться одной строкой
`$collection->addFieldToFilter('mytable.myfield',$yuorFilterValue)`

Вы немножко неправильно поняли назначение моего кода — он подменяет алиасы для дополнительных столбцов исходного SQL'а для WHERE-правила (да-да, в background'е "Magento ORM" спрятан самый обычный SQL, впрочем, как и в background'е других ORM framework'ов) полным значением имени столбца, с добавлением алиаса таблицы.


В вашем примере код


$collection->addFieldToFilter('mytable.myfield',$yuorFilterValue)

просто добавляет в список WHERE-правил еще одно условие. Этот код и так исполняется, когда Magento разбирает условия фильтрации данных грида, заданные пользователем через WebUI (трассировка от \Magento\Framework\View\Element\UiComponent\DataProvider\FilterPool::applyFilters как раз и выведет на метод "addFieldToFilter"). У Magento-коллекции есть метод "addFilterToMap", который позволяет ввести карту преобразований, аналогичных тем, которые делаю я, и выполнять их перед тем, как добавить условие фильтрации (\Magento\Framework\Data\Collection\AbstractDb::_translateCondition, вызывается из addFieldToFilter), вот только нет возможности вклиниться в поток выполнения команд через событие (применение фильтров идет после создания коллекции и до генерации события "core_collection_abstract_load_before"). Можно использовать механизм плагинов и обернуть, например, метод \Magento\Framework\View\Element\UiComponent\DataProvider\CollectionFactory::getReport, чтобы он выполнял те же самые действия, что и в обсервере, плюс добавлял маппинг.


Регистрация around-плагина:
etc/di.xml


<type name="Magento\Framework\View\Element\UiComponent\DataProvider\CollectionFactory">
    <plugin
            name="vendor_module_data_provider_collection_factory"
            type="Vendor\Module\Plugin\Framework\View\Element\UiComponent\DataProvider\CollectionFactory"
            sortOrder="100"
            disabled="false"
    />
</type>

Код самого плагина, вызывающий класс-модификатор для добавления JOIN'ов к выборке и маппинг полей для их преобразования в фильтрах:


namespace Vendor\Module\Plugin\Framework\View\Element\UiComponent\DataProvider;
class CollectionFactory
{
    protected $_subQueryModifier;

    public function __construct(
        Sub\QueryModifier $subQueryModufier
    ) {
        $this->_subQueryModifier = $subQueryModufier;
    }

    public function aroundGetReport(
        \Magento\Framework\View\Element\UiComponent\DataProvider\CollectionFactory $subject,
        \Closure $proceed,
        $requestName
    ) {
        $result = $proceed($requestName);
        if ($requestName == 'customer_listing_data_source') {
            if ($result instanceof \Magento\Customer\Model\ResourceModel\Grid\Collection) {
                /* add JOINs to the select query */
                $this->_subQueryModifier->populateSelect($result);
                /* add fields to mapping */
                $this->_subQueryModifier->addFieldsMapping($result);
            }
        }
        return $result;
    }
}

Код, который модифицирует выбоку аналогичный тому, что в статье. Код для маппинга трививален:


    // depth
    $fieldAlias = self::AS_FLD_CUSTOMER_DEPTH;
    $fieldFullName = self::AS_TBL_CUST . '.' . Customer::ATTR_DEPTH;
    $collection->addFilterToMap($fieldAlias, $fieldFullName);

Этот подход позволяет использовать механизмы Magento для замены алиасов истинными именами полей вместо "грязного хака".

Возможно потому, что Magento — не CMS.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории