Я только что нашел решение специально для случая в sonata admin, расширив код php, чтобы сделать его «автоформатируемым».Вот что я сделал:
ObjectTypeCaster.php
(из https://stackoverflow.com/a/53081037/301277):
class ObjectTypeCaster
{
/**
* This method is able to recast an object by copying all properties
*/
public static function castAs($sourceObject, $newClass)
{
$castedObject = new $newClass();
$reflectedSourceObject = new \ReflectionClass($sourceObject);
$reflectedSourceObjectProperties = $reflectedSourceObject->getProperties();
foreach ($reflectedSourceObjectProperties as $reflectedSourceObjectProperty) {
$propertyName = $reflectedSourceObjectProperty->getName();
$reflectedSourceObjectProperty->setAccessible(true);
$castedObject->$propertyName = $reflectedSourceObjectProperty->getValue($sourceObject);
}
return $castedObject;
}
}
Расширение FormMapper
и ShowMapper
следующим образом:
IndentedFormMapper.php
:
<?php
namespace App\Admin\Form;
use App\Helper\ObjectTypeCaster;
use Sonata\AdminBundle\Admin\AdminInterface;
use Sonata\AdminBundle\Builder\BuilderInterface;
use Sonata\AdminBundle\Builder\FormContractorInterface;
use Sonata\AdminBundle\Form\FormMapper;
use Symfony\Component\Form\FormBuilderInterface;
class IndentedFormMapper extends FormMapper
{
/**
* Makes protected property from BaseMapper public
*
* @var AdminInterface
*/
public $admin;
/**
* Makes protected property from BaseMapper public
*
* @var BuilderInterface
*/
public $builder;
/**
* Makes protected property from FormMapper public
*
* @var FormBuilderInterface
*/
public $formBuilder;
/**
* Makes protected property from BaseGroupedMapper public
*
* @var string|null
*/
public $currentGroup;
/**
* Makes protected property from BaseGroupedMapper public
*
* @var string|null
*/
public $currentTab;
/**
* Makes protected property from BaseGroupedMapper public
*
* @var bool|null
*/
public $apply;
/**
* We overwrite the constructor from FormMapper and BaseMapper to be able to create
* this object without any parameter. Its properties are copied by ObjectTypeCaster.
*
* IndentedFormMapper constructor.
*
* @see ObjectTypeCaster
*/
public function __construct()
{
}
/**
* This makes it possible to chain this object in a way that allows
* autoformatting in IntelliJ IDEs. Usage:
*
* $formMapper
* ->tab('General')
* ->chain(function ($formMapper) {
* $formMapper
* ->add('...')
* // Default usage here, you can also chain again
* ;
* })
* ->end()
* ;
*
* @param $callback
* @return $this
*/
public function chain($callback)
{
$callback($this);
return $this;
}
}
IndentedShowMapper.php
:
<?php
namespace App\Admin\Form;
use App\Helper\ObjectTypeCaster;
use Sonata\AdminBundle\Admin\AdminInterface;
use Sonata\AdminBundle\Builder\BuilderInterface;
use Sonata\AdminBundle\Builder\FormContractorInterface;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Show\ShowMapper;
use Symfony\Component\Form\FormBuilderInterface;
class IndentedShowMapper extends ShowMapper
{
/**
* Makes protected property from ShowMapper public
*
* @var AdminInterface
*/
public $list;
/**
* Makes protected property from BaseGroupedMapper public
*
* @var string|null
*/
public $currentGroup;
/**
* Makes protected property from BaseGroupedMapper public
*
* @var string|null
*/
public $currentTab;
/**
* Makes protected property from BaseGroupedMapper public
*
* @var bool|null
*/
public $apply;
/**
* Makes protected property from BaseMapper public
*
* @var AdminInterface
*/
public $admin;
/**
* Makes protected property from BaseMapper public
*
* @var BuilderInterface
*/
public $builder;
/**
* We overwrite the constructor from ShowMapper and BaseMapper to be able to create
* this object without any parameter. Its properties are copied by ObjectTypeCaster.
*
* IndentedFormMapper constructor.
*
* @see ObjectTypeCaster
*/
public function __construct()
{
}
/**
* This makes it possible to chain this object in a way that allows
* autoformatting in IntelliJ IDEs. Usage:
*
* $showMapper
* ->tab('General')
* ->chain(function ($showMapper) {
* $showMapper
* ->add('...')
* // Default usage here, you can also chain again
* ;
* })
* ->end()
* ;
*
* @param $callback
* @return $this
*/
public function chain($callback)
{
$callback($this);
return $this;
}
}
Добавьте класс BaseAdmin
от того, который вы унаследовали во всех ваших административных классах, и добавьте следующие методы:
<?php
use App\Admin\Form\IndentedFormMapper;
use App\Admin\Form\IndentedShowMapper;
use App\Entity\User;
use App\Helper\ObjectTypeCaster;
use Sonata\AdminBundle\Admin\AbstractAdmin;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Mapper\BaseMapper;
use Sonata\AdminBundle\Show\ShowMapper;
class BaseAdmin extends AbstractAdmin
{
/**
* @param FormMapper $formMapper
* @throws \ReflectionException
*/
protected function configureFormFields(FormMapper $formMapper)
{
$indentFormMapper = ObjectTypeCaster::castAs($formMapper, IndentedFormMapper::class);
$this->configureFormFieldsIndention($indentFormMapper);
}
/**
* @param IndentedFormMapper $formMapper
*/
protected function configureFormFieldsIndention(IndentedFormMapper $formMapper)
{
}
/**
* @param ShowMapper $showMapper
* @throws \ReflectionException
*/
protected function configureShowFields(ShowMapper $showMapper)
{
$indentShowMapper = ObjectTypeCaster::castAs($showMapper, IndentedShowMapper::class);
$this->configureShowFieldsIndention($indentShowMapper);
}
/**
* @param IndentedShowMapper $showMapper
*/
protected function configureShowFieldsIndention(IndentedShowMapper $showMapper)
{
}
}
Используйте его в своих BaseAdmin
дочерних классах, например:
ExampleAdmin.php
:
<?php
namespace App\Admin;
use App\Admin\Form\IndentedFormMapper;
use App\Admin\Form\IndentedShowMapper;
use App\Entity\Example;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Show\ShowMapper;
class ExampleAdmin extends BaseAdmin
{
// ...
/**
* @param IndentedFormMapper $formMapper
*/
protected function configureFormFieldsIndention(IndentedFormMapper $formMapper)
{
$formMapper
->tab('General')
->chain(function ($formMapper) {
$formMapper
->with(
'Example',
[
'class' => AdminLayout::HALF,
]
)
->chain(function ($formMapper) {
$formMapper
->add(
'name',
Types::TEXT
)
;
})
->end()
;
})
->end()
;
}
/**
* @param IndentedShowMapper $showMapper
*/
protected function configureShowFieldsIndention(IndentedShowMapper $showMapper)
{
$mapData = $this->getMapData();
$showMapper
->with('Internal')
->chain(function ($showMapper) {
$showMapper
->add('id')
->add('createdAt')
->add('updatedAt')
;
})
->end()
;
}
}