在我们之前的一篇博客中,我们学习了如何创建一个小部件。现在我们将看到如何创建一个自定义的甚至更好的,如何扩展核心的。在本篇博客中,我选择了默认的产品列表小部件,我将使用排序字段对其进行扩展,以便更好地自定义此小部件。
模块设置
首先,我们需要创建一个新模块。新模块要求的名称和模块文件夹是模块文件夹内的registration.php
和etc/module.xml
。对于此示例,我将使用Magease作为名称,使用CatalogWidget作为模块名称。
registration.php
<?php
\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
'Magease_CatalogWidget',
__DIR__
);
etc/module.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="Magease_CatalogWidget" setup_version="1.0.0" >
<sequence>
<module name="Magento_CatalogWidget"/>
</sequence>
</module>
</config>
自定义代码
首先,我们将创建与扩展小部件中使用的工具几乎相同的小部件配置。我们通过在etc文件夹中创建widget.xml文件来实现这一点除了标签和描述的变化,有两个额外的参数collection_sort_by
和collection_sort_order
,稍后我们将使用这两个参数对产品集合进行排序。参数类型是select,它们使用我们将在下面步骤中创建的自定义源模型。其他区别是容器节点(我将在后面解释)和模板参数选项。我添加了自己的模板选项和名称top_products
。这将是我们自己的自定义模板,以便按照我们想要的方式呈现产品列表。最后但并非最不重要的是自定义小部件占位符图像。我们将把它放在view/adminhtml/web/images/magease_widget_block.png。
etc/widget.xml
<?xml version="1.0" encoding="UTF-8"?>
<widgets xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Widget:etc/widget.xsd">
<widget id="magease_products_list" class="Magease\CatalogWidget\Block\Product\ProductsList"
placeholder_image="Magease_CatalogWidget::images/magease_widget_block.png">
<label translate="true">Magease Catalog Products List</label>
<description>Magease - Extended Catalog Products List</description>
<parameters>
<parameter name="title" xsi:type="text" required="false" visible="true">
<label translate="true">Title</label>
</parameter>
<parameter name="collection_sort_by" xsi:type="select" visible="true"
source_model="Magease\CatalogWidget\Model\Config\Source\SortBy">
<label translate="true">Sort Collection By</label>
</parameter>
<parameter name="collection_sort_order" xsi:type="select" visible="true"
source_model="Magease\CatalogWidget\Model\Config\Source\SortOrder">
<label translate="true">Sort Collection Order</label></parameter>
<parameter name="show_pager" xsi:type="select" visible="true"
source_model="Magento\Config\Model\Config\Source\Yesno">
<label translate="true">Display Page Control</label>
</parameter>
<parameter name="products_per_page" xsi:type="text" required="true" visible="true">
<label translate="true">Number of Products per Page</label>
<depends>
<parameter name="show_pager" value="1" />
</depends>
<value>5</value>
</parameter>
<parameter name="products_count" xsi:type="text" required="true" visible="true">
<label translate="true">Number of Products to Display</label>
<value>10</value>
</parameter>
<parameter name="template" xsi:type="select" required="true" visible="true">
<label translate="true">Template</label>
<options>
<option name="default" value="Magento_CatalogWidget::product/widget/content/grid.phtml" selected="true">
<label translate="true">Products Grid Template</label>
</option>
<option name="top_products" value="Magease_CatalogWidget::product/widget/content/top_products.phtml">
<label translate="true">Top Products Template</label>
</option>
</options>
</parameter>
<parameter name="cache_lifetime" xsi:type="text" visible="true">
<label translate="true">Cache Lifetime (Seconds)</label>
<description translate="true">86400 by default, if not set. To refresh instantly, clear the Blocks HTML Output cache.</description>
</parameter>
<parameter name="condition" xsi:type="conditions" visible="true" required="true" sort_order="10"
class="Magento\CatalogWidget\Block\Product\Widget\Conditions">
<label translate="true">Conditions</label>
</parameter>
</parameters>
<containers>
<container name="content">
<template name="grid" value="default" />
<template name="top-products" value="top_products" />
</container>
<container name="content.top">
<template name="grid" value="default" />
</container>
</containers>
</widget>
</widgets>
我们有两个自定义参数和两个自定义源模型。我喜欢按照magento核心模块一样组织我的模块,所以我将创建模型Model/Config/Source
Model/Config/Source/SortBy.php
<?php
namespace Magease\CatalogWidget\Model\Config\Source;
class SortBy implements \Magento\Framework\Option\ArrayInterface
{
public function toOptionArray()
{
return [
['value' => 'name', 'label' => __('Product Name')],
['value' => 'price', 'label' => __('Price')]
];
}
}
Model/Config/Source/SortOrder.php
<?php
namespace Magease\CatalogWidget\Model\Config\Source;
class SortOrder implements \Magento\Framework\Option\ArrayInterface
{
public function toOptionArray()
{
return [
['value' => 'asc', 'label' => __('Ascending')],
['value' => 'desc', 'label' => __('Descending')]
];
}
}
下一步是创建我们的小部件将使用的自定义块。为了简单,我们将扩展Magento_CatalogWidget中的ProductList
块。这将为我们提供产品列表小部件的所有Magento现有功能
我们从ProductList中重写createCollection方法,在集合上添加排序。我添加了“collection_sort_by”和“collection_sort_order”属性getter,并在类的开头定义了默认值。此自定义参数在widget.xml
配置中定义。
Block/Product/ProductsList.php
<?php
namespace Magease\CatalogWidget\Block\Product;
class ProductsList extends \Magento\CatalogWidget\Block\Product\ProductsList
{
const DEFAULT_COLLECTION_SORT_BY = 'name';
const DEFAULT_COLLECTION_ORDER = 'asc';
public function createCollection()
{
/** @var $collection \Magento\Catalog\Model\ResourceModel\Product\Collection */
$collection = $this->productCollectionFactory->create();
$collection->setVisibility($this->catalogProductVisibility->getVisibleInCatalogIds());
$collection = $this->_addProductAttributesAndPrices($collection)
->addStoreFilter()
->setPageSize($this->getPageSize())
->setCurPage($this->getRequest()->getParam($this->getData('page_var_name'), 1))
->setOrder($this->getSortBy(), $this->getSortOrder());
$conditions = $this->getConditions();
$conditions->collectValidatedAttributes($collection);
$this->sqlBuilder->attachConditionToCollection($collection, $conditions);
return $collection;
}
public function getSortBy()
{
if (!$this->hasData('collection_sort_by')) {
$this->setData('collection_sort_by', self::DEFAULT_COLLECTION_SORT_BY);
}
return $this->getData('collection_sort_by');
}
public function getSortOrder()
{
if (!$this->hasData('collection_sort_order')) {
$this->setData('collection_sort_order', self::DEFAULT_COLLECTION_ORDER);
}
return $this->getData('collection_sort_order');
}
}
现在可以开始测试了。
Containers
在创建小部件时,我们有布局更新选项,可以指定在哪个页面以及在哪个容器中展示我们的小部件。为了充分展示其能力,我将创建自定义模板文件。在这个示例中,我复制了默认产品列表模板。同样,为了保持一致性,我模仿了view/frontend/templates/product/widget/content/top_products.phtml的模版路径。在我们的小部件配置中,我们指定了两个容器,一个名为content,另一个名为content.top。在第一个中,我定义了两个模板grid和 top-products。这个节点的值将显示具有相同名称的模板选项,能使特定的自定义模板只在特定的容器中显示。
<container name="content">
<template name="grid" value="default" />
<template name="top-products" value="top_products" />
</container>
<container name="content.top">
<template name="grid" value="default" />
</container>
主要内容区域 - name="content"
,模板选择可用。
主要内容顶部 - name="content.top
,模板选择不可用。