Installation
Add the bundle to your composer.json:
composer require sylius/resource-bundle
Enable it in config/bundles.php:
return [
// ...
Sylius\ResourceBundle\SyliusResourceBundle::class => ['all' => true],
];
Define a Resource
Annotate your entity with @AsResource (or use the attribute [AsResource] in PHP 8+):
use Sylius\Component\Resource\Model\ResourceInterface;
use Sylius\ResourceBundle\Annotation\AsResource;
#[AsResource]
class Product implements ResourceInterface
{
// Your entity properties
}
Configure the Resource
Define the resource in config/packages/sylius_resource.yaml:
sylius_resource:
resources:
App\Entity\Product:
driver: doctrine/orm
repository:
type: doctrine
class: App\Repository\ProductRepository
factory:
type: doctrine
class: App\Factory\ProductFactory
form: App\Form\ProductType
Generate Basic CRUD
Use the sylius:resource:generate command to scaffold controllers and routes:
php bin/console sylius:resource:generate App\Entity\Product
First Use Case
Access the generated routes (e.g., /api/products for listing, /api/products/{id} for detail) or integrate with your frontend.
doctrine/orm, doctrine/mongodb, or custom drivers via driver: { type: custom, class: MyCustomDriver }.class ProductRepository extends ServiceEntityRepository
{
public function findByActive(bool $active): array
{
return $this->createQueryBuilder('p')
->andWhere('p.active = :active')
->setParameter('active', $active)
->getQuery()
->getResult();
}
}
class ProductFactory implements FactoryInterface
{
public function createNew(): Product
{
return new Product();
}
}
AbstractResourceController for shared logic:
use Sylius\Bundle\ResourceBundle\Controller\AbstractResourceController;
class ProductController extends AbstractResourceController
{
protected function configureActions(Actions $actions): Actions
{
return $actions
->index()
->create()
->update()
->delete();
}
}
# config/packages/sylius_resource.yaml
sylius_resource:
resources:
App\Entity\Product:
actions:
bulk_delete: true
?active=true):
// In your repository
public function createQueryBuilder(string $alias, ?string $indexBy = null): QueryBuilder
{
$qb = parent::createQueryBuilder($alias, $indexBy);
$active = $this->getRequest()->query->get('active');
if ($active !== null) {
$qb->andWhere("p.active = :active")->setParameter('active', $active);
}
return $qb;
}
?sort=-createdAt:
sylius_resource:
resources:
App\Entity\Product:
sorting:
createdAt: ~
name: ~
sylius_resource:
resources:
App\Entity\Product:
state_machine:
machine: product_state_machine
transition: publish
use Sylius\Component\Resource\StateMachine\Guard\GuardInterface;
class PublishGuard implements GuardInterface
{
public function supports(object $object, string $transition): bool
{
return $object instanceof Product && $object->isReadyToPublish();
}
}
sylius_resource:
resources:
App\Entity\Product:
serialization:
groups: ['api']
use Pagerfanta\Pagerfanta;
public function indexAction(Request $request): Response
{
$pager = new Pagerfanta(new ArrayAdapter($this->repository->findAll()));
$pager->setMaxPerPage(10);
$pager->setCurrentPage($request->query->getInt('page', 1));
return $this->handleView($this->view($pager, 200));
}
pre_create, post_update):
use Sylius\Component\Resource\Model\ResourceInterface;
use Sylius\Component\Resource\ResourceEvents;
$eventDispatcher->addListener(ResourceEvents::PRE_CREATE, function (ResourceEvent $event) {
if ($event->getSubject() instanceof Product) {
$event->getSubject()->setCreatedBy($this->getUser());
}
});
$eventDispatcher->addListener(ResourceEvents::POST_CREATE, function (ResourceEvent $event) {
$this->addFlash('success', 'Product created successfully!');
});
Doctrine Attributes:
Use Doctrine’s attributes (e.g., [ORM\Entity], [ORM\Table]) alongside AsResource for cleaner annotations.
Symfony UX: Combine with Symfony UX for reactive forms:
use Symfony\UX\LiveComponent\Attribute\AsLiveComponent;
#[AsLiveComponent('product_form')]
class ProductFormType extends AbstractType
{
// ...
}
Testing:
Use the sylius:resource:debug command to inspect resource configurations:
php bin/console sylius:resource:debug App\Entity\Product
Validation: Integrate with Symfony Validator for form validation:
use Symfony\Component\Validator\Constraints as Assert;
class Product
{
#[Assert\NotBlank]
private string $name;
}
API Platform: For API-first projects, pair with API Platform for automatic API generation:
# config/packages/api_platform.yaml
api_platform:
formats:
jsonld:
mime_types: ['application/ld+json']
patch_formats:
json: true
Route Conflicts:
DELETE /products/{id}) may conflict with other bundles.sylius_resource:
resources:
App\Entity\Product:
route_name_prefix: api_products
Circular Dependencies:
interface ProductRepositoryInterface extends RepositoryInterface
{
// ...
}
State Machine Mismatches:
php bin/console debug:state-machine App\Entity\Product
Pagination Limits:
$pager->setMaxPerPage(50); // Adjust as needed
Form Parameter Bags:
class ProductType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('images', CollectionType::class, [
'entry_type' => ImageType::class,
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false,
]);
}
}
**Doctrine Event List
How can I help you explore Laravel packages today?