### Install Python Dependencies for Docs Source: https://github.com/sonata-project/sonatadoctrineormadminbundle/blob/4.x/CONTRIBUTING.md Installs Python dependencies required for rendering documentation using Sphinx. It reads requirements from a specified file and installs them for the current user. ```bash pip install --requirement docs/requirements.txt --user ``` -------------------------------- ### Example: Good Commit Message with Contextual Description Source: https://github.com/sonata-project/sonatadoctrineormadminbundle/blob/4.x/CONTRIBUTING.md Presents an example of a good commit message with a descriptive subject and a detailed explanation of the changes, including references to related discussions or issues. ```text Change web UI background color to pink This is a consensus made on #4242 in addition to #1337. We agreed that blank color is boring and so deja vu. Pink is the new way to do. ``` -------------------------------- ### Build Documentation Source: https://github.com/sonata-project/sonatadoctrineormadminbundle/blob/4.x/CONTRIBUTING.md Builds the project documentation using the 'make docs' command. This command typically relies on Sphinx and requires the Python dependencies to be installed first. The output is generated in the 'docs/_build/html' directory. ```bash make docs ``` -------------------------------- ### Example: Good Commit Message Subject Source: https://github.com/sonata-project/sonatadoctrineormadminbundle/blob/4.x/CONTRIBUTING.md Provides an example of a well-crafted commit message subject line that is concise and clearly states the action taken. ```text Document how to install the project ``` -------------------------------- ### Example: Commit Message with Description Source: https://github.com/sonata-project/sonatadoctrineormadminbundle/blob/4.x/CONTRIBUTING.md Demonstrates a comprehensive commit message including a clear subject and a detailed description explaining the changes and their context, referencing related issues. ```text call foo::bar() instead of bar::baz() This fixes a bug that arises when doing this or that, because baz() needs a flux capacitor object that might not be defined. Fixes #42 ``` -------------------------------- ### Example: Bad Commit Message Subject Source: https://github.com/sonata-project/sonatadoctrineormadminbundle/blob/4.x/CONTRIBUTING.md Illustrates a poorly written commit message subject line that lacks specificity and clarity. ```text Update README.md ``` -------------------------------- ### Open Documentation in Browser Source: https://github.com/sonata-project/sonatadoctrineormadminbundle/blob/4.x/CONTRIBUTING.md Opens the locally built documentation in the user's default web browser. The documentation files are located in the 'docs/_build/html/index.html' path. ```bash $YOUR_FAVORITE_BROWSER docs/_build/html/index.html ``` -------------------------------- ### PHP Docblock Annotations for Static Analysis Source: https://github.com/sonata-project/sonatadoctrineormadminbundle/blob/4.x/CONTRIBUTING.md Example of using PHP docblock annotations for static analysis, prioritizing `@phpstan-` annotations for IDE support and consistency. Standard annotations are used when necessary. ```php /** * @param Bar|Baz $foo * @param class-string $class * @param int $limit a crucial, fascinating comment * * @return object * * @phpstan-template T of object * @phpstan-param class-string $class * @phpstan-return T */ protected function bar($foo, string $class, int $limit): object { // ... } ``` -------------------------------- ### Install SonataDoctrineORMAdminBundle with Composer Source: https://github.com/sonata-project/sonatadoctrineormadminbundle/blob/4.x/docs/reference/installation.rst This command installs the SonataDoctrineORMAdminBundle using Composer, the dependency manager for PHP. Ensure Composer is installed and accessible in your environment. ```bash composer require sonata-project/doctrine-orm-admin-bundle ``` -------------------------------- ### Install EntityAuditBundle Source: https://github.com/sonata-project/sonatadoctrineormadminbundle/blob/4.x/docs/reference/audit.rst Installs the optional EntityAuditBundle using Composer, which is required for the audit functionality. ```bash composer require sonata-project/entity-audit-bundle ``` -------------------------------- ### Fix Coding Style with PHP CS Fixer Source: https://github.com/sonata-project/sonatadoctrineormadminbundle/blob/4.x/CONTRIBUTING.md This command uses the PHP Coding Standard Fixer tool to automatically format code according to Symfony Coding Standards. Ensure PHP CS Fixer is installed before running. ```bash php-cs-fixer fix --verbose ``` -------------------------------- ### XML Deprecation: Service Definition Source: https://github.com/sonata-project/sonatadoctrineormadminbundle/blob/4.x/CONTRIBUTING.md Shows how to mark a service as deprecated in an XML configuration file, including a deprecation message specifying the version and reason for deprecation. ```xml The "%service_id%" service is deprecated since sonata-project/bar-bundle 42.x and will be removed in 43.0. ``` -------------------------------- ### Enable EntityAuditBundle Source: https://github.com/sonata-project/sonatadoctrineormadminbundle/blob/4.x/docs/reference/audit.rst Enables the installed EntityAuditBundle in the application's bundles.php configuration file. ```php // config/bundles.php return [ // ... SimpleThings\EntityAudit\SimpleThingsEntityAuditBundle::class => ['all' => true], ]; ``` -------------------------------- ### Enable SonataDoctrineORMAdminBundle in bundles.php Source: https://github.com/sonata-project/sonatadoctrineormadminbundle/blob/4.x/docs/reference/installation.rst This PHP code snippet shows how to enable the SonataDoctrineORMAdminBundle by adding its class to the bundles configuration array in the config/bundles.php file. This is a standard practice for enabling bundles in Symfony applications. ```php // config/bundles.php return [ // ... Sonata\DoctrineORMAdminBundle\SonataDoctrineORMAdminBundle::class => ['all' => true], ]; ``` -------------------------------- ### PHP Deprecation: Class, Property, and Method Source: https://github.com/sonata-project/sonatadoctrineormadminbundle/blob/4.x/CONTRIBUTING.md Demonstrates how to deprecate a class, property, and method in PHP using the `@deprecated` tag and `trigger_error` for methods. Includes 'NEXT_MAJOR' tags for future removal planning. ```php /** * NEXT_MAJOR: Remove this class. * * @deprecated since sonata-project/foo-lib 42.x, to be removed in 43.0. Use Shiny\New\ClassOfTheMonth instead. */ final class IAmOldAndUseless { } final class StillUsedClass { /** * NEXT_MAJOR: Remove this property. * * @deprecated since sonata-project/foo-lib 42.x, to be removed in 43.0. */ public $butNotThisProperty; /** * NEXT_MAJOR: Remove this method. * * @deprecated since sonata-project/foo-lib 42.x, to be removed in 43.0. */ public function iAmBatman() { @trigger_error(sprintf( 'Method %s() is deprecated since sonata-project/foo-lib 42.x and will be removed in version 43.0.', __METHOD__ ), \E_USER_DEPRECATED); echo "But this is not Gotham here."; } } ``` -------------------------------- ### Entity ID as Object (UUID Example) Source: https://github.com/sonata-project/sonatadoctrineormadminbundle/blob/4.x/docs/tutorial/creating_your_first_admin_class/defining_entities.rst Demonstrates how to define an entity ID as an object, specifically using Ramsey's UuidInterface with a custom ID generator. ```php use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; use Ramsey\Uuid\Doctrine\UuidOrderedTimeGenerator; use Ramsey\Uuid\UuidInterface; class Comment { #[ORM\Id] #[ORM\Column(type: Types::INTEGER)] #[ORM\GeneratedValue(strategy: 'CUSTOM')] #[ORM\CustomIdGenerator(class: UuidOrderedTimeGenerator::class)] private ?UuidInterface $id = null; // ... } ``` -------------------------------- ### Install Doctrine JSON Functions Source: https://github.com/sonata-project/sonatadoctrineormadminbundle/blob/4.x/docs/reference/filter_field_definition.rst Installs the 'scienta/doctrine-json-functions' package via Composer, which provides necessary functions for querying JSON data in Doctrine. ```Bash composer require "scienta/doctrine-json-functions" ``` -------------------------------- ### PHPUnit Deprecation: Legacy Test Group Source: https://github.com/sonata-project/sonatadoctrineormadminbundle/blob/4.x/CONTRIBUTING.md Demonstrates marking PHPUnit tests that relate to deprecated functionality with the `@group legacy` annotation and a 'NEXT_MAJOR' comment for future reference. ```php /** * @group legacy * NEXT_MAJOR: Remove this test and update the related code. */ public function testSomethingDeprecated() { // ... test code ... } ``` -------------------------------- ### PHPUnit Test Method Naming Convention Source: https://github.com/sonata-project/sonatadoctrineormadminbundle/blob/4.x/CONTRIBUTING.md Demonstrates the required naming convention for test methods in PHPUnit. Test methods must be prefixed with 'test' and use camel case for their names. ```php public function testItReturnsNull() ``` -------------------------------- ### PHP Deprecation: Conditional Trigger Source: https://github.com/sonata-project/sonatadoctrineormadminbundle/blob/4.x/CONTRIBUTING.md Illustrates how to trigger a deprecation notice conditionally within PHP code when a legacy way of doing things is detected. Includes a 'NEXT_MAJOR' tag for future removal. ```php with('General') ->add('enabled', null, ['required' => false]) ->add('author', ModelType::class, [], ['edit' => 'list']) ->add('title') ->add('abstract') ->add('content') ->end() ->with('Tags') ->add('tags', ModelType::class, ['expanded' => true]) ->end() ->with('Options', ['collapsed' => true]) ->add('commentsCloseAt') ->add('commentsEnabled', null, ['required' => false]) ->add('commentsDefaultStatus', ChoiceType::class, [ 'choices' => Comment::getStatusList() ]) ->end() ; } } ``` -------------------------------- ### PHP - ImmutableArrayType Example Source: https://github.com/sonata-project/sonatadoctrineormadminbundle/blob/4.x/docs/reference/form_types_and_transformers.rst Demonstrates how to use the ImmutableArrayType to edit a fixed array of settings within a Sonata Admin form. It shows the configuration of keys for content, public status, and type selection. ```php namespace Sonata\PageBundle\Admin; use Sonata\AdminBundle\Admin\AbstractAdmin; use Sonata\AdminBundle\Form\FormMapper; use Sonata\Form\Type\ImmutableArrayType; final class PageAdmin extends AbstractAdmin { protected function configureFormFields(FormMapper $form): void { $form ->add('enabled') ->add('settings', ImmutableArrayType::class, [ 'keys' => [ ['content', 'textarea', []], ['public', 'checkbox', []], ['type', 'choice', ['choices' => [1 => 'type 1', 2 => 'type 2']]] ]); } } ``` -------------------------------- ### PHP: Deprecating Code with NEXT_MAJOR Marker Source: https://github.com/sonata-project/sonatadoctrineormadminbundle/blob/4.x/CONTRIBUTING.md This PHP code snippet demonstrates how to use the `NEXT_MAJOR` marker comment to indicate code that should be removed or uncommented in a future major release. It's used within an interface definition to mark a method that will be added in a non-backward-compatible way. ```php add('title') ->add('enabled') ->add('tags', null, [ 'field_options' => ['expanded' => true, 'multiple' => true], ]); } } ``` -------------------------------- ### Use ModelType and ModelListType for Many-to-One Relations Source: https://github.com/sonata-project/sonatadoctrineormadminbundle/blob/4.x/docs/reference/form_field_definition.rst This PHP example demonstrates the usage of both SonataAdminBundleModelType and ModelListType for managing 'Many-to-One' relationships. It configures the 'author' field with options for button labels, translation domains, and placeholders, showcasing different ways to interact with related entities. ```php namespace Sonata\NewsBundle\Admin; use Sonata\AdminBundle\Admin\AbstractAdmin; use Sonata\AdminBundle\Form\FormMapper; use Sonata\AdminBundle\Form\Type\ModelListType; use Sonata\AdminBundle\Form\Type\ModelType; final class PostAdmin extends AbstractAdmin { protected function configureFormFields(FormMapper $form): void { $form ->with('General') ->add('enabled', null, ['required' => false]) ->add('author', ModelListType::class, [ 'btn_add' => 'Add author', 'btn_list' => 'button.list', 'btn_delete' => false, 'btn_edit' => 'Edit', 'btn_catalogue' => 'SonataNewsBundle', ], [ 'placeholder' => 'No author selected', ]); } } ``` -------------------------------- ### Implement Custom Callback Filter Source: https://github.com/sonata-project/sonatadoctrineormadminbundle/blob/4.x/docs/reference/filter_field_definition.rst Provides an example of creating a custom filter using a callback function. This allows for complex filtering logic, such as joining tables and applying conditional WHERE clauses based on filter input. ```PHP namespace Sonata\NewsBundle\Admin; use Application\Sonata\NewsBundle\Entity\Comment; use Sonata\AdminBundle\Admin\AbstractAdmin; use Sonata\AdminBundle\Datagrid\DatagridMapper; use Sonata\AdminBundle\Filter\Model\FilterData; use Sonata\DoctrineORMAdminBundle\Datagrid\ProxyQueryInterface; use Sonata\DoctrineORMAdminBundle\Filter\CallbackFilter; use Symfony\Component\Form\Extension\Core\Type\CheckboxType; final class PostAdmin extends AbstractAdmin { protected function configureDatagridFilters(DatagridMapper $filter): void { $filter ->add('title') ->add('enabled') ->add('tags', null, [ 'field_options' => ['expanded' => true, 'multiple' => true], ]) ->add('author') ->add('with_open_comments', CallbackFilter::class, [ // This option accepts any callable syntax. // 'callback' => [$this, 'getWithOpenCommentFilter'], 'callback' => static function(ProxyQueryInterface $query, string $alias, string $field, FilterData $data): bool { if (!$data->hasValue()) { return false; } $query ->leftJoin(sprintf('%s.comments', $alias), 'c') ->andWhere('c.status = :status') ->setParameter('status', Comment::STATUS_MODERATE); return true; }, 'field_type' => CheckboxType::class, ]); } } ``` -------------------------------- ### Register TagAdmin Service (YAML) Source: https://github.com/sonata-project/sonatadoctrineormadminbundle/blob/4.x/docs/tutorial/creating_your_first_admin_class/defining_admin_class.rst This YAML configuration registers the TagAdmin class as a service in the DIC. It specifies the class, arguments, and tags it with 'sonata.admin' for ORM group 'tutorial_blog' with label 'Tag'. ```yaml # config/services.yaml services: tutorial.blog.admin.tag: class: Tutorial\BlogBundle\Admin\TagAdmin arguments: [~, Tutorial\BlogBundle\Entity\Tag, TutorialBlogBundle:TagAdmin] tags: - { name: sonata.admin, manager_type: orm, group: tutorial_blog, label: 'Tag' } ``` -------------------------------- ### SonataDoctrineORMAdminBundle Configuration Options Source: https://github.com/sonata-project/sonatadoctrineormadminbundle/blob/4.x/docs/reference/configuration.rst This snippet shows the full configuration structure for the SonataDoctrineORMAdminBundle. It includes settings for the entity manager, audit features, and detailed template mappings for various data types in both list and show views. ```yaml sonata_doctrine_orm_admin: # default value is null, so doctrine uses the value defined in the configuration entity_manager: ~ audit: force: true templates: types: list: array: "@SonataAdmin/CRUD/list_array.html.twig" boolean: "@SonataAdmin/CRUD/list_boolean.html.twig" date: "@SonataAdmin/CRUD/list_date.html.twig" time: "@SonataAdmin/CRUD/list_time.html.twig" datetime: "@SonataAdmin/CRUD/list_datetime.html.twig" text: "@SonataAdmin/CRUD/base_list_field.html.twig" trans: "@SonataAdmin/CRUD/list_trans.html.twig" string: "@SonataAdmin/CRUD/base_list_field.html.twig" smallint: "@SonataAdmin/CRUD/base_list_field.html.twig" bigint: "@SonataAdmin/CRUD/base_list_field.html.twig" integer: "@SonataAdmin/CRUD/base_list_field.html.twig" decimal: "@SonataAdmin/CRUD/base_list_field.html.twig" identifier: "@SonataAdmin/CRUD/base_list_field.html.twig" currency: "@SonataAdmin/CRUD/list_currency.html.twig" percent: "@SonataAdmin/CRUD/list_percent.html.twig" choice: "@SonataAdmin/CRUD/list_choice.html.twig" url: "@SonataAdmin/CRUD/list_url.html.twig" show: array: "@SonataAdmin/CRUD/show_array.html.twig" boolean: "@SonataAdmin/CRUD/show_boolean.html.twig" date: "@SonataAdmin/CRUD/show_date.html.twig" time: "@SonataAdmin/CRUD/show_time.html.twig" datetime: "@SonataAdmin/CRUD/show_datetime.html.twig" text: "@SonataAdmin/CRUD/base_show_field.html.twig" trans: "@SonataAdmin/CRUD/show_trans.html.twig" string: "@SonataAdmin/CRUD/base_show_field.html.twig" smallint: "@SonataAdmin/CRUD/base_show_field.html.twig" bigint: "@SonataAdmin/CRUD/base_show_field.html.twig" integer: "@SonataAdmin/CRUD/base_show_field.html.twig" decimal: "@SonataAdmin/CRUD/base_show_field.html.twig" currency: "@SonataAdmin/CRUD/base_currency.html.twig" percent: "@SonataAdmin/CRUD/base_percent.html.twig" choice: "@SonataAdmin/CRUD/show_choice.html.twig" url: "@SonataAdmin/CRUD/show_url.html.twig" ``` -------------------------------- ### Register CommentAdmin Service (YAML) Source: https://github.com/sonata-project/sonatadoctrineormadminbundle/blob/4.x/docs/tutorial/creating_your_first_admin_class/defining_admin_class.rst This YAML configuration registers the CommentAdmin class as a service in the DIC. It specifies the class, arguments, and tags it with 'sonata.admin' for ORM group 'tutorial_blog' with label 'Comment'. ```yaml # config/services.yaml services: tutorial.blog.admin.comment: class: Tutorial\BlogBundle\Admin\CommentAdmin arguments: [, Tutorial\BlogBundle\Entity\Comment, TutorialBlogBundle:CommentAdmin] tags: - { name: sonata.admin, manager_type: orm, group: tutorial_blog, label: 'Comment' } ``` -------------------------------- ### Generate Doctrine Entities Source: https://github.com/sonata-project/sonatadoctrineormadminbundle/blob/4.x/docs/tutorial/creating_your_first_admin_class/defining_entities.rst Generates getters and setters for Doctrine entities using the Symfony console command. ```bash bin/console doctrine:generate:entities Tutorial ``` -------------------------------- ### Register PostAdmin in DIC Source: https://github.com/sonata-project/sonatadoctrineormadminbundle/blob/4.x/docs/tutorial/creating_your_first_admin_class/defining_admin_class.rst This YAML configuration registers the `PostAdmin` class with the SonataAdminBundle's dependency injection container. It specifies the class, entity, template, and tags for integration into the Sonata dashboard. ```yaml services: tutorial.blog.admin.post: class: Tutorial\BlogBundle\Admin\PostAdmin arguments: [~, Tutorial\BlogBundle\Entity\Post, TutorialBlogBundle:PostAdmin] tags: - { name: sonata.admin, manager_type: orm, group: tutorial_blog, label: 'Post' } ``` -------------------------------- ### PHP: Using ProxyQuery for Doctrine ORM Queries Source: https://github.com/sonata-project/sonatadoctrineormadminbundle/blob/4.x/docs/reference/query_proxy.rst Demonstrates how to instantiate and use the ProxyQuery object to build and execute enhanced Doctrine ORM queries. It shows adding left joins, setting sort order, and limiting results, simulating Doctrine 1 behavior. ```PHP use Sonata\AdminBundle\Datagrid\ORM\ProxyQuery; $queryBuilder = $this->em->createQueryBuilder(); $queryBuilder->from('Post', 'p'); $proxyQuery = new ProxyQuery($queryBuilder); $proxyQuery->leftJoin('p.tags', 't'); $proxyQuery->setSortBy('name'); $proxyQuery->setMaxResults(10); $results = $proxyQuery->execute(); ``` -------------------------------- ### Define PostAdmin Class Source: https://github.com/sonata-project/sonatadoctrineormadminbundle/blob/4.x/docs/tutorial/creating_your_first_admin_class/defining_admin_class.rst This PHP code defines the `PostAdmin` class, extending `AbstractAdmin` from SonataAdminBundle. It configures how the Post entity is displayed, edited, and listed, including relationships with tags and comments. ```php namespace Tutorial\BlogBundle\Admin; use Sonata\AdminBundle\Admin\AbstractAdmin; use Sonata\AdminBundle\Form\FormMapper; use Sonata\AdminBundle\Datagrid\DatagridMapper; use Sonata\AdminBundle\Datagrid\ListMapper; use Sonata\AdminBundle\Form\Type\ModelType; use Sonata\AdminBundle\Show\ShowMapper; use Knp\Menu\ItemInterface as MenuItemInterface; use Tutorial\BlogBundle\Entity\Comment; final class PostAdmin extends AbstractAdmin { protected function configureShowFields(ShowMapper $showMapper) { $showMapper ->add('enabled') ->add('title') ->add('author.name') ->add('abstract') ->add('content') ->add('tags'); } protected function configureFormFields(FormMapper $formMapper) { $formMapper ->with('General') ->add('enabled', null, ['required' => false]) ->add('title') ->add('abstract') ->add('content') ->end() ->with('Tags') ->add('tags', ModelType::class, ['expanded' => true, 'multiple' => true]) ->end() ->with('Comments') ->add('comments', ModelType::class, ['multiple' => true]) ->end() ->with('System Information', ['collapsed' => true]) ->add('created_at') ->end(); } protected function configureListFields(ListMapper $listMapper) { $listMapper ->addIdentifier('title') ->add('author.name') ->add('enabled') ->add('abstract') ->add('content') ->add('tags') ->add('_action', 'actions', [ 'actions' => [ 'show' => [], 'edit' => [], 'delete' => [], ] ]); } protected function configureDatagridFilters(DatagridMapper $datagridMapper) { $datagridMapper ->add('title') ->add('enabled') ->add('tags', null, ['field_options' => ['expanded' => true, 'multiple' => true]]); } } ``` -------------------------------- ### Customize Global SonataAdminBundle Layout Source: https://github.com/sonata-project/sonatadoctrineormadminbundle/blob/4.x/docs/reference/templates.rst This snippet shows how to configure global layout and action templates for the SonataAdminBundle via the `sonata_admin.yaml` configuration file. It allows overriding default templates for layout, AJAX requests, and various CRUD actions like list, show, and edit. ```yaml # config/packages/sonata_admin.yaml sonata_admin: templates: # default global templates layout: '@SonataAdmin/standard_layout.html.twig' ajax: '@SonataAdmin/ajax_layout.html.twig' # default value if done set, actions templates, should extend global templates list: '@SonataAdmin/CRUD/list.html.twig' show: '@SonataAdmin/CRUD/show.html.twig' edit: '@SonataAdmin/CRUD/edit.html.twig' ``` -------------------------------- ### Tweak TagAdmin Class Source: https://github.com/sonata-project/sonatadoctrineormadminbundle/blob/4.x/docs/tutorial/creating_your_first_admin_class/defining_admin_class.rst This PHP code defines the `TagAdmin` class, extending `AbstractAdmin`. It configures the form fields, datagrid filters, and list fields for the Tag entity, including validation for the 'name' field. ```php namespace Tutorial\BlogBundle\Admin; use Sonata\AdminBundle\Admin\AbstractAdmin; use Sonata\AdminBundle\Datagrid\ListMapper; use Sonata\AdminBundle\Datagrid\DatagridMapper; use Sonata\AdminBundle\Form\FormMapper; use Sonata\Form\Validator\ErrorElement; use Tutorial\BlogBundle\Entity\Tag; final class TagAdmin extends AbstractAdmin { protected function configureFormFields(FormMapper $formMapper) { $formMapper ->add('name') ->add('enabled', null, ['required' => false]); } protected function configureDatagridFilters(DatagridMapper $datagridMapper) { $datagridMapper ->add('name') ->add('posts'); } protected function configureListFields(ListMapper $listMapper) { $listMapper ->addIdentifier('name') ->add('enabled'); } public function validate(ErrorElement $errorElement, $object) { $errorElement ->with('name') ->assertMaxLength(['limit' => 32]) ``` -------------------------------- ### Update Database Schema Source: https://github.com/sonata-project/sonatadoctrineormadminbundle/blob/4.x/docs/tutorial/creating_your_first_admin_class/defining_entities.rst Updates the database schema to reflect entity and mapping changes using the Symfony console command. ```bash bin/console doctrine:schema:update --force ``` -------------------------------- ### Create PostAdminController Source: https://github.com/sonata-project/sonatadoctrineormadminbundle/blob/4.x/docs/tutorial/creating_your_first_admin_class/defining_crud_controller.rst Defines a custom controller for the Post admin interface by extending Sonata's CRUDController. This allows for custom actions or overriding default CRUD operations. ```php namespace Tutorial\BlogBundle\Controller; use Sonata\AdminBundle\Controller\CRUDController; final class PostAdminController extends CRUDController { } ``` -------------------------------- ### Create CommentAdminController Source: https://github.com/sonata-project/sonatadoctrineormadminbundle/blob/4.x/docs/tutorial/creating_your_first_admin_class/defining_crud_controller.rst Defines a custom controller for the Comment admin interface by extending Sonata's CRUDController. This allows for custom actions or overriding default CRUD operations. ```php namespace Tutorial\BlogBundle\Controller; use Sonata\AdminBundle\Controller\CRUDController; final class CommentAdminController extends CRUDController { } ``` -------------------------------- ### Create TagAdminController Source: https://github.com/sonata-project/sonatadoctrineormadminbundle/blob/4.x/docs/tutorial/creating_your_first_admin_class/defining_crud_controller.rst Defines a custom controller for the Tag admin interface by extending Sonata's CRUDController. This allows for custom actions or overriding default CRUD operations. ```php namespace Tutorial\BlogBundle\Controller; use Sonata\AdminBundle\Controller\CRUDController; final class TagAdminController extends CRUDController { } ``` -------------------------------- ### Customize CommentAdmin Class (PHP) Source: https://github.com/sonata-project/sonatadoctrineormadminbundle/blob/4.x/docs/tutorial/creating_your_first_admin_class/defining_admin_class.rst This PHP code defines the CommentAdmin class, extending Sonata's AbstractAdmin. It configures form fields, datagrid filters, list fields, and custom batch actions ('enabled', 'disabled') for managing Comment entities. ```php // src/Tutorial/BlogBundle/Admin/CommentAdmin.php namespace Tutorial\BlogBundle\Admin; use Sonata\AdminBundle\Admin\AbstractAdmin; use Sonata\AdminBundle\Form\FormMapper; use Sonata\AdminBundle\Form\Type\ModelType; use Sonata\AdminBundle\Datagrid\DatagridMapper; use Sonata\AdminBundle\Datagrid\ListMapper; use Application\Sonata\NewsBundle\Entity\Comment; final class CommentAdmin extends AbstractAdmin { protected $parentAssociationMapping = 'post'; protected function configureFormFields(FormMapper $formMapper) { if (!$this->isChild()) { $formMapper->add('post', ModelType::class, [], ['edit' => 'list']); } $formMapper ->add('name') ->add('email') ->add('url', null, ['required' => false]) ->add('message'); } protected function configureDatagridFilters(DatagridMapper $datagridMapper) { $datagridMapper ->add('name') ->add('email') ->add('message'); } protected function configureListFields(ListMapper $listMapper) { $listMapper ->addIdentifier('name') ->add('post') ->add('email') ->add('url') ->add('message'); } public function getBatchActions() { $actions = parent::getBatchActions(); $actions['enabled'] = [ 'label' => $this->trans('batch_enable_comments'), 'ask_confirmation' => true, ]; $actions['disabled'] = [ 'label' => $this->trans('batch_disable_comments'), 'ask_confirmation' => false ]; return $actions; } } ``` -------------------------------- ### Configure Entity Audit in services.xml Source: https://github.com/sonata-project/sonatadoctrineormadminbundle/blob/4.x/docs/reference/audit.rst Configures entity auditing by setting the 'audit' attribute to 'false' for a specific service in the services.xml file. ```xml Tutorial\BlogBundle\Entity\Post TutorialBlogBundle:PostAdmin ``` -------------------------------- ### Decorate DataSource for Custom Export Formatting (PHP) Source: https://github.com/sonata-project/sonatadoctrineormadminbundle/blob/4.x/docs/reference/data_source.rst This PHP code demonstrates how to decorate the default SonataDoctrineORMAdminBundleExporterDataSource. It allows customization of date/time formats and the handling of backed enumerations during data export by calling convenience methods on the data source iterator. ```php namespace App\Service\Admin; use Sonata\AdminBundle\Datagrid\ProxyQueryInterface; use Sonata\AdminBundle\Exporter\DataSourceInterface; use Sonata\DoctrineORMAdminBundle\Exporter\DataSource; use Sonata\Exporter\Source\DoctrineORMQuerySourceIterator; class DecoratingDataSource implements DataSourceInterface { private DataSource $dataSource; public function __construct(DataSource $dataSource) { $this->dataSource = $dataSource; } public function createIterator(ProxyQueryInterface $query, array $fields): \Iterator { /** @var DoctrineORMQuerySourceIterator $iterator */ $iterator = $this->dataSource->createIterator($query, $fields); $iterator->setDateTimeFormat('Y-m-d H:i:s'); $iterator->useBackedEnumValue(false); return $iterator; } } ``` -------------------------------- ### Define Comment Entity Source: https://github.com/sonata-project/sonatadoctrineormadminbundle/blob/4.x/docs/tutorial/creating_your_first_admin_class/defining_entities.rst Defines the Comment entity with Doctrine ORM mappings for ID, string, text, and a many-to-one relationship with Post entities. Includes Symfony validation constraints. ```php namespace Tutorial\BlogBundle\Entity; use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Constraints as Assert; #[ORM\Entity] class Comment { #[ORM\Id] #[ORM\Column(type: Types::INTEGER)] #[ORM\GeneratedValue] private ?int = null; #[ORM\Column(type: Types::STRING)] #[Assert\NotBlank] private ?string $name = null; #[ORM\Column(type: Types::STRING)] #[Assert\NotBlank] private ?string $email = null; #[ORM\Column(type: Types::STRING)] private ?string $url = null; #[ORM\Column(type: Types::TEXT)] #[Assert\NotBlank] private ?string $message = null; #[ORM\ManyToOne(targetEntity: Post::class)] private ?Post $post = null; public function __toString(): string { return $this->getName() ?? '-'; } } ``` -------------------------------- ### Define Tag Entity Source: https://github.com/sonata-project/sonatadoctrineormadminbundle/blob/4.x/docs/tutorial/creating_your_first_admin_class/defining_entities.rst Defines the Tag entity with Doctrine ORM mappings for ID, string, boolean, and many-to-many relationships with Post entities. Includes Symfony validation constraints. ```php namespace Tutorial\BlogBundle\Entity; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Constraints as Assert; #[ORM\Entity] class Tag { #[ORM\Id] #[ORM\Column(type: Types::INTEGER)] #[ORM\GeneratedValue] private ?int $id = null; #[ORM\Column(type: Types::STRING)] #[Assert\NotBlank] private ?string $name = null; #[ORM\Column(type: Types::BOOLEAN)] private bool $enabled = false; #[ORM\ManyToMany(targetEntity: Post::class)] private Collection $posts; public function __construct() { $this->posts = new ArrayCollection(); } public function __toString(): string { return $this->getName() ?? '-'; } } ``` -------------------------------- ### Configure File Upload Field in MediaAdmin Source: https://github.com/sonata-project/sonatadoctrineormadminbundle/blob/4.x/docs/reference/form_field_definition.rst This PHP code shows how to add a file upload field ('binaryContent') to the MediaAdmin form using SonataAdminBundle. It sets 'required' to false for several fields and specifies the field type as 'file' for binaryContent, indicating that an UploadedFile instance will be provided. ```php namespace Sonata\MediaBundle\Admin; use Sonata\AdminBundle\Admin\AbstractAdmin; use Sonata\AdminBundle\Form\FormMapper; final class MediaAdmin extends AbstractAdmin { protected function configureFormFields(FormMapper $form): void { $form ->add('name', null, ['required' => false]) ->add('enabled', null, ['required' => false]) ->add('authorName', null, ['required' => false]) ->add('cdnIsFlushable', null, ['required' => false]) ->add('description', null, ['required' => false]) ->add('copyright', null, ['required' => false]) ->add('binaryContent', 'file', ['required' => false]); } } ``` -------------------------------- ### Configure Order-By for Ordered Fields (XML) Source: https://github.com/sonata-project/sonatadoctrineormadminbundle/blob/4.x/docs/reference/troubleshootings.rst This XML configuration snippet shows how to set the 'order-by' option for one-to-many associations in Doctrine ORM. This is crucial for ensuring that elements within the association are displayed in the correct order, based on a specified field. ```xml ``` -------------------------------- ### Enable Custom Filter (YAML) Source: https://github.com/sonata-project/sonatadoctrineormadminbundle/blob/4.x/docs/reference/filter_field_definition.rst This snippet shows how to enable a custom filter, App\Filter\JsonListFilter, by tagging it for Sonata Admin. ```yaml App\Filter\JsonListFilter: tags: - { name: sonata.admin.filter.type } ``` -------------------------------- ### ModelAutocompleteFilter Usage (PHP) Source: https://github.com/sonata-project/sonatadoctrineormadminbundle/blob/4.x/docs/reference/filter_field_definition.rst Demonstrates using ModelAutocompleteFilter for fields with many related items, requiring the 'property' option for autocompletion. ```php protected function configureDatagridFilters(DatagridMapper $filter): void { $filter ->add('category', ModelAutocompleteFilter::class, [ // in related CategoryAdmin there must be datagrid filter on `title` field to make the autocompletion work 'field_options' => ['property'=>'title'], ]); } ``` -------------------------------- ### Define Post Entity Source: https://github.com/sonata-project/sonatadoctrineormadminbundle/blob/4.x/docs/tutorial/creating_your_first_admin_class/defining_entities.rst Defines the Post entity with various Doctrine ORM mappings, including ID, string, text, boolean, datetime, one-to-many, many-to-many, and embedded relationships. It also includes Symfony validation constraints. ```php namespace Tutorial\BlogBundle\Entity; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Constraints as Assert; #[ORM\Entity] class Post { #[ORM\Id] #[ORM\Column(type: Types::INTEGER)] #[ORM\GeneratedValue] private ?int $id = null; #[ORM\Column(type: Types::STRING)] #[Assert\NotBlank] #[Assert\Length(min: 10, max: 255)] private ?string $title = null; #[ORM\Column(type: Types::TEXT)] private ?string $abstract = null; #[ORM\Column(type: Types::TEXT)] #[Assert\NotBlank] private ?string $content = null; #[ORM\Column(type: Types::BOOLEAN)] private bool $enabled = false; #[ORM\Column(type: Types::DATETIME_MUTABLE)] private ?\DateTimeInterface $created_at = null; #[ORM\Column(type: Types::DATETIME_IMMUTABLE)] private ?\DateTimeInterface $updated_at = null; #[ORM\OneToMany(targetEntity: Comment::class, mappedBy: 'post')] private Collection $comments; #[ORM\ManyToMany(targetEntity: Tag::class)] private Collection $tags; #[ORM\Embedded(class: Author::class)] private Author $author; public function __construct() { $this->tags = new ArrayCollection(); $this->comments = new ArrayCollection(); $this->created_at = new \DateTime("now"); $this->author = new Author('admin'); } public function __toString(): string { return $this->getTitle() ?? '-'; } public function getAuthor(): Author { return $this->author; } } ``` -------------------------------- ### Define Author Entity Source: https://github.com/sonata-project/sonatadoctrineormadminbundle/blob/4.x/docs/tutorial/creating_your_first_admin_class/defining_entities.rst Defines the Author entity using Doctrine ORM annotations. This entity is embeddable and contains a 'name' property. ```php namespace Tutorial\BlogBundle\Entity; use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; #[ORM\Embeddable] class Author { public function __construct( #[ORM\Column(type: Types::STRING)] private string $name ) { } public function getName(): string { return $this->name; } } ``` -------------------------------- ### DateRangeFilter Usage (PHP) Source: https://github.com/sonata-project/sonatadoctrineormadminbundle/blob/4.x/docs/reference/filter_field_definition.rst Shows how to use DateRangeFilter to filter records within a specified date range or from/until a given date. ```php protected function configureDatagridFilters(DatagridMapper $filter): void { $filter->add('created', DateRangeFilter::class); } ``` -------------------------------- ### Configure Orphan Removal for One-to-Many Associations (XML) Source: https://github.com/sonata-project/sonatadoctrineormadminbundle/blob/4.x/docs/reference/troubleshootings.rst This XML configuration snippet demonstrates how to correctly set the 'orphan-removal' option to 'true' for one-to-many associations in Doctrine ORM. This ensures that deleted elements from the association are properly removed. ```xml true ```