You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Doctrine/ExtJS:如何基于第三方模型创建自定义模型并关联商品

解决Shopware商品Ktype适配复选框列及关联问题的思路

我之前处理过类似的Shopware插件定制需求,先梳理下你的核心痛点:第三方Ktype插件的数据表没有和Shopware商品表建立外键关联,仅靠商品的文本字段存储关联的Ktype编号;现在要在商品详情页的自定义标签页里实现带复选框的可排序列,加载时自动勾选已关联的Ktype,变更后能保存新的关联关系。下面是几个针对性的解决方案:

思路1:扩展ExtJS Store/Model,动态添加selected字段(无需改动数据库)

这个方案不需要新建自定义模型或数据库表,直接在前端ExtJS层面处理,既解决复选框状态,又支持排序。

步骤1:扩展第三方Ktype的ExtJS Model

在你的自定义插件里,创建一个扩展自第三方插件Model的自定义Model,添加selected字段:

// 假设第三方Model是'KtypePlugin\Model\Ktype'
Ext.define('YourPlugin\Model\CustomKtype', {
    extend: 'KtypePlugin\Model\Ktype',
    fields: [
        { name: 'selected', type: 'boolean', defaultValue: false }
    ]
});

步骤2:配置Store并加载时设置勾选状态

在你的商品详情标签页的Store配置中,使用自定义Model,并且在Store加载完成后,根据当前商品的ktypes文本字段匹配设置selected状态:

Ext.define('YourPlugin\Store\KtypeSelection', {
    extend: 'Shopware.store.Listing',
    model: 'YourPlugin\Model\CustomKtype',
    remoteSort: true, // 支持远程排序
    proxy: {
        type: 'ajax',
        url: '{url controller="YourPlugin" action="getKtypes"}',
        reader: {
            type: 'json',
            rootProperty: 'data'
        }
    },
    listeners: {
        load: function(store, records) {
            // 获取当前商品的Ktype文本字段(假设商品数据存在record变量中)
            const currentArticleKtypes = record.get('ktypes').split(',');
            records.forEach(record => {
                if (currentArticleKtypes.includes(record.get('ktype_number'))) {
                    record.set('selected', true);
                }
            });
        }
    }
});

步骤3:在Grid中添加可排序的复选框列

在你的自定义标签页Grid里,添加selected列,设置sortable: true,并且绑定复选框:

{
    xtype: 'gridcolumn',
    dataIndex: 'selected',
    text: '{s name="selected"}Selected{/s}',
    width: 80,
    sortable: true,
    renderer: function(value, metaData, record) {
        return `<input type="checkbox" ${value ? 'checked' : ''} 
                    onclick="Ext.ComponentQuery.query('your-plugin-ktype-grid')[0].handleCheckboxClick(this, '${record.get('ktype_number')}')">`;
    }
}

步骤4:保存选中的Ktype到商品字段

添加保存按钮的点击事件,收集所有选中的Ktype编号,拼接成文本后更新商品的ktypes字段:

handleSave: function() {
    const grid = this.down('your-plugin-ktype-grid');
    const selectedKtypes = grid.getStore().queryBy(record => record.get('selected')).getRange().map(r => r.get('ktype_number'));
    const articleRecord = this.record; // 当前商品的Record
    
    articleRecord.set('ktypes', selectedKtypes.join(','));
    articleRecord.save({
        success: function() {
            Shopware.Notification.createGrowlMessage(
                '{s name="successTitle"}Success{/s}',
                '{s name="successMessage"}Ktype associations saved{/s}'
            );
        }
    });
}

思路2:创建Doctrine中间关联表(长期优化方案)

如果希望从数据库层面建立关联,解决后续扩展问题,可以创建一个中间表,关联商品ID和Ktype编号,手动同步现有数据。

步骤1:创建中间表实体

在你的插件中创建一个ArticleKtype实体:

// YourPlugin/src/Entity/ArticleKtype.php
namespace YourPlugin\Entity;

use Shopware\Core\Content\Product\ProductDefinition;
use Doctrine\ORM\Mapping as ORM;
use Shopware\Core\Framework\DataAbstractionLayer\Entity;
use Shopware\Core\Framework\DataAbstractionLayer\EntityIdTrait;

/**
 * @ORM\Entity
 * @ORM\Table(name="your_plugin_article_ktype")
 */
class ArticleKtype extends Entity
{
    use EntityIdTrait;

    /**
     * @ORM\Column(name="article_id", type="string", length=36)
     */
    protected string $articleId;

    /**
     * @ORM\Column(name="ktype_number", type="string", length=255)
     */
    protected string $ktypeNumber;

    // Getters and Setters
    public function getArticleId(): string
    {
        return $this->articleId;
    }

    public function setArticleId(string $articleId): void
    {
        $this->articleId = $articleId;
    }

    public function getKtypeNumber(): string
    {
        return $this->ktypeNumber;
    }

    public function setKtypeNumber(string $ktypeNumber): void
    {
        $this->ktypeNumber = $ktypeNumber;
    }
}

步骤2:同步现有商品的Ktype数据

编写一个命令或脚本,将现有商品ktypes字段中的编号同步到中间表:

// 示例同步代码(可放在插件安装时执行)
$products = $this->productRepository->search(new Criteria(), $context)->getEntities();
foreach ($products as $product) {
    $ktypes = explode(',', $product->getCustomFields()['ktypes'] ?? ''); // 假设存在自定义字段或商品字段中
    foreach ($ktypes as $ktype) {
        if (trim($ktype)) {
            $articleKtype = new ArticleKtype();
            $articleKtype->setArticleId($product->getId());
            $articleKtype->setKtypeNumber(trim($ktype));
            $this->articleKtypeRepository->create([$articleKtype->jsonSerialize()], $context);
        }
    }
}

步骤3:ExtJS层面关联中间表数据

此时你的ExtJS Store可以从中间表获取当前商品已选中的Ktype,加载时直接设置selected状态,保存时直接操作中间表(新增/删除关联),同时支持排序,因为selected状态可以通过关联查询返回,或者在Store中处理。

关键注意事项

  • 如果选择思路1,要注意selected字段是前端动态添加的,排序时需要在后端处理:当排序字段是selected时,后端查询Ktype数据时,根据当前商品的关联情况返回排序后的结果。
  • 思路2需要考虑数据同步的一致性,比如商品ktypes字段更新时,也要同步中间表,或者后续废弃ktypes文本字段,完全用中间表关联。

内容的提问来源于stack exchange,提问作者Stefan Schulte

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 09:52:51