Korzystanie z pól niestandardowych w Shopware 6
Podczas opracowywania nowej wtyczki w Shopware 6 często konieczne jest włączenie pól niestandardowych. Pola te mają wiele funkcji, które można szczegółowo zbadać na stronie dokumentacji Shopware. Zasadniczo pola niestandardowe Shopware umożliwiają przechowywanie dodatkowych danych na temat różnych podmiotów. Dane te są przechowywane w bazie danych w formacie JSON i są dostępne jako tablica. W tym artykule skupimy się na prawidłowej implementacji pól niestandardowych w projekcie. Treść jest skierowana do programistów, którzy zdobyli już pewne doświadczenie w tworzeniu wtyczek.
Typowe błędy, których należy unikać
- Zaniedbanie usuwania nieużywanych pól niestandardowych – częsty błąd występuje, gdy definicja pola niestandardowego jest dodawana podczas instalacji wtyczki, ale nie jest usuwana, gdy nie jest już potrzebna. To niedopatrzenie może prowadzić do błędów podczas ponownej instalacji wtyczki, ponieważ system wskaże, że definicja już istnieje.
- Przeciążenie głównego pliku wtyczki danymi – Kolejne wyzwanie pojawia się, gdy istnieje potrzeba dodania znacznej ilości danych. Jeśli wymaganych jest wiele definicji, główny plik instalacyjny wtyczki może stać się zbyt długi, zwłaszcza jeśli wtyczka zawiera wiele funkcji. W takich przypadkach zaleca się przeniesienie instalacji pól niestandardowych do oddzielnej klasy lub nawet wielu klas, jeśli istnieje wiele pól niestandardowych do zarządzania.
Poniżej znajduje się przykład tego, jak może wyglądać główny plik wtyczki.
<?php declare(strict_types=1);
namespace Example;
use Example\Service\OrderCustomFields;
use Shopware\Core\Framework\Plugin;
use Shopware\Core\Framework\Plugin\Context\ActivateContext;
use Shopware\Core\Framework\Plugin\Context\DeactivateContext;
use Shopware\Core\Framework\Plugin\Context\InstallContext;
use Shopware\Core\Framework\Plugin\Context\UninstallContext;
class Example extends Plugin
{
public function install(InstallContext $installContext): void
{
(new OrderCustomFields($this--->container))
->installCustomFields($installContext->getContext());
}
public function activate(ActivateContext $activateContext): void
{
(new OrderCustomFields($this->container))
->activateCustomFields($activateContext->getContext());
}
public function deactivate(DeactivateContext $deactivateContext): void
{
(new OrderCustomFields($this->container))
->deactivateCustomFields($deactivateContext->getContext());
}
public function uninstall(UninstallContext $uninstallContext): void
{
(new OrderCustomFields($this->container))
->uninstallCustomFields($uninstallContext->getContext());
}
}
Wdrożenie tego podejścia ułatwi rozszerzenie dodatkowych pól w przyszłości i zapobiegnie nadmiernemu zaśmieceniu głównej klasy wtyczki kodem.
Jak instalować Order Custom Field
Przyjrzyjmy się bliżej samej klasie OrderCustomField. Aby usprawnić zarządzanie polami niestandardowymi, zaleca się zdefiniowanie kluczy dla tych pól jako stałych na początku definicji klasy.
class OrderCustomFields
{
public const LABEL_CUSTOM_FIELD_KEY = custom_label;
public const ONE_CUSTOM_FIELD_KEY = 'custom_field_one';
public const TWO_CUSTOM_FIELD_KEY = 'custom_field_two';
protected ContainerInterface $container;
public function __construct(ContainerInterface $container)
{
$this->container = $container;
}
public function installCustomFields(Context $context): void
{
$searchResults = $this->getCustomFields($context);
if($searchResults->getTotal() === 0)
{
// Add custom fields
}
}
public function activateCustomFields(Context $context): void
{
$this->setCustomFieldsActivate(
$this->getCustomFields($context)->getIds(), true, $context);
}
public function deactivateCustomFields(Context $context): void
{
$this->setCustomFieldsActivate(
$this->getCustomFields($context)->getIds(), false, $context);
}
public function uninstallCustomFields(Context $context): void
{
$customFieldsIds = $this->getCustomFields($context)->getIds();
if(count($customFieldsIds) !== 0)
{
$this->container->get('custom_field_set.repository')->delete([[
'id' => $customFieldsIds[0]
]], $context);
}
}
private function setCustomFieldsActivate(array $customFieldsIds, bool $active, Context $context): void
{
$this->container->get('custom_field_set.repository')->update([[
'id' => $customFieldsIds[0],
'active' => $active
]], $context);
}
private function getCustomFields(Context $context): IdSearchResult
{
return $this->container->get('custom_field_set.repository')->searchIds(
(new Criteria())->addFilter(new EqualsFilter(
'name', self::LABEL_CUSTOM_FIELD_KEY)), $context);
}
}
Tworzenie Custom Fields
Po ustaleniu przepływu zarządzania polami niestandardowymi można przystąpić do faktycznego tworzenia tych pól. Podczas dodawania pól niestandardowych należy pamiętać, że należy uwzględnić zarówno definicję zestawu pól niestandardowych (która odpowiada tabeli w bazie danych o nazwie „custom_field_set”), jak i same definicje pól (znajdujące się w tabelach „custom_field”). Wszelkie zmiany wprowadzone w statusie zestawu będą miały wpływ na wszystkie powiązane pola.
Na przykład podstawowa struktura tworzenia pola może wyglądać następująco:
public function installCustomFields(Context $context): void
{
$searchResults = $this->getCustomFields($context);
if($searchResults->getTotal() === 0)
{
$customField = [
'name' => self::LABEL_CUSTOM_FIELD_KEY,
'active' => false,
'config' => [
'label' => [
'en-GB' => 'Label translation'
]
],
'relations' => [
[
'entityName' => 'order'
]
],
'customFields' => [
[
'name' => self::ONE_CUSTOM_FIELD_KEY,
'type' => CustomFieldTypes::TEXT,
'config' => [
'label' => [
'en-GB' => 'Field one translation'
]
]
], [
'name' => self::TWO_CUSTOM_FIELD_KEY,
'type' => CustomFieldTypes::TEXT,
'config' => [
'label' => [
'en-GB' => 'Field two translation'
]
]
]
]
];
$this->container->get('custom_field_set.repository')->create([$customField], $context);
}
}
Na tym etapie proces można technicznie uznać za zakończony. Jednak pola niestandardowe są zwykle dodawane w języku, z którego będzie korzystał klient. Podczas tworzenia wtyczki do sklepu konieczne jest uwzględnienie tłumaczeń w wielu językach. Jak można to zrobić najskuteczniej? Poniższy przykład pokazuje nie tylko jak oddzielić tłumaczenia od kodu, który dodaje pola, ale także jak upewnić się, że dodawane są tylko tłumaczenia dla języków już obecnych w bazie danych Shopware.
Pierwszym krokiem jest stworzenie nowej klasy, która będzie obsługiwać tłumaczenia:
class CustomFieldsTranslation
{
public const TRANSLATIONS = [
'en-GB' => [
OrderCustomFields::LABEL_CUSTOM_FIELD_KEY => 'Label translation',
OrderCustomFields::ONE_CUSTOM_FIELD_KEY => 'Field one translation',
OrderCustomFields::TWO_CUSTOM_FIELD_KEY => 'Field two translation'
],
'pl-PL' => [
OrderCustomFields::LABEL_CUSTOM_FIELD_KEY => 'Label translation',
OrderCustomFields::ONE_CUSTOM_FIELD_KEY => 'Field one translation',
OrderCustomFields::TWO_CUSTOM_FIELD_KEY => 'Field two translation'
]
];
}
Wracając do klasy odpowiedzialnej za tworzenie pól niestandardowych, musisz dodać funkcję, która pobiera dostępne języki:
private function getAvailableLanguages(Context $context): array
{
return $this->container->get('language.repository')->search(
(new Criteria())->addAssociation('locale'),
$context
)->getElements();
}
Następnie dołącz funkcję, która będzie obsługiwać generowanie tłumaczeń:
private function generateTranslation(string $key, array $languages): array
{
$translation = [];
foreach($languages as $language)
{
$code = $language->getLocale()->getCode();
if(isset(CustomFieldsTranslation::TRANSLATIONS[$code]))
{
$translation['config']['label'][$code] = CustomFieldsTranslation::TRANSLATIONS[$code][$key];
}
}
return $translation;
}
Następnie dokonaj niezbędnych zmian w funkcji generatora:
if($searchResults->getTotal() === 0)
{
$languages = $this->getAvailableLanguages($context);
$customField = [
'name' => self::LABEL_CUSTOM_FIELD_KEY,
'active' => false,
'config' => $this->generateTranslation(self::LABEL_CUSTOM_FIELD_KEY, $languages),
'customFields' => [
[
'name' => self::ONE_CUSTOM_FIELD_KEY,
'type' => CustomFieldTypes::TEXT,
'config' => $this->generateTranslation(self::ONE_CUSTOM_FIELD_KEY, $languages)
], [
'name' => self::TWO_CUSTOM_FIELD_KEY,
'type' => CustomFieldTypes::TEXT,
'config' => $this->generateTranslation(self::TWO_CUSTOM_FIELD_KEY, $languages)
]
]
];
$this->container->get('custom_field_set.repository')->create([$customField], $context);
}
Takie podejście skutkuje solidną implementacją pól niestandardowych, które można bez wysiłku rozszerzyć o dodatkowe pola lub języki w razie potrzeby.
Kategorie:Shopware
Tagi:


