sonata-project / SonataDoctrineORMAdminBundle

Integrate Doctrine ORM into the SonataAdminBundle
https://docs.sonata-project.org/projects/SonataDoctrineORMAdminBundle
MIT License
445 stars 344 forks source link

Cannot embed a self referenced CollectionType #1174

Closed alexandrubau closed 4 years ago

alexandrubau commented 4 years ago

Environment

Sonata packages

$ composer show --latest 'sonata-project/*'
sonata-project/admin-bundle              3.73.0 3.78.1 The missing Symfony Admin Generator
sonata-project/block-bundle              3.20.0 4.4.0  Symfony SonataBlockBundle
sonata-project/cache                     2.0.1  2.0.1  Cache library
sonata-project/datagrid-bundle           2.5.0  3.2.0  Symfony SonataDatagridBundle
sonata-project/doctrine-extensions       1.9.1  1.10.1 Doctrine2 behavioral extensions
sonata-project/doctrine-orm-admin-bundle 3.21.0 3.24.0 Symfony Sonata / Integrate Doctrine ORM into the SonataAdminBundle
sonata-project/exporter                  2.3.0  2.4.1  Lightweight Exporter library
sonata-project/form-extensions           1.6.0  1.6.0  Symfony form extensions
sonata-project/twig-extensions           1.4.1  1.4.1  Sonata twig extensions
sonata-project/user-bundle               4.7.0  4.9.0  Symfony SonataUserBundle

Symfony packages

$ composer show --latest 'symfony/*'
symfony/asset                      v4.4.10 v4.4.16 Symfony Asset Component
symfony/browser-kit                v4.4.10 v4.4.16 Symfony BrowserKit Component
symfony/cache                      v4.4.10 v4.4.16 Symfony Cache component with PSR-6, PSR-16, and tags
symfony/cache-contracts            v2.1.3  v2.2.0  Generic abstractions related to caching
symfony/config                     v4.4.10 v4.4.16 Symfony Config Component
symfony/console                    v4.4.10 v4.4.16 Symfony Console Component
symfony/css-selector               v4.4.15 v4.4.16 Symfony CssSelector Component
symfony/debug                      v4.4.10 v4.4.16 Symfony Debug Component
symfony/debug-bundle               v4.4.10 v4.4.16 Symfony DebugBundle
symfony/debug-pack                 v1.0.8  v1.0.9  A debug pack for Symfony projects
symfony/dependency-injection       v4.4.10 v4.4.16 Symfony DependencyInjection Component
symfony/doctrine-bridge            v4.4.10 v4.4.16 Symfony Doctrine Bridge
symfony/dom-crawler                v4.4.15 v4.4.16 Symfony DomCrawler Component
symfony/dotenv                     v4.4.10 v4.4.16 Registers environment variables from a .env file
symfony/error-handler              v4.4.10 v4.4.16 Symfony ErrorHandler Component
symfony/event-dispatcher           v4.4.10 v4.4.16 Symfony EventDispatcher Component
symfony/event-dispatcher-contracts v1.1.9  v2.2.0  Generic abstractions related to dispatching event
symfony/expression-language        v4.4.10 v4.4.16 Symfony ExpressionLanguage Component
symfony/filesystem                 v4.4.10 v4.4.16 Symfony Filesystem Component
symfony/finder                     v4.4.10 v4.4.16 Symfony Finder Component
symfony/flex                       v1.8.4  v1.9.10 Composer plugin for Symfony
symfony/form                       v4.4.10 v4.4.16 Symfony Form Component
symfony/framework-bundle           v4.4.10 v4.4.16 Symfony FrameworkBundle
symfony/http-client                v4.4.10 v4.4.16 Symfony HttpClient component
symfony/http-client-contracts      v2.1.3  v2.3.1  Generic abstractions related to HTTP clients
symfony/http-foundation            v4.4.10 v4.4.16 Symfony HttpFoundation Component
symfony/http-kernel                v4.4.15 v4.4.16 Symfony HttpKernel Component
symfony/inflector                  v4.4.10 v4.4.16 Symfony Inflector Component
symfony/intl                       v4.4.10 v4.4.16 A PHP replacement layer for the C intl extension that includes additional data from the ICU library.
symfony/mailer                     v4.4.10 v4.4.16 Symfony Mailer Component
symfony/maker-bundle               v1.19.1 v1.23.0 Symfony Maker helps you create empty commands, controllers, form classes, tests and more so you can forget about writing boilerplate code.
symfony/mime                       v4.4.10 v4.4.16 A library to manipulate MIME messages
symfony/monolog-bridge             v4.4.10 v4.4.16 Symfony Monolog Bridge
symfony/monolog-bundle             v3.5.0  v3.6.0  Symfony MonologBundle
symfony/options-resolver           v4.4.10 v4.4.16 Symfony OptionsResolver Component
symfony/orm-pack                   v1.0.7  v2.0.0  A pack for the Doctrine ORM
symfony/phpunit-bridge             v4.4.10 v5.1.8  Symfony PHPUnit Bridge
symfony/polyfill-intl-grapheme     v1.18.1 v1.20.0 Symfony polyfill for intl's grapheme_* functions
symfony/polyfill-intl-icu          v1.17.1 v1.20.0 Symfony polyfill for intl's ICU-related data and classes
symfony/polyfill-intl-idn          v1.17.1 v1.20.0 Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions
symfony/polyfill-intl-normalizer   v1.18.1 v1.20.0 Symfony polyfill for intl's Normalizer class and related functions
symfony/polyfill-mbstring          v1.18.1 v1.20.0 Symfony polyfill for the Mbstring extension
symfony/polyfill-php72             v1.17.0 v1.20.0 Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions
symfony/polyfill-php73             v1.17.1 v1.20.0 Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions
symfony/polyfill-php80             v1.17.1 v1.20.0 Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions
symfony/process                    v4.4.10 v4.4.16 Symfony Process Component
symfony/profiler-pack              v1.0.4  v1.0.5  A pack for the Symfony web profiler
symfony/property-access            v4.4.10 v4.4.16 Symfony PropertyAccess Component
symfony/property-info              v4.4.10 v4.4.16 Symfony Property Info Component
symfony/routing                    v4.4.10 v4.4.16 Symfony Routing Component
symfony/security-acl               v3.1.0  v3.1.0  Symfony Security Component - ACL (Access Control List)
symfony/security-bundle            v4.4.10 v4.4.16 Symfony SecurityBundle
symfony/security-core              v4.4.10 v4.4.16 Symfony Security Component - Core Library
symfony/security-csrf              v4.4.10 v4.4.16 Symfony Security Component - CSRF Library
symfony/security-guard             v4.4.10 v4.4.16 Symfony Security Component - Guard
symfony/security-http              v4.4.10 v4.4.16 Symfony Security Component - HTTP Integration
symfony/serializer                 v4.4.10 v4.4.16 Symfony Serializer Component
symfony/serializer-pack            v1.0.3  v1.0.4  A pack for the Symfony serializer
symfony/service-contracts          v2.1.3  v2.2.0  Generic abstractions related to writing services
symfony/stopwatch                  v4.4.10 v4.4.16 Symfony Stopwatch Component
symfony/string                     v5.1.3  v5.1.8  Symfony String component
symfony/templating                 v4.4.11 v4.4.16 Symfony Templating Component
symfony/test-pack                  v1.0.6  v1.0.7  A pack for functional and end-to-end testing within a Symfony app
symfony/translation                v4.4.10 v4.4.16 Symfony Translation Component
symfony/translation-contracts      v2.1.3  v2.3.0  Generic abstractions related to translation
symfony/twig-bridge                v4.4.10 v4.4.16 Symfony Twig Bridge
symfony/twig-bundle                v4.4.10 v4.4.16 Symfony TwigBundle
symfony/twig-pack                  v1.0.0  v1.0.2  A Twig pack for Symfony projects
symfony/validator                  v4.4.10 v4.4.16 Symfony Validator Component
symfony/var-dumper                 v4.4.10 v4.4.16 Symfony mechanism for exploring and dumping PHP variables
symfony/var-exporter               v4.4.10 v4.4.16 A blend of var_export() + serialize() to turn any serializable data structure to plain PHP code
symfony/web-link                   v4.4.10 v4.4.16 Symfony WebLink Component
symfony/web-profiler-bundle        v4.4.10 v4.4.16 Symfony WebProfilerBundle
symfony/webpack-encore-bundle      v1.7.3  v1.8.0  Integration with your Symfony app & Webpack Encore!
symfony/yaml                       v4.4.10 v4.4.16 Symfony Yaml Component

PHP version

$ php -v
PHP 7.4.8 (cli) (built: Jul  9 2020 23:47:36) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
    with Zend OPcache v7.4.8, Copyright (c), by Zend Technologies
    with Xdebug v2.9.6, Copyright (c) 2002-2020, by Derick Rethans

Subject

When using a CollectionType referencing the same Admin class, no form fields (and no errors) are loaded upon clicking "Add new" button.

// App/Entity/Menu.php
<?php

namespace App\Entity;

use App\Entity\Traits\Identifiable;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;

/**
 * Class Menu
 *
 * @ORM\Entity
 * @ORM\Table(name="menus")
 */
class Menu
{
    use Identifiable;

    /**
     * @var Menu|null
     *
     * @ORM\ManyToOne(targetEntity="App\Entity\Menu", inversedBy="children")
     */
    protected $parent;

    /**
     * @var Menu[]|Collection
     *
     * @ORM\OneToMany(targetEntity="App\Entity\Menu", mappedBy="parent", cascade={"persist", "remove"})
     */
    protected $children;

    /**
     * @var string|null
     *
     * @ORM\Column(type="string", length=255)
     */
    protected $name;

    /**
     * @var string|null
     *
     * @ORM\Column(type="string", length=255)
     */
    protected $linkOrRoute;

    /**
     * Menu constructor.
     */
    public function __construct()
    {
        $this->children = new ArrayCollection();
    }

    /**
     * @return string
     */
    public function __toString(): string
    {
        return (string) $this->name;
    }

    /**
     * @return string|null
     */
    public function getName(): ?string
    {
        return $this->name;
    }

    /**
     * @param string|null $name
     *
     * @return Menu
     */
    public function setName(?string $name): Menu
    {
        $this->name = $name;

        return $this;
    }

    /**
     * @return string|null
     */
    public function getLinkOrRoute(): ?string
    {
        return $this->linkOrRoute;
    }

    /**
     * @param string|null $linkOrRoute
     *
     * @return Menu
     */
    public function setLinkOrRoute(?string $linkOrRoute): Menu
    {
        $this->linkOrRoute = $linkOrRoute;

        return $this;
    }

    /**
     * @return Menu|null
     */
    public function getParent(): ?Menu
    {
        return $this->parent;
    }

    /**
     * @param Menu|null $parent
     *
     * @return Menu
     */
    public function setParent(?Menu $parent): Menu
    {
        $this->parent = $parent;

        return $this;
    }

    /**
     * @return Menu[]|Collection
     */
    public function getChildren(): Collection
    {
        return $this->children;
    }

    /**
     * @param Menu[]|Collection $children
     *
     * @return Menu
     */
    public function setChildren(Collection $children): Menu
    {
        $this->children = $children;

        return $this;
    }

    /**
     * @param Menu $menu
     *
     * @return $this
     */
    public function addChild(Menu $menu): Menu
    {
        if (!$this->children->contains($menu)) {
            $this->children->add($menu);
            $menu->setParent($this);
        }

        return $this;
    }

    /**
     * @param Menu $menu
     *
     * @return $this
     */
    public function removeChild(Menu $menu): Menu
    {
        if ($this->children->contains($menu)) {
            $this->children->removeElement($menu);
            $menu->setParent(null);
        }

        return $this;
    }
}
# App/Admin/MenuAdmin.php

<?php

namespace App\Admin;

use App\Entity\Menu;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\Form\Type\CollectionType;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;

/**
 * Class MenuAdmin
 */
class MenuAdmin extends AbstractAdmin
{
    /**
     * @inheritdoc
     */
    protected function configureListFields(ListMapper $list)
    {
        $list
            ->addIdentifier('name');
    }

    /**
     * @inheritdoc
     */
    protected function configureFormFields(FormMapper $form)
    {
        $form
            ->with('Menu')
                ->add('parent', EntityType::class, [
                    'required' => false,
                    'class'    => Menu::class
                ])
                ->add('name')
                ->add('linkOrRoute')
                ->add('children', CollectionType::class, [  // <----- HERE: referencing the same admin
                    'required' => false,
                    'by_reference' => false,
                    'type_options' => [
                        'delete' => true
                    ]
                ], [
                    'edit' => 'inline',
                    'inline' => 'table'
                ])
                ->end()
            ->end();
    }
}

screen

alexandrubau commented 4 years ago

I think it was more appropriate to open the bug in the "sonata-admin" project. Moved it here.