Sylius Stack
  • Sylius Stack Documentation
  • Getting started
  • Cookbook
    • How to customize your admin panel
      • Basic operations
      • Customizing your grids
      • Customizing the logo
      • Customizing the menu
      • Configuring the security access
      • Customizing the page titles
    • How to use in a DDD architecture
      • Architecture overview
      • Resource configuration
      • Basic operations
      • Operation using a grid
  • Admin UI
    • Getting started
  • Bootstrap Admin UI
    • Getting started
  • Resource
    • Resource Bundle documentation
      • Installation
      • Create new resource
      • Configure your resource
      • Configure your operations
      • Validation
      • Redirect
      • Resource factories
      • Providers
      • Processors
      • Responders
      • Legacy Resource Documentation
        • Configuration
        • Services
        • Routing
        • Forms
        • Getting a Single Resource
        • Getting a Collection of Resources
        • Creating Resources
        • Updating Resources
        • Deleting Resources
        • Configuring a state machine
        • Configuration Reference
  • Grid
    • Grid Bundle documentation
      • Installation
      • Creating your first grid
      • Configuring Fields
      • Field types
      • Creating a custom Field Type
      • Creating a custom Action
      • Creating a custom Bulk Action
      • Filters
      • Creating a custom Filter
      • Advanced configuration
      • Configuration Reference
  • 🍀Twig Extra
    • Getting started
  • 🌱Twig Hooks
    • Getting started
    • Passing data to your hookables
    • Making your hookables configurable
    • Autoprefixing feature
    • Composable Layouts with a predictable structure
    • Advanced
      • Ergonomic work with hooks
      • Metadata objects
      • Multiple hooks inside a single template
      • Overriding hookables
Powered by GitBook
On this page
  • Default factory for your resource
  • Inject the factory in your service
  • Define your custom factory
  • Use your custom method
  • Pass arguments to your method
  • Use a factory without declaring it
  • Use a callable for your custom factory
  1. Resource
  2. Resource Bundle documentation

Resource factories

PreviousRedirectNextProviders

Last updated 1 month ago

Resource factories are used on Create operations to instantiate your resource.

Default factory for your resource

By default, a resource factory is defined to your resource Sylius\Component\Resource\Factory\Factory.

It has a createNew method with no arguments.

Inject the factory in your service

If you are using Symfony autowiring, you can inject the resource factory using the right variable name.

src/MyService.php
namespace App;

use Sylius\Resource\Factory\FactoryInterface;

final class MyService
{
    public function __construct(
        private FactoryInterface $bookFactory,
    ) {}
}

In this example, the app.factory.book will be injected in your $bookFactory

You can find the variable name using this debug command:

$ bin/console debug:autowiring app.factory.book

Define your custom factory

src/Factory/BookFactory.php
declare(strict_types=1);

namespace App\Factory;

use App\Entity\Book;
use Sylius\Resource\Factory\FactoryInterface;

final class BookFactory implements FactoryInterface
{
    public function createNew(): Book
    {
        $book = new Book();
        $book->setCreatedAt(new \DateTimeImmutable());
        
        return $book;
    }
}

Configure your factory

config/services.yaml
services:
    App\Factory\BookFactory:
        decorates: 'app.factory.book'

Use your custom method

src/Factory/BookFactory.php

declare(strict_types=1);

namespace App\Factory;

use App\Entity\Book;
use Sylius\Resource\Factory\FactoryInterface;
use Symfony\Component\Security\Core\Security;

final class BookFactory implements FactoryInterface
{
    public function __construct(private Security $security) 
    {
    }

    public function createNew(): Book
    {
        return new Book();
    }
    
    public function createWithCreator(): Book
    {
        $book = $this->createNew();
        
        $book->setCreator($this->security->getUser());
        
        return $book;
    }
}

Use it on your create operation

src/Entity/Book.php

declare(strict_types=1);

namespace App\Entity\Book;

use Sylius\Resource\Metadata\AsResource;
use Sylius\Resource\Metadata\Create;
use Sylius\Resource\Model\ResourceInterface;

#[AsResource(
    operations: [
        new Create(
            path: 'authors/{authorId}/books',
            factoryMethod: 'createWithCreator',
        ),
    ],
)
class Book implements ResourceInterface
{
}

Pass arguments to your method

You can pass arguments to your factory method.

3 variables are available:

  • request: to retrieve data from the request via Symfony\Component\HttpFoundation\Request

  • token: to retrieve data from the authentication token via Symfony\Component\Security\Core\Authentication\Token\TokenInterface

  • user: to retrieve data from the logged-in user via Symfony\Component\Security\Core\User\UserInterface

src/Factory/BookFactory.php

declare(strict_types=1);

namespace App\Factory;

use App\Entity\Book;
use Sylius\Resource\Doctrine\Persistence\RepositoryInterface;
use Sylius\Resource\Factory\FactoryInterface;

final class BookFactory implements FactoryInterface
{
    public function __construct(private RepositoryInterface $authorRepository) 
    {
    }

    public function createNew(): Book
    {
        return new Book();
    }
    
    public function createForAuthor(string $authorId): Book
    {
        $book = $this->createNew();
        
        $author = $this->authorRepository->find($authorId);
        
        $book->setAuthor($author);
        
        return $book;
    }
}

Use it on your create operation

src/Entity/Book.php

declare(strict_types=1);

namespace App\Entity\Book;

use Sylius\Resource\Model\ResourceInterface;
use Sylius\Resource\Metadata\AsResource;
use Sylius\Resource\Metadata\Create;

#[AsResource(
    operations: [
        new Create(
            path: 'authors/{authorId}/books',
            factoryMethod: 'createForAuthor',
            factoryArguments: ['authorId' => "request.attributes.get('authorId')"],
        ),
    ],
)
class Book implements ResourceInterface
{
}

Use a factory without declaring it

You can use a factory without declaring it on services.yaml.

src/Entity/Book.php

declare(strict_types=1);

namespace App\Entity\Book;

use App\Factory\BookFactory;
use Sylius\Resource\Model\ResourceInterface;
use Sylius\Resource\Metadata\AsResource;
use Sylius\Resource\Metadata\Create;

#[AsResource(
    operations: [
        new Create(
            path: 'authors/{authorId}/books',
            # Here we declared the factory to use with its fully classified class name
            factory: BookFactory::class,
            factoryMethod: 'createForAuthor', 
            factoryArguments: ['authorId' => "request.attributes.get('authorId')"],
        ),
    ],
)
class Book implements ResourceInterface
{
}

Use a callable for your custom factory

src/Factory/BookFactory.php

declare(strict_types=1);

namespace App\Factory;

use App\Entity\Book;

final class BookFactory
{    
    public static function create(): Book
    {
        return new Book();
    }
}
src/Entity/Book.php

declare(strict_types=1);

namespace App\Entity\Book;

use App\Factory\BookFactory;
use Sylius\Resource\Metadata\AsResource;
use Sylius\Resource\Metadata\Create;
use Sylius\Resource\Model\ResourceInterface

#[AsResource(
    operations: [
        new Create(
            factory: [BookFactory::class, 'create'], 
        ),
    ],
)
class Book implements ResourceInterface
{
}

It uses the component.

Symfony expression language
Resource factories
Default factory for your resource
Inject the factory in your service
Define your custom factory
Use your custom method
Pass arguments to your method
Use a factory without declaring it
Use a callable for your custom factory