{"id":12920,"date":"2021-09-16T01:17:49","date_gmt":"2021-09-16T06:47:49","guid":{"rendered":"https:\/\/www.emizentech.com\/blog\/?p=12920"},"modified":"2023-01-30T10:59:39","modified_gmt":"2023-01-30T10:59:39","slug":"create-custom-field-in-database-entity-in-shopware","status":"publish","type":"post","link":"https:\/\/multisitelocal.ezxdemo.com\/blog\/create-custom-field-in-database-entity-in-shopware.html","title":{"rendered":"How To Create Custom Field In Database Entity In Shopware"},"content":{"rendered":"<p>Shopware&#8217;s custom field system allows you to extend entities, without writing a complete entity extension.This is possible by storing the additional data in a JSON-Field. Custom fields therefore can only be used to store scalar values. If you&#8217;d like to create associations between entities, you&#8217;ll need to use an Entity extension.<\/p>\n<p>Supporting custom fields with your entity<\/p>\n<p>For creating custom fields in database we need to extend any entity definition which is already created in shopware.<\/p>\n<p>In order to support custom fields with your custom entity, there are two steps necessary:<\/p>\n<ul>\n<li>1) Add a CustomFields field to your EntityDefinition<\/li>\n<li>2) Add a column custom_fields to your entities&#8217; database table via migration<\/li>\n<\/ul>\n<p>Also, you may want to add translatable custom fields, which is also covered in very short here.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Add_custom_field_to_entity_definition\"><\/span>Add custom field to entity definition<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<pre>&lt;plugin root&gt;\/src\/Core\/Content\/Example\/ExampleDefinition.php\n\nuse Shopware\\Core\\Framework\\DataAbstractionLayer\\Field\\CustomFields;                                                                    \n\u200b\n[...]\nclass ExampleDefinition extends EntityDefinition\n{\n    [...]\n    protected function defineFields(): FieldCollection\n    {\n        return new FieldCollection([\n            (new IdField('id', 'id'))-&gt;addFlags(new Required(), new PrimaryKey()),\n            (new StringField('name', 'name')),\n            (new StringField('description', 'description')),\n            (new BoolField('active', 'active')),\n            new CustomFields()\n        ]);\n    }\n}\n<\/pre>\n<p>Note the new field that was added in the FieldCollection. That&#8217;s already it for your custom entity definition. Now go ahead and add the column to the database.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Add_column_in_database_table\"><\/span>Add column in database table<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>If you want to support custom fields now, you have to add a new column custom_fields of type JSON to your migration.<\/p>\n<pre>&lt;plugin root&gt;\/src\/Migration\/Migration1611664789Example.php\npublic function update(Connection $connection): void\n{\n    $sql = &lt;&lt;&lt;SQL\n        CREATE TABLE IF NOT EXISTS `swag_example` (\n        `id` BINARY(16) NOT NULL,\n        `name` VARCHAR(255) COLLATE utf8mb4_unicode_ci,\n        `description` VARCHAR(255) COLLATE utf8mb4_unicode_ci,\n        `active` TINYINT(1) COLLATE utf8mb4_unicode_ci,\n\u200b\n        `custom_fields` json DEFAULT NULL,\n\u200b\n        `created_at` DATETIME(3) NOT NULL,\n        `updated_at` DATETIME(3),\n        PRIMARY KEY (`id`)\n        )\n        ENGINE = InnoDB\n        DEFAULT CHARSET = utf8mb4\n        COLLATE = utf8mb4_unicode_ci;\n    SQL;\n    $connection-&gt;executeStatement($sql);\n}\n<\/pre>\n<p>Custom field always must be json field and it should default to null, since it doesn&#8217;t have to contain values.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Add_translatable_custom_field_to_entity_definition\"><\/span>Add translatable custom field to entity definition<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Make sure to understand entity translations in general first, which is explained here Add data translations. If you want your custom fields to be translatable, you can simply work with a TranslatedField here as well.<\/p>\n<pre>&lt;plugin root&gt;\/src\/Core\/Content\/Example\/ExampleDefinition.php\nuse Shopware\\Core\\Framework\\DataAbstractionLayer\\Field\\TranslatedField;                                                               \n\u200b\n[...]\n\u200b\nclass ExampleDefinition extends EntityDefinition\n{\n    [...]\n\u200b\n    protected function defineFields(): FieldCollection\n    {\n        return new FieldCollection([\n            (new IdField('id', 'id'))-&gt;addFlags(new Required(), new PrimaryKey()),\n            (new StringField('name', 'name')),\n            (new StringField('description', 'description')),\n            (new BoolField('active', 'active')),\n\u200b\n            new TranslatedField('customFields'),\n        ]);\n    }\n}\n<\/pre>\n<p>Just add the TranslatedField and apply customFields as a parameter.<br>\nIn your translated entity definition, you then add the CustomFields field instead.<\/p>\n<pre>&lt;plugin root&gt;\/src\/Core\/Content\/Example\/Aggregate\/ExampleTranslation\/ExampleTranslationDefinition.php\nuse Shopware\\Core\\Framework\\DataAbstractionLayer\\Field\\CustomFields;                                                                    \n[...]\nclass ExampleTranslationDefinition extends EntityTranslationDefinition\n{\n    [...]\n\u200b\n    protected function defineFields(): FieldCollection\n    {\n        return new FieldCollection([\n            (new StringField('name', 'name'))-&gt;addFlags(new Required()),\n\u200b\n            new CustomFields()\n        ]);\n    }\n}\n<\/pre>\n<h3><span class=\"ez-toc-section\" id=\"Add_custom_fields_to_an_entity\"><\/span>Add custom fields to an entity<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Defining a custom field set is not necessary it is only necessary, if you want it to be editable in the administration or if you need validation when writing your custom field.<\/p>\n<p>Because of that, we&#8217;ll start with filling data to an actual entities&#8217; custom field, before actually defining it.<\/p>\n<h4>Filling data into custom fields<\/h4>\n<pre>$this-&gt;swagExampleRepository-&gt;upsert([[\n    'id' =&gt; '&lt;your ID here&gt;',\n    'customFields' =&gt; ['swag_example_size' =&gt; 15]\n]], $context);\n<\/pre>\n<p>You can write any valid json you want to write in custom Field. Example:<\/p>\n<pre>$this-&gt;swagExampleRepository-&gt;upsert([[\n    'id' =&gt; '&lt;your ID here&gt;',\n    'customFields' =&gt; [ 'foo' =&gt; 'bar', 'baz' =&gt; [] ]\n]], $context);\n<\/pre>\n<h4>Adding an actual custom field<\/h4>\n<p>You can skip this section if you do not want your new custom field to be editable in the administration.<\/p>\n<p>use Shopware\\Core\\System\\CustomField\\CustomFieldTypes;<\/p>\n<pre>[...]\n\n$this-&gt;customFieldSetRepository-&gt;create([\n    [\n        'name' =&gt; 'swag_example_set',\n        'config' =&gt; [\n            'label' =&gt; [\n                'en-GB' =&gt; 'English custom field set label',\n                'de-DE' =&gt; 'German custom field set label'\n            ]\n        ],\n        'customFields' =&gt; [\n            [\n                'name' =&gt; 'swag_example_size',\n                'type' =&gt; CustomFieldTypes::INT,\n                'config' =&gt; [\n                    'label' =&gt; [\n                        'en-GB' =&gt; 'English custom field label',\n                        'de-DE' =&gt; 'German custom field label'\n                    ],\n                    'customFieldPosition' =&gt; 1\n                ]\n            ]\n        ]\n    ]\n], $context);\n<\/pre>\n<h3><span class=\"ez-toc-section\" id=\"Here_is_the_example_of_removing_some_categories_from_navigation_menu\"><\/span>Here is the example of removing some categories from navigation menu.<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>I am adding a custom field which will hide menu from sidebar.<\/p>\n<p>custom\/plugin\/pluginRoot\/src\/pluginName.php<\/p>\n<p>Have a look on the screenshot:<br>\n<img fetchpriority=\"high\" decoding=\"async\" class=\"aligncenter size-full wp-image-12258\" src=\"\/blog\/wp-content\/uploads\/sites\/2\/2021\/09\/shopware-remove-categories-1.png\" alt=\"shopware remove categories 1\" width=\"801\" height=\"355\"><\/p>\n<p>Here my plugin name is SidebarNavigation<\/p>\n<p><strong>This class will perform operation on custom_field_set<\/strong><\/p>\n<pre>&lt;?php declare(strict_types=1);\n\nnamespace SidebarNavigation;\n\nuse Doctrine\\DBAL\\Connection;\nuse Shopware\\Core\\Framework\\Plugin;\nuse Shopware\\Core\\Framework\\Plugin\\Context\\UninstallContext;\nuse Shopware\\Core\\Framework\\Plugin\\Context\\InstallContext;\nuse Shopware\\Core\\Framework\\Context;\nuse Shopware\\Core\\Framework\\DataAbstractionLayer\\Search\\IdSearchResult;\nuse Shopware\\Core\\Framework\\DataAbstractionLayer\\Search\\Criteria;\nuse Shopware\\Core\\Framework\\DataAbstractionLayer\\Search\\Filter\\EqualsAnyFilter;\nuse SidebarNavigation\\Services\\SidebarNavigationCustomFieldSetService;\n\nclass SidebarNavigation extends Plugin\n{\n    public function install(InstallContext $installContext): void\n    {\n        parent::install($installContext);\n\n        $SidebarNavigationCustomFieldSetService = new SidebarNavigationCustomFieldSetService(\n            $this-&gt;container-&gt;get('custom_field_set.repository')\n        );\n\n        \/** @var Context $context *\/\n        $context = $installContext-&gt;getContext();\n\n        $SidebarNavigationCustomFieldSetService-&gt;createCategoryCustomFieldSet($context);\n    }\n\n    public function uninstall(UninstallContext $context): void\n    {\n        parent::uninstall($context);\n        if ($context-&gt;keepUserData()) {\n            return;\n        }\n\n        $this-&gt;removeCustomFields($context);\n    }\n\n    private function removeCustomFields(UninstallContext $uninstallContext)\n    {\n        $customFieldSetRepository = $this-&gt;container-&gt;get('custom_field_set.repository');\n\n        \/** @var Context $context *\/\n        $context = $uninstallContext-&gt;getContext();\n\n        \/\/ Delete custom field set\n\n        $this-&gt;deleteCustomFieldSet(\n            $context,\n            $customFieldSetRepository,\n            SidebarNavigationCustomFieldSetService::SIDEBAR_CATEGORY_NAVIGATION_CUSTOM_FIELD_SET\n        );\n    }\n\n    private function deleteCustomFieldSet(Context $context, $customFieldSetRepository, string $customFieldSet): void\n    {\n        $customFieldIds = $this-&gt;getCustomFieldSetIds($context, $customFieldSet);\n\n        if ($customFieldIds) {\n            $customFieldSetRepository-&gt;delete(array_values($customFieldIds-&gt;getData()), $context);\n        }\n    }\n\n    private function getCustomFieldSetIds(Context $context, string $customFieldSet): ?IdSearchResult\n    {\n        $customFieldSetRepository = $this-&gt;container-&gt;get('custom_field_set.repository');\n\n        $criteria = new Criteria();\n        $criteria-&gt;addFilter(new EqualsAnyFilter('name', [$customFieldSet]));\n\n        $customFieldIds = $customFieldSetRepository-&gt;searchIds($criteria, $context);\n\n        return $customFieldIds-&gt;getTotal() &gt; 0 ? $customFieldIds : null;\n    }\n}\n<\/pre>\n<p>Then create a service on the given location which will create custom field:<\/p>\n<p>\/custom\/plugins\/PluginRoot\/src\/Services<\/p>\n<pre>&lt;?php declare(strict_types=1);\n\nnamespace SidebarNavigation\\Services;\n\nuse Shopware\\Core\\Framework\\DataAbstractionLayer\\EntityRepositoryInterface;\nuse Shopware\\Core\\System\\CustomField\\CustomFieldTypes;\nuse Shopware\\Core\\Framework\\Context;\nuse Shopware\\Core\\Framework\\DataAbstractionLayer\\Search\\Criteria;\nuse Shopware\\Core\\Framework\\DataAbstractionLayer\\Search\\Filter\\EqualsFilter;\nuse Shopware\\Core\\System\\CustomField\\Aggregate\\CustomFieldSet\\CustomFieldSetCollection;\nuse Shopware\\Core\\Framework\\Uuid\\Uuid;\n\nclass SidebarNavigationCustomFieldSetService {\n    \/\/custom field set\n    public const SIDEBAR_CATEGORY_NAVIGATION_CUSTOM_FIELD_SET = 'sidebar_category_navigation_custom_field_set';\n\n    public const SIDEBAR_CATEGORY_ACTIVE_CUSTOM_FIELD = 'sidebar_category_active_custom_field';\n    \/**\n     * @var EntityRepositoryInterface\n     *\/\n    private $customFieldSetRepository;\n\n    public function __construct(EntityRepositoryInterface $customFieldSetRepository)\n    {\n        $this-&gt;customFieldSetRepository = $customFieldSetRepository;\n    }\n\n    public function createCategoryCustomFieldSet(Context $context): void\n    {\n        $criteria = new Criteria();\n        $criteria-&gt;addFilter(new EqualsFilter('name', self::SIDEBAR_CATEGORY_NAVIGATION_CUSTOM_FIELD_SET));\n\n        \/** @var CustomFieldSetCollection $customFieldSets *\/\n        $customFieldSets = $this-&gt;customFieldSetRepository-&gt;search($criteria, $context)-&gt;getEntities();\n\n        if (!count($customFieldSets)) {\n            $this-&gt;customFieldSetRepository-&gt;create([\n                [\n                    'name' =&gt; self::SIDEBAR_CATEGORY_NAVIGATION_CUSTOM_FIELD_SET,\n                    'global' =&gt; true,\n                    'config' =&gt; [\n                        'label' =&gt; [\n                            'de-DE' =&gt; 'Sidebar (Navigation)',\n                            'en-GB' =&gt; 'Sidebar (Navigation)'\n                        ]\n                    ],\n                'customFields' =&gt; [\n                    [\n                        'name' =&gt; self::SIDEBAR_CATEGORY_ACTIVE_CUSTOM_FIELD,\n                        'type' =&gt; CustomFieldTypes::SWITCH,\n                        'config' =&gt; [\n                            'label' =&gt; [\n                                'de-DE' =&gt; 'Hide in sidebar navigation',\n                                'en-GB' =&gt; 'Hide in sidebar navigation'\n                            ],\n\/\/Here I am creating SWITCH type field, we can create any field you want.\n                            'componentName' =&gt; 'sw-field',\n                            'type' =&gt; CustomFieldTypes::SWITCH,\n                            'customFieldType' =&gt; CustomFieldTypes::SWITCH,\n                            'customFieldPosition' =&gt; 1\n                        ]\n                    ]\n                ],\n                'relations' =&gt; [\n                    [\n                        'id' =&gt; Uuid::randomHex(),\n                        'entityName' =&gt; 'category' \/\/ You can use any entity where you want to create custom field.\n                    ]\n                ]\n                ]\n            ], $context);\n\n            \n        }\n    }\n}\n<\/pre>\n<p>Here are some more types of custom fields:<\/p>\n<div class=\"blog-innertxt\">\n<ul class=\"benefits-points\">\n<li>1) CustomFieldTypes::TEXT<\/li>\n<li>2) CustomFieldTypes::JSON<\/li>\n<li>3) CustomFieldTypes::INT<\/li>\n<li>4) CustomFieldTypes::BOOL<\/li>\n<\/ul>\n<\/div>\n<p>I have removed the categories from storefront for this I have extended the category navigation file. Follow the given location<br>\ncustom\/plugins\/PluginRoot\/src\/Resources\/views\/storefront\/layout\/sidebar<\/p>\n<pre>{% sw_extends '@Storefront\/storefront\/layout\/sidebar\/category-navigation.html.twig' %}\n\n{% block layout_navigation_categories_list_entry %}\n{% if not item.category.customFields.sidebar_category_active_custom_field is defined %}\n    &lt;li class=\"category-navigation-entry\"&gt;\n        {% block layout_navigation_categories_link_children %}\n           {{parent()}}\n        {% endblock %}\n        {% block layout_navigation_categories_recoursion %}\n            {{parent()}}\n        {% endblock %}\n    &lt;\/li&gt;\n{% endif %}\n{% endblock %}\n<\/pre>\n<p>Look into Screenshot on Category for new Custom Field:<\/p>\n<p><img decoding=\"async\" class=\"aligncenter size-full wp-image-12257\" src=\"\/blog\/wp-content\/uploads\/sites\/2\/2021\/09\/Shopware-custom-field-2-1.png\" alt=\"Shopware custom field 2\" width=\"1394\" height=\"528\"><br>\nHere is the screenshot of the categories with removed menus:<br>\n<img decoding=\"async\" class=\"aligncenter size-full wp-image-12259\" src=\"\/blog\/wp-content\/uploads\/sites\/2\/2021\/09\/shopware-removed-menus.png\" alt=\"shopware removed menus\" width=\"537\" height=\"533\"><\/p>\n\n","protected":false},"excerpt":{"rendered":"<p>Shopware&#8217;s custom field system allows you to extend entities, without writing a complete entity extension.This is possible by storing the additional data in a JSON-Field. Custom fields therefore can only be used to store scalar values. If you&#8217;d like to create associations between entities, you&#8217;ll need to use an Entity extension. Supporting custom fields with<\/p>\n","protected":false},"author":36,"featured_media":12334,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"MSN_Categories":"Uncategorized","MSN_Publish_Option":false,"MSN_Is_Local_News":false,"MSN_Is_AIAC_Included":"Empty","MSN_Location":"[]","MSN_Add_Feature_Img_On_Top_Of_Post":false,"MSN_Has_Custom_Author":false,"MSN_Custom_Author":"","MSN_Has_Custom_Canonical_Url":false,"MSN_Custom_Canonical_Url":"","_lmt_disableupdate":"","_lmt_disable":"","footnotes":""},"categories":[85],"tags":[84],"class_list":{"0":"post-12920","1":"post","2":"type-post","3":"status-publish","4":"format-standard","5":"has-post-thumbnail","7":"category-shopware","8":"tag-shopware"},"modified_by":"Marketing EmizenTech","featured_image_src":"https:\/\/multisitelocal.ezxdemo.com\/blog\/wp-content\/uploads\/sites\/2\/2021\/09\/How-To-Override-A-Controller-In-Shopware-6-1.png","featured_image_src_square":"https:\/\/multisitelocal.ezxdemo.com\/blog\/wp-content\/uploads\/sites\/2\/2021\/09\/How-To-Override-A-Controller-In-Shopware-6-1.png","author_info":{"display_name":"Vivek Khatri","author_link":"https:\/\/multisitelocal.ezxdemo.com\/blog\/author\/vivek"},"_links":{"self":[{"href":"https:\/\/multisitelocal.ezxdemo.com\/blog\/wp-json\/wp\/v2\/posts\/12920","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/multisitelocal.ezxdemo.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/multisitelocal.ezxdemo.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/multisitelocal.ezxdemo.com\/blog\/wp-json\/wp\/v2\/users\/36"}],"replies":[{"embeddable":true,"href":"https:\/\/multisitelocal.ezxdemo.com\/blog\/wp-json\/wp\/v2\/comments?post=12920"}],"version-history":[{"count":0,"href":"https:\/\/multisitelocal.ezxdemo.com\/blog\/wp-json\/wp\/v2\/posts\/12920\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/multisitelocal.ezxdemo.com\/blog\/wp-json\/wp\/v2\/media\/12334"}],"wp:attachment":[{"href":"https:\/\/multisitelocal.ezxdemo.com\/blog\/wp-json\/wp\/v2\/media?parent=12920"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/multisitelocal.ezxdemo.com\/blog\/wp-json\/wp\/v2\/categories?post=12920"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/multisitelocal.ezxdemo.com\/blog\/wp-json\/wp\/v2\/tags?post=12920"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}