Search code examples
shopwareshopware6

Connect product extension to custom entity and add to administration


I’ve created a custom entity, lets call it my_entity, and added a StringField called name. After that I created an admin section with a list view and detail page. The list view shows all the entries from my_entity and within the detail page you can create or edit an entry. So far so good.

Then I created a product extension. But this is the part where I’m stuck. The extension will use a separate DB table, my_entity_extension. The extension and the DB table need to reference to a product and my_entity. A product can have multiple references to an entry from my_entity.

How will the productExtension, in particular the extendFields, look like? Do I need to use a OneToOneAssociationField or a ManytoOne?

Then my next question, I couldn’t quit find this in the documentation. I extended the product view tab in the administration. Now I want to add a sw-entity-multi-select component which is linked to my_identity but I need to save the selection in the product extension. How can I get this to work in the Twig and JS file?

Also what I noticed is that if I enable the autoload in the product extension, then the product overview list is empty. No products are showing in the admin. Once I set it to false, it’s showing again.

A lof of questions but hopefully someone can help me out.


Solution

  • Do I need to use a OneToOneAssociationField or a ManytoOne?

    This really depends on your intended use. Shall multiple products be associated to one single record of your custom entity? Then it's ManyToOne. Shall there be one unique record of your custom entity per plugin? Then it's OneToOne. See the documentation with examples to each kind of association.

    You can then use the extension property of the product entity to store values for associations to the extended entity.

    Assuming you override sw-product-settings-form to place the field in the administration:

    Component.override('sw-product-settings-form', {
        template,
        inject: ['repositoryFactory'],
        computed: {
            someProperty: {
                get() {
                    return this.product.extensions.yourEntity?.someProperty ?? null;
                },
                set(value) {
                    if (!this.customer.extensions.yourEntity) {
                        this.$set(this.product.extensions, 'yourEntity', this.repositoryFactory.create('your_entity').create());
                    }
    
                    this.$set(this.product.extensions.yourEntity, 'someProperty', value);
                },
            },
        }
    });
    

    In your override's template:

    <sw-text-field
        v-model="someProperty"
    />
    

    Changes to the field will then be persisted when saving the product. Here's an example plugin that extends the customer module with an extension field in the same manner.