Родительский класс сущности в бандле

В случае, если наш бандл имеет некоторые сущности, которые могут быть переопределены в проекте, в который бандл будет установлен, может возникнуть вопрос наследования от этих сущностей.

Например, мой бандл параметров товаров для интернет-магазина определяет сущности Product и Category, где определяются зависимости от сущностей бандла. И эти сущности Product и Category скорее всего должны быть дополнены специфическими полями в проекте.

Можно в такой ситуации сделать так:

namespace Onest\EshopParamsBundle\Entity;
// Родительский класс
/**
 * @ORM\MappedSuperclass
 */
class Product
{
    /**
     * @ORM\OneToMany(targetEntity="Onest\EshopParamsBundle\Entity\Parameter", mappedBy="product", cascade={"persist", "remove"})
     */
    protected $parameters;
...
// логика, которую нужно будет унаследовать
...
}
namespace App\Entity;
// Дочерний класс
/**
 * @ORM\Entity
 */
class Product   extends \Onest\EshopParamsBundle\Entity\Product
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;
...
}

Ссылка в тему:

https://www.doctrine-project.org/projects/doctrine-orm/en/2.7/reference/inheritance-mapping.html

Минимальный состав бандла

Структура бандла почти повторяет структуру обычного проекта на Symfony.

https://github.com/prawas/symfony-bundle-skeleton

Sonata Admin CollectionType сортировка

Допустим, есть entity Product, к которому привязаны ProductCharacteristic. В Sonata Admin последние вводятся / вводятся при помощи Sonata\Form\Type\CollectionType. Выглядит это примерно так:

А в коде так:

$formMapper
                ->add('characteristics'CollectionType::class, [
                    'label' => 'Характеристики',
                    'required' => false,
                    'type_options' => [
                        'delete' => true,
                    ],
                ], [
                    'edit' => 'inline',
                    'inline' => 'table',
                    'sortable' => 'position',
                ])
;

Обратите внимание на ‘sortable’ => ‘position’. Это поле, в которое записывается порядок вывода.

И «из коробки» эта конструкция ПОЧТИ работает. То есть мышью все таскается, но при сохранении возвращается на исходную позицию.

Что нужно сделать, чтобы заработало:

1. Добавить в entity ProductCharacteristic поле position, если его еще нет.

class ProductCharacteristic
{
...
    /**
     * @ORM\Column(type="integer")
     */
    private $position = 0;
...
}

2. Прописать автоматическую сортировку полю characteristics в entity Product.

class Product
{
...
    /**
     * @ORM\OneToMany(targetEntity="App\Entity\ProductCharacteristic", mappedBy="product", cascade={"persist", "remove"})
     * @ORM\OrderBy({"position" = "ASC"})
     */
    private $characteristics;
...
}

3. Вывести скрытое поле position в форму редактирования ProductCharacteristics.

final class ProductCharacteristicAdmin extends AbstractAdmin
{
    protected function configureFormFields(FormMapper $formMapper)
    {
        $formMapper
...
                ->add('position'HiddenType::class, [
                    'label' => 'Порядок',
                ])
...
    }
}

Скрыть страницу из сайдбара

Чтобы не показывать страницу в сайдбаре админки, нужно добавить в конфиг сервисов параметр show_in_dashboard: false.

# config/services.yaml
admin.phones:
    class: App\Admin\PhoneWithMobileOperatorAdmin
    arguments: [~, App\Entity\PhoneWithMobileOperator, ~]
    tags:
        - { name: sonata.admin, manager_type: orm, label: Телефоны, group: CMS, show_in_dashboard: false }

Нестандартная сортировка в медиатеке (MediaBundle)

Прописываем новый класс в параметрах:

<?php
// config/services.yaml
parameters:
    sonata.media.admin.media.classApp\Sonata\MediaBundle\Admin\MediaAdmin

Создаем этот класс, наследуясь от Sonata\MediaBundle\Admin\PHPCR\MediaAdmin:

<?php
// src/Sonata/MediaBundle/Admin/MediaAdmin.php
namespace App\Sonata\MediaBundle\Admin;
use Sonata\MediaBundle\Admin\PHPCR\MediaAdmin as BaseMediaAdmin;
class MediaAdmin extends BaseMediaAdmin
{
    protected $datagridValues = array(
        '_page' => 1,
        '_per_page' => 25,
        '_sort_order' => 'DESC',
        '_sort_by' => 'createdAt',
    );
}