Search code examples
phpsymfonyshopwareshopware6

Shopware admin extend property details page with one to many relation


Trying to extend property with one to many relation to be able to categorize each property group. I did the extension and the migrations. all Seems to be working fine except from saving the relation in the admin panel property details page "/sw/property/detail/{id}" where I added a dropdown field using the sw-entity-single-select. Any help is appreciated. Here is my currently code:

class PropertyGroupExtension extends EntityExtension
{
    public function getDefinitionClass(): string
    {
        return PropertyGroupDefinition::class;
    }

    public function extendFields(FieldCollection $collection): void
    {
        $collection->add(
            (new FkField(
                'property_group_category_id',
                'propertyGroupCategoryId',
                PropertyGroupCategoryDefinition::class
            ))->addFlags(new ApiAware())
        );

        $collection->add(
            (new ManyToOneAssociationField(
                'propertyGroupCategory',
                'property_group_category_id',
                PropertyGroupCategoryDefinition::class,
                'id',
                false
            ))->addFlags(new ApiAware())
        );
    }
}
class PropertyGroupCategoryDefinition extends EntityDefinition
{
    public const ENTITY_NAME = 'property_group_category';

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

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

    protected function defineFields(): FieldCollection
    {
        return new FieldCollection([
            (new IdField('id', 'id'))->addFlags(new ApiAware(), new PrimaryKey(), new Required()),
            (new StringField('name', 'name'))->addFlags(new ApiAware(), new Required()),
            (new OneToManyAssociationField('propertyGroups', PropertyGroupDefinition::class, 'property_group_category_id'))->addFlags(new ApiAware()),
        ]);
    }
}
class PropertyGroupCategoryEntity extends Entity
{
    use EntityIdTrait;

    /**
     * @var string
     */
    protected $name;

    /**
     * @var PropertyGroupCollection|null
     */
    protected $propertyGroups;

    public function getName(): string
    {
        return $this->name;
    }

    public function setName(string $name): void
    {
        $this->name = $name;
    }

    public function getPropertyGroups(): ?PropertyGroupCollection
    {
        return $this->propertyGroups;
    }

    public function setPropertyGroups(PropertyGroupCollection $propertyGroups): void
    {
        $this->propertyGroups = $propertyGroups;
    }
}
#[Package('core')]
class Migration1726207525CreatePropertyGroupCategory extends MigrationStep
{
    public function getCreationTimestamp(): int
    {
        return 1726207525;
    }

    public function update(Connection $connection): void
    {
        $connection->executeStatement('
            CREATE TABLE `property_group_category` (
                `id` BINARY(16) NOT NULL,
                `name` VARCHAR(255) NOT NULL,
                `created_at` DATETIME(3) NOT NULL,
                `updated_at` DATETIME(3) NULL,
                PRIMARY KEY (`id`)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
        ');

        $connection->executeStatement('
            ALTER TABLE `property_group`
            ADD COLUMN `property_group_category_id` BINARY(16) NULL AFTER `filterable`,
            ADD CONSTRAINT `fk.property_group.property_group_category_id` FOREIGN KEY (`property_group_category_id`)
                REFERENCES `property_group_category` (`id`) ON DELETE SET NULL ON UPDATE CASCADE;
        ');
    }

}

and here is where i need the help. this is the admin shopware component already overridden by my plugin.

import template from './sw-property-group-detail.html.twig';
import {Component} from 'Shopware';

Component.override('sw-property-detail-base', {
    template,

    inject: ['repositoryFactory'],


    computed: {
        propertyGroupRepository() {
            return this.repositoryFactory.create('property_group');
        },

        propertyGroupCategoryRepository() {
            return this.repositoryFactory.create('property_group_category');
        },
    },

    methods: {
        onChange(id) {
            this.propertyGroup.propertyGroupCategoryId = id;
            if (id) {
                this.propertyGroupCategoryRepository.get(id).then((category) => {
                    this.propertyGroup.propertyGroupCategory = category;
                });
            } else {
                this.propertyGroup.propertyGroupCategory = null;
            }

            console.log(this.propertyGroup) // the data is here but is not saved on click the save button. is there anything here i am missing out?
        },
    }
});

template

{% block sw_property_detail_base_visible_on_detail %}
    {% parent %}
    <sw-entity-single-select
            id="propertyGroupCategory"
            ref="propertyGroupCategory"
            entity="property_group_category"
            :criteria="propertyGroupCategoryCriteria"
            :value="propertyGroup.propertyGroupCategoryId"
            label="Group By"
            placeholder="Group By"
            @update:value="onChange"
    ></sw-entity-single-select>
{% endblock %}
sw/property/detail/

services:

        <service id="MyProject\Core\Content\Property\PropertyGroupExtension">
            <tag name="shopware.entity_extension" />
        </service>

        <service id="MyProject\Core\Content\PropertyGroupCategory\PropertyGroupCategoryDefinition">
            <tag name="shopware.entity.definition" entity="property_group_category" />
        </service>

Solution

  • The reason was not working its because of the way was registered in the service definition. specifically was a typo in the tag name.

    Instead of

    
            <service id="MyProject\Core\Content\Property\PropertyGroupExtension">
                <tag name="shopware.entity_extension" />
            </service>
    

    should be

            <service id="MyProject\Core\Content\Property\PropertyGroupExtension">
                <tag name="shopware.entity.extension" />
            </service>
    

    The correct tag name for the EntityExtension is shopware.entity.extension