php Shopware 6:无法在新的自定义插件中保存关联字段(媒体)

laik7k3q  于 2023-05-05  发布在  PHP
关注(0)|答案(1)|浏览(133)

我已经创建了一个自定义插件,它正在执行CRUD(创建,读取,更新,删除)。在“编辑”页面中,将保存除sw-media-field以外的所有字段。当我选择一个媒体文件,它显示,但当点击保存,它恢复到旧文件(或没有,如果什么都没有)。
新的实体名称为“certificate”,列名为media_id。这里有什么错误,导致只更新media_id列?

CertificateDefinition类:

<?php declare(strict_types=1);

namespace Certificate\Entity;

use Shopware\Core\Checkout\Customer\CustomerDefinition;
use Shopware\Core\Content\Category\CategoryDefinition;
use Shopware\Core\Content\Media\MediaDefinition;
use Shopware\Core\Framework\DataAbstractionLayer\EntityDefinition;
use Shopware\Core\Framework\DataAbstractionLayer\Field\BoolField;
use Shopware\Core\Framework\DataAbstractionLayer\Field\FkField;
use Shopware\Core\Framework\DataAbstractionLayer\Field\Flag\PrimaryKey;
use Shopware\Core\Framework\DataAbstractionLayer\Field\Flag\Required;
use Shopware\Core\Framework\DataAbstractionLayer\Field\IdField;
use Shopware\Core\Framework\DataAbstractionLayer\Field\ManyToOneAssociationField;
use Shopware\Core\Framework\DataAbstractionLayer\Field\StringField;
use Shopware\Core\Framework\DataAbstractionLayer\FieldCollection;

class CertificateDefinition extends EntityDefinition
{
    public const ENTITY_NAME = 'certificate';

    public function getEntityName(): string
    {
        return self::ENTITY_NAME;
    }

    public function getEntityClass(): string
    {
        return CertificateEntity::class;
    }

    public function getCollectionClass(): string
    {
        return CertificateCollection::class;
    }

    protected function defineFields(): FieldCollection
    {
        return new FieldCollection(
            [
                (new IdField('id', 'id'))->addFlags(new Required(), new PrimaryKey()),
                (new StringField('name', 'name'))->addFlags(new Required()),
                (new StringField('file_name', 'fileName'))->addFlags(new Required()),
                (new BoolField('active', 'active'))->addFlags(new Required()),

                (new FkField('media_id', 'media', MediaDefinition::class))->addFlags(new Required()),
                (new ManyToOneAssociationField('media', 'media_id', MediaDefinition::class, 'id', true)),
            ]
        );
    }
}

detail.html.twig:

<sw-page class="certificate-detail">
    <template slot="smart-bar-actions">
        <sw-button :routerLink="{ name: 'webconia.certificate.list' }">
            {{ $t('certificate.detail.backButtonText') }}
        </sw-button>

        <sw-button-process :isLoading="isLoading"
                           :processSuccess="processSuccess"
                           variant="primary"
                           @process-finish="saveFinish"
                           @click="onClickSave">
            {{ $t('certificate.detail.saveButtonText') }}
        </sw-button-process>
    </template>
    <template slot="content">
        <sw-card-view>
            <sw-card v-if="certificate">
                <sw-field :label="$t('certificate.list.name')" v-model="certificate.name"
                          validation="required"></sw-field>
                <sw-field :label="$t('certificate.list.fileName')" v-model="certificate.fileName"
                          validation="required"></sw-field>
                <sw-switch-field :label="$t('certificate.detail.active')" v-model="certificate.active" size="medium"
                          validation="required"></sw-switch-field>

                <sw-media-field
                        :media-id="certificate.media.id"
                        fileAccept="application/pdf"
                        label="PDF upload"
                        @media-id-change="onMediaIdChange"
                        >
                </sw-media-field>
                <div>{{ certificate.media.fileName|json_encode }}{{ certificate.media.id|json_encode }}</div>

            </sw-card>
        </sw-card-view>
    </template>
</sw-page>

index.js:

import template from './certificate-detail.html.twig';
const { EntityCollection, Criteria } = Shopware.Data;

Shopware.Component.register('webconia-certificate-detail', {
    template,

    inject: [
        'repositoryFactory'
    ],

    metaInfo() {
        return {
            title: this.$createTitle()
        };
    },

    data() {
        return {
            repository: null,
            mediaReopsitory: null,
            isLoading: null,
            processSuccess: null,
            certificate: null
        };
    },

    created() {
        this.repository = this.repositoryFactory.create('certificate');
        this.mediaReopsitory = this.repositoryFactory.create('media');
        this.getCertificate();
    },
    methods: {
        onMediaIdChange(mediaId) {
            const mediaRepository = this.repositoryFactory.create('media');
            mediaRepository.get(mediaId, Shopware.Context.api).then((media) => {
                this.certificate.media = media;
                // this.certificate.mediaId = mediaId;
            });
        },
        getCertificate() {
            this.repository
                .get(this.$route.params.id, Shopware.Context.api, new Criteria().addAssociation('media'))
                .then((entity) => {
                    this.certificate = entity;
                });
        },
        onClickSave() {
            this.isLoading = true;
            // Save certificate
            this.repository
                .save(this.certificate, Shopware.Context.api)
                .then(() => {
                    this.getCertificate();
                    this.isLoading = false;
                    this.processSuccess = true
                }).catch((exception) => {
                this.isLoading = false;
                this.createNotificationError({
                    title: this.$tc('certificate.detail.errorTitle'),
                    message: exception
                });
            });
        },
        saveFinish() {
            this.processSuccess = false;
        },
    }
});
t2a7ltrp

t2a7ltrp1#

FkFieldpropertyName不应与关联的propertyName相同。将其更改为定义中唯一的值,如mediaId

(new FkField('media_id', 'mediaId', MediaDefinition::class))->addFlags(new Required()),
(new ManyToOneAssociationField('media', 'media_id', MediaDefinition::class, 'id', true)),

您还必须将新mediaId属性的getter和setter添加到实体类中。
然后,您可以通过直接设置外键字段来关联现有媒体实体,如下所示:

onMediaIdChange(mediaId) {
    this.certificate.mediaId = mediaId;
},

或者更简单的是,将其用作sw-media-field的模型绑定,您甚至不需要更改处理程序:

<sw-media-field v-model="certificate.mediaId" />

相关问题