Skip to content

Data Fixtures

Fixtures provide deterministic development and test data. The core application ships a custom AbstractFixture base class that all fixture classes — both core and plugin — extend.


Core fixtures overview

The following fixture classes live in src/DataFixtures/ and are loaded on every full dev reset:

Fixture class What it creates Reference names
SystemUserFixture System/bot user for automated actions system
UserFixture Regular users (admin, organizers, members) Admin, Crystal Liu, Adem Lane, …
HostFixture Host records linked to users Admin, Crystal, Adem, Jessie, Mollie
LocationFixture Physical and online venues Weiqi Cafe, Community Center, Online Platform, …
EventFixture Events with translations, RSVPs, comments Weekly Go Study Group, Berlin Go Tournament 2026, …
CmsFixture CMS pages (about, imprint, privacy, …) about, imprint, …
CmsBlockFixture Content blocks for CMS pages
ConfigFixture Application configuration defaults
LanguageFixture Supported languages
EmailTemplateFixture Email template content
ActivityFixture Activity log entries
MinimalAdminFixture Minimal admin user for install group

Reference names are the string keys passed to addRefXxx() in each fixture. Check the fixture class constants (e.g. UserFixture::ADMIN) for the exact values.


Why extend AbstractFixture?

App\DataFixtures\AbstractFixture provides type-safe helper methods that resolve references to core fixture objects by name. This avoids querying the database and ensures your fixture data links to the same objects the core fixtures created.

namespace App\DataFixtures;

use Doctrine\Persistence\ObjectManager;

class MyEntityFixture extends AbstractFixture
{
    public function load(ObjectManager $manager): void
    {
        // Resolve core fixture references by name
        $user  = $this->getRefUser(UserFixture::ADMIN);
        $event = $this->getRefEvent(EventFixture::WEEKLY_GO_STUDY);

        $entity = new MyEntity();
        $entity->setUser($user);
        $entity->setEvent($event);

        $manager->persist($entity);
        $this->addRefMyEntity('my_entity', $entity);

        $manager->flush();
    }
}

Cross-fixture references

AbstractFixture provides typed getters and setters for all core reference types:

Getter Setter Returns
getRefUser(string $name) addRefUser(string $name, User $entity) User
getRefEvent(string $name) addRefEvent(string $name, Event $entity) Event
getRefLocation(string $name) addRefLocation(string $name, Location $entity) Location
getRefCms(string $name) addRefCms(string $name, Cms $entity) Cms
getRefHost(string $name) addRefHost(string $name, Host $entity) Host

References are keyed by the string name you pass. For core fixtures, use the class constants (e.g. UserFixture::ADMIN, EventFixture::WEEKLY_GO_STUDY) to avoid typos.


Creating a core fixture

Full example of a new AbstractFixture subclass for a new entity:

<?php declare(strict_types=1);

namespace App\DataFixtures;

use App\Entity\Rating;
use Doctrine\Bundle\FixturesBundle\Attribute\AsFixture;
use Doctrine\Common\DataFixtures\DependentFixtureInterface;
use Doctrine\Persistence\ObjectManager;

#[AsFixture(groups: ['base'])]
class RatingFixture extends AbstractFixture implements DependentFixtureInterface
{
    public const string FIVE_STARS = 'five-star-rating';

    public function load(ObjectManager $manager): void
    {
        $this->start();

        $rating = new Rating();
        $rating->setUser($this->getRefUser(UserFixture::ADMIN));
        $rating->setEvent($this->getRefEvent(EventFixture::WEEKLY_GO_STUDY));
        $rating->setScore(5);

        $manager->persist($rating);
        $this->addRefRating(self::FIVE_STARS, $rating);

        $manager->flush();
        $this->stop();
    }

    public function getDependencies(): array
    {
        return [UserFixture::class, EventFixture::class];
    }
}

Key points: - Use #[AsFixture(groups: ['base'])] for standard dev data - Use #[AsFixture(groups: ['install'])] only for data required at first-time install - Declare getDependencies() to ensure load order - Call $this->start() / $this->stop() for consistent progress output


Fixture groups

Fixtures are tagged with groups to control when they run:

Group When used
base Loaded by just devModeFixtures — full development reset (default for core fixtures)
plugin Plugin fixtures loaded during full dev reset
install Loaded during first-time installation (minimal required data only)

Most new fixtures belong to the base (core) or plugin (plugin code) group. Only add install if the data is required for the application to function at all (e.g. default configuration values, language records).


Helper methods

$this->start();                        // Prints "Creating FixtureName ..."
$this->stop();                         // Prints " OK\n"
$text = $this->getText('filename');    // Reads DataFixtures/FixtureName/filename.txt

Use getText() to keep long text content (event descriptions, CMS page bodies) in separate .txt files instead of PHP strings.


Dev commands

# Full dev reset — loads all fixtures
just devModeFixtures

# Load only a specific plugin's fixtures
just devModeFixtures your-plugin

# Minimal reset — loads install group only (faster)
just devModeMinimal

Fixture hooks for plugins

Plugins can run code before and after fixture loading via preFixtures(), loadPostExtendFixtures(), and postFixtures() in their Kernel.php. These hooks are documented in Required Hooks.