Skip to content

Fixture Bundle

Fixture Bundle ​

The Fixture Bundle provides a flexible and organized way to load test and demo data into your Shopware 6 application. It's designed to be extensible and easy to use, supporting dependency management, priority-based execution, and group filtering. This guide walks you through creating and managing data fixtures for your Shopware project.

Installation ​

To get started, add the Fixture Bundle to your project using Composer:

bash
composer require shopware/fixture-bundle:*

Creating a basic fixture ​

To create a fixture, you need to create a new class that implements the Shopware\Core\Framework\Test\TestCaseBase\FixtureInterface and has the #[Fixture] attribute.

Here is an example of a simple fixture that creates two product categories:

php
<?php declare(strict_types=1);

namespace Swag\BasicExample\Test\Fixture;

use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
use Shopware\Core\Framework\Test\TestCaseBase\Fixture;
use Shopware\Core\Framework\Test\TestCaseBase\FixtureInterface;
use Shopware\Core\Framework\Uuid\Uuid;
use Symfony\Component\DependencyInjection\Attribute\Autowire;

#[Fixture(name: 'category')]
class CategoryFixture implements FixtureInterface
{
    public function __construct(
 #[Autowire(service: 'category.repository')]
        private readonly EntityRepository $categoryRepository,
    ) {
    }

    public function load(): void
    {
        $categories = [
            [
                'id' => Uuid::randomHex(),
                'name' => 'Electronics',
                'active' => true,
            ],
            [
                'id' => Uuid::randomHex(),
                'name' => 'Clothing',
                'active' => true,
            ],
        ];

        $this->categoryRepository->create($categories, Context::createDefaultContext());
    }
}

The Fixture attribute ​

The #[Fixture] attribute configures the behavior of your fixture and accepts the following parameters:

  • priority (int, default: 0): A higher integer means the fixture will be executed earlier.
  • dependsOn (array, default: []): An array of fixture class names that must be executed before this fixture.
  • groups (array, default: ['default']): An array of group names this fixture belongs to. This allows for selective loading of fixtures.

Commands ​

The Fixture Bundle comes with two bin/console commands to help you manage your fixtures.

Loading fixtures ​

To execute your fixtures and load data into the database, use the fixture:load command.

  • Load all fixtures:
bash
   bin/console fixture:load
  • Load fixtures from a specific group: You can also load a subset of fixtures by specifying a group. This is useful for separating test data from demo data, for example.
bash
   bin/console fixture:load --group=test-data

Listing fixtures ​

To see a list of all available fixtures, their execution order, and their configuration, use the fixture:list command.

bash
bin/console fixture:list

This command provides a clear overview of how your fixtures are prioritized and their dependencies.

Example output:

text
 Available Fixtures
 ==================

+-------+---------------------+----------+-----------------+---------------------+
| Order | Class               | Priority | Groups          | Depends On          |
+-------+---------------------+----------+-----------------+---------------------+
| 1     | CategoryFixture     | 100      | catalog, test-  | -                   |
|       |                     |          | data            |                     |
| 2     | ManufacturerFixture | 90       | catalog         | -                   |
| 3     | ProductFixture      | 50       | catalog, test-  | CategoryFixture,    |
|       |                     |          | data            | ManufacturerFixture |
| 4     | CustomerFixture     | 0        | customers       | -                   |
+-------+---------------------+----------+-----------------+---------------------+

 [OK] Found 4 fixture(s).

Execution order ​

The following rules determine the execution order of fixtures:

  1. Dependencies: If a fixture declares dependencies using dependsOn, it will always run after its dependencies have been executed.
  2. Priority: Among fixtures without dependency relationships, those with a higher priority value are executed first.
  3. Circular dependency detection: The system will throw an exception if circular dependencies are detected, preventing infinite loops.

Specialized fixtures ​

The Fixture Bundle includes several specialized loaders to simplify common data creation tasks.

Theme fixtures ​

The ThemeFixtureLoader provides a convenient, fluent interface for configuring theme settings. It automatically handles theme discovery and recompilation and applies changes only when necessary.

php
<?php declare(strict_types=1);

namespace Swag\BasicExample\Test\Fixture;

use Shopware\Core\Framework\Test\TestCaseBase\Fixture;
use Shopware\Core\Framework\Test\TestCaseBase\FixtureInterface;
use Shopware\Storefront\Theme\ThemeDefinition;

#[Fixture(name: 'theme', groups: ['theme-config', 'branding'])]
class ThemeFixture implements FixtureInterface
{
    public function __construct(
        private readonly ThemeFixtureLoader $themeFixtureLoader
    ) {
    }

    public function load(): void
    {
        // Will be uploaded just once and reused based on file content
        $logo = $this->mediaHelper->upload(__DIR__ . '/shop.png', $this->mediaHelper->getDefaultFolder(ThemeDefinition::ENTITY_NAME)->getId());

        $this->themeFixtureLoader->apply(
            (new ThemeFixtureDefinition('Shopware default theme'))
                ->config('sw-color-brand-primary', '#ff6900')
                ->config('sw-border-radius-default', '8px')
                ->config('sw-font-family-base', '"Inter", sans-serif')
                ->config('sw-logo-desktop', $logo)
        );
    }
}

Custom field fixtures ​

The CustomFieldSetFixtureLoader helps you create and manage custom field sets and their associated custom fields for different entities.

php
<?php declare(strict_types=1);

namespace Swag\BasicExample\Test\Fixture;

use Shopware\Core\Framework\Test\TestCaseBase\Fixture;
use Shopware\Core\Framework\Test\TestCaseBase\FixtureInterface;
use Shopware\Core\System\CustomField\CustomFieldTypes;

#[Fixture(name: 'custom-field')]
class CustomFieldFixture implements FixtureInterface
{
    public function __construct(
        private readonly CustomFieldSetFixtureLoader $customFieldSetFixtureLoader
    ) {
    }

    public function load(): void
    {
        $this->customFieldSetFixtureLoader->apply(
            (new CustomFieldSetFixtureDefinition('Product Specifications', 'product_specs'))
                ->relation('product')
                ->field(
                    (new CustomFieldFixtureDefinition('weight', CustomFieldTypes::FLOAT))
                        ->label('en-GB', 'Weight (kg)')
                        ->label('de-DE', 'Gewicht (kg)')
                )
                ->field(
                    (new CustomFieldFixtureDefinition('warranty_period', CustomFieldTypes::INT))
                        ->label('en-GB', 'Warranty Period (months)')
                )
        );
    }
}

Customer fixtures ​

The CustomerFixtureLoader offers a comprehensive way to create customers with addresses, custom fields, and other properties. The loader uses the email address as a unique identifier and updates existing customers if a match is found.

php
<?php declare(strict_types=1);

namespace Swag\BasicExample\Test\Fixture;

use Shopware\Core\Framework\Test\TestCaseBase\Fixture;
use Shopware\Core\Framework\Test\TestCaseBase\FixtureInterface;

#[Fixture(name: 'customer', groups: ['customers', 'addresses'])]
class CustomerFixture implements FixtureInterface
{
    public function __construct(
        private readonly CustomerFixtureLoader $customerFixtureLoader
    ) {
    }

    public function load(): void
    {
        $this->customerFixtureLoader->apply(
            (new CustomerFixtureDefinition('max.mustermann@example.com'))
                ->firstName('Max')
                ->lastName('Mustermann')
                ->salutation('mr')
                ->password('password')
                ->defaultBillingAddress([
                    'firstName' => 'Max',
                    'lastName' => 'Mustermann',
                    'street' => 'Musterstraße 123',
                    'zipcode' => '12345',
                    'city' => 'Musterstadt',
                    'country' => 'DEU',
                ])
                ->addAddress('work', [
                    'firstName' => 'Max',
                    'lastName' => 'Mustermann',
                    'street' => 'Office Street 789',
                    'zipcode' => '11111',
                    'city' => 'Business City',
                    'country' => 'DEU',
                ])
        );
    }
}

Best practices ​

  • Meaningful Names: Give your fixture classes clear, descriptive names.
  • Organize with Groups: Use groups like test-data, demo-data, or performance-test to categorize fixtures.
  • Declare Dependencies: Explicitly declare dependencies to ensure a predictable and correct execution order.
  • Focused Fixtures: Each fixture should have a single, clear responsibility.
  • Idempotent Design: Fixtures should be possible to run multiple times without causing errors or creating duplicate data.
  • Use Dependency Injection: Inject services into your fixture's constructor instead of fetching them from the container.

By following these guidelines, you can build a robust and maintainable set of data fixtures for your Shopware project.

Was this page helpful?
UnsatisfiedSatisfied
Be the first to vote!
0.0 / 5  (0 votes)