sonata-project / SonataAdminBundle

The missing Symfony Admin Generator
https://docs.sonata-project.org/projects/SonataAdminBundle
MIT License
2.1k stars 1.26k forks source link

The name "Doctrine\ODM\MongoDB\ArrayCollectionelements" contains illegal characters. #8148

Closed smilesrg closed 6 months ago

smilesrg commented 6 months ago

Environment

Dev, os x 14.1.2 (23B92), Docker

Sonata packages

show

``` Direct dependencies required in composer.json: sonata-project/admin-bundle 4.28.0 4.29.2 The missing Symfony Admin Generator sonata-project/doctrine-mongodb-admin-bundle 4.10.0 4.10.0 Symfony Sonata / Integrate Doctrine MongoDB ODM i... sonata-project/intl-bundle 3.2.0 3.2.0 Symfony SonataIntlBundle Transitive dependencies not required in composer.json: sonata-project/block-bundle 4.19.0 5.1.0 Symfony SonataBlockBundle sonata-project/cache 2.2.0 2.2.0 Cache library Package sonata-project/cache is abandoned, you should avoid using it. No replacement was suggested. sonata-project/doctrine-extensions 2.3.0 2.3.0 Doctrine2 behavioral extensions sonata-project/exporter 3.3.0 3.3.0 Lightweight Exporter library sonata-project/form-extensions 1.20.0 2.3.0 Symfony form extensions sonata-project/twig-extensions 2.3.0 2.4.0 Sonata twig extensions ```

Symfony packages

show

``` Direct dependencies required in composer.json: symfony/asset v5.4.31 v6.4.0 Manages URL generation and versioning of web assets such ... symfony/browser-kit v5.4.31 v6.4.0 Simulates the behavior of a web browser, allowing you to ... symfony/cache v5.4.32 v6.4.0 Provides extended PSR-6, PSR-16 (and tags) implementations symfony/console v5.4.32 v6.4.1 Eases the creation of beautiful and testable command line... symfony/css-selector v5.4.26 v6.4.0 Converts CSS selectors to XPath expressions symfony/dotenv v5.4.30 v6.4.0 Registers environment variables from a .env file symfony/expression-language v5.4.21 v6.4.0 Provides an engine that can compile and evaluate expressions symfony/flex v1.21.3 v2.4.2 Composer plugin for Symfony symfony/framework-bundle v5.4.32 v6.4.1 Provides a tight integration between Symfony components a... symfony/intl v5.4.30 v6.4.0 Provides a PHP replacement layer for the C intl extension... symfony/mailer v5.4.31 v6.4.0 Helps sending emails symfony/maker-bundle v1.50.0 v1.52.0 Symfony Maker helps you create empty commands, controller... symfony/mime v5.4.26 v6.4.0 Allows manipulating MIME messages symfony/phpunit-bridge v5.4.33 v7.0.1 Provides utilities for PHPUnit, especially user deprecati... symfony/property-access v5.4.26 v6.4.0 Provides functions to read and write from/to an object or... symfony/property-info v5.4.24 v6.4.0 Extracts information about PHP class' properties using me... symfony/proxy-manager-bridge v5.4.21 v6.4.0 Provides integration for ProxyManager with various Symfon... symfony/security-bundle v5.4.31 v6.4.0 Provides a tight integration of the Security component in... symfony/sendgrid-mailer v5.4.23 v6.4.0 Symfony Sendgrid Mailer Bridge symfony/serializer v5.4.33 v6.4.1 Handles serializing and deserializing data structures, in... symfony/twig-bundle v5.4.31 v6.4.0 Provides a tight integration of Twig into the Symfony ful... symfony/validator v5.4.32 v6.4.0 Provides tools to validate values symfony/workflow v5.4.28 v6.4.1 Provides tools for managing a workflow or finite state ma... symfony/yaml v5.4.31 v6.4.0 Loads and dumps YAML files Transitive dependencies not required in composer.json: symfony/cache-contracts v2.5.2 v3.4.0 Generic abstractions related to caching symfony/config v5.4.31 v6.4.0 Helps you find, load, combine, autofill and validate conf... symfony/dependency-injection v5.4.33 v6.4.1 Allows you to standardize and centralize the way objects ... symfony/deprecation-contracts v3.4.0 v3.4.0 A generic function and convention to trigger deprecation ... symfony/doctrine-bridge v5.4.31 v6.4.0 Provides integration for Doctrine with various Symfony co... symfony/dom-crawler v5.4.32 v6.4.0 Eases DOM navigation for HTML and XML documents symfony/error-handler v5.4.29 v6.4.0 Provides tools to manage errors and ease debugging PHP code symfony/event-dispatcher v5.4.26 v6.4.0 Provides tools that allow your application components to ... symfony/event-dispatcher-contracts v3.4.0 v3.4.0 Generic abstractions related to dispatching event symfony/filesystem v5.4.25 v6.4.0 Provides basic utilities for the filesystem symfony/finder v5.4.27 v6.4.0 Finds files and directories via an intuitive fluent inter... symfony/form v5.4.33 v6.4.1 Allows to easily create, process and reuse HTML forms symfony/http-client v5.4.31 v6.4.0 Provides powerful methods to fetch HTTP resources synchro... symfony/http-client-contracts v2.5.2 v3.4.0 Generic abstractions related to HTTP clients symfony/http-foundation v5.4.32 v6.4.0 Defines an object-oriented layer for the HTTP specification symfony/http-kernel v5.4.33 v6.4.1 Provides a structured process for converting a Request in... symfony/options-resolver v5.4.21 v6.4.0 Provides an improved replacement for the array_replace PH... symfony/password-hasher v5.4.31 v6.4.0 Provides password hashing utilities symfony/polyfill-intl-grapheme v1.28.0 v1.28.0 Symfony polyfill for intl's grapheme_* functions symfony/polyfill-intl-icu v1.28.0 v1.28.0 Symfony polyfill for intl's ICU-related data and classes symfony/polyfill-intl-idn v1.28.0 v1.28.0 Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 ... symfony/polyfill-intl-normalizer v1.28.0 v1.28.0 Symfony polyfill for intl's Normalizer class and related ... symfony/polyfill-mbstring v1.28.0 v1.28.0 Symfony polyfill for the Mbstring extension symfony/polyfill-php56 v1.20.0 v1.20.0 Symfony polyfill backporting some PHP 5.6+ features to lo... symfony/polyfill-php73 v1.28.0 v1.28.0 Symfony polyfill backporting some PHP 7.3+ features to lo... symfony/polyfill-php80 v1.28.0 v1.28.0 Symfony polyfill backporting some PHP 8.0+ features to lo... symfony/polyfill-php81 v1.28.0 v1.28.0 Symfony polyfill backporting some PHP 8.1+ features to lo... symfony/process v5.4.28 v6.4.0 Executes commands in sub-processes symfony/routing v5.4.33 v6.4.1 Maps an HTTP request to a set of configuration variables symfony/security-acl v3.3.3 v3.3.3 Symfony Security Component - ACL (Access Control List) symfony/security-core v5.4.30 v6.4.0 Symfony Security Component - Core Library symfony/security-csrf v5.4.27 v6.4.0 Symfony Security Component - CSRF Library symfony/security-guard v5.4.27 v5.4.27 Symfony Security Component - Guard symfony/security-http v5.4.31 v6.4.0 Symfony Security Component - HTTP Integration symfony/service-contracts v2.5.2 v3.4.0 Generic abstractions related to writing services symfony/string v5.4.32 v6.4.0 Provides an object-oriented API to strings and deals with... symfony/templating v5.4.21 v6.4.0 Provides all the tools needed to build any kind of templa... symfony/translation v5.4.31 v6.4.0 Provides tools to internationalize your application symfony/translation-contracts v2.5.2 v3.4.0 Generic abstractions related to translation symfony/twig-bridge v5.4.31 v6.4.0 Provides integration for Twig with various Symfony compon... symfony/var-dumper v5.4.29 v6.4.0 Provides mechanisms for walking through any arbitrary PHP... symfony/var-exporter v6.4.1 v6.4.1 Allows exporting any serializable PHP data structure to p... ```

PHP version

PHP 8.1.26 (cli) (built: Dec 19 2023 15:15:39) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.1.26, Copyright (c) Zend Technologies

Subject

The name "Doctrine\Common\Collections\ArrayCollectionelements" contains illegal characters. Names should start with a letter, digit or underscore and only contain letters, digits, numbers, underscores ("_"), hyphens ("-") and colons (":").

The definition of field:

use Sonata\Form\Type\CollectionType;
// ...
    protected function configureFormFields(FormMapper $form): void
    {
//...
            ->add('hotelInfoTranslations', CollectionType::class, [
                'modifiable' => true,
                'by_reference' => false,
            ], [
                'edit' => 'inline',
                'inline' => 'table',
                'sortable' => 'position',
            ])
//...

The definition of the Document field:

    /**
     * @var Collection<HotelInfoTranslation>
     */
    #[Assert\All([new Assert\Type(HotelInfoTranslation::class)])]
    #[Assert\Valid]
    #[ODM\EmbedMany(targetDocument: HotelInfoTranslation::class)]
    protected Collection $hotelInfoTranslations;

    public function __construct()
    {
        $this->hotelInfoTranslations = new ArrayCollection();
    }

Minimal repository with the bug

Steps to reproduce

I tried to display a collection of Documents (MongoDB) using use Sonata\Form\Type\CollectionType;, but when trying to add new element, server returns HTTP 500

Expected results

Actual results

curl 'http://localhost:8081/admin/core/append-form-field-element?_sonata_admin=App%5CAdmin%5CHotelAdmin&elementId=s658b1f54ef9be_hotelInfoTranslations&objectId=16&uniqid=s658b1f54ef9be&_sonata_name=admin_app_hotel_edit&id=16&_tab=tab_s658b183c4ce95_1494968676_2' \
  -H 'Accept: text/html, */*; q=0.01' \
  -H 'Accept-Language: uk,en-US;q=0.9,en;q=0.8,ru;q=0.7' \
  -H 'Cache-Control: no-cache' \
  -H 'Connection: keep-alive' \
  -H 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8' \
  -H 'Cookie: PHPSESSID=084bee652680722ab0ca84cb580ecf41; sonata_sidebar_hide=0' \
  -H 'Origin: http://localhost:8081' \
  -H 'Pragma: no-cache' \
  -H 'Referer: http://localhost:8081/admin/app/hotel/16/edit?_tab=tab_s658b183c4ce95_1494968676_2' \
  -H 'Sec-Fetch-Dest: empty' \
  -H 'Sec-Fetch-Mode: cors' \
  -H 'Sec-Fetch-Site: same-origin' \
  -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36' \
  -H 'X-Requested-With: XMLHttpRequest' \
  -H 'sec-ch-ua: "Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120"' \
  -H 'sec-ch-ua-mobile: ?0' \
  -H 'sec-ch-ua-platform: "macOS"' \
  --data-raw $'s658b1f54ef9be%5BhotelId%5D=16&s658b1f54ef9be%5BisEnabled%5D=1&s658b1f54ef9be%5BisApproved%5D=1&s658b1f54ef9be%5BhotelAddressPostcode%5D=01001&s658b1f54ef9be%5BhotelAddressCountry%5D=UA&s658b1f54ef9be%5BhotelType%5D=hotelTypeHotel&s658b1f54ef9be%5BhotelTypeStars%5D=5&s658b1f54ef9be%5BhotelCreditCard%5D%5B0%5D=VISA&s658b1f54ef9be%5BhotelCreditCard%5D%5B1%5D=MASTERCARD&s658b1f54ef9be%5BhotelTimeZone%5D=Europe%2FKyiv&s658b1f54ef9be%5BhotelCheckInTime%5D=900&s658b1f54ef9be%5BhotelCheckOutTime%5D=720&s658b1f54ef9be%5BhotelTotalRoomQuantity%5D=1&s658b1f54ef9be%5BhotelInfoTranslations%5D%5B0%5D%5BhotelName%5D=%D0%93%D0%BE%D1%81%D1%82%D0%B8%D0%BD%D0%B8%D1%87%D0%BD%D0%BE-%D1%80%D0%B5%D1%81%D1%82%D0%BE%D1%80%D0%B0%D0%BD%D0%BD%D1%8B%D0%B9+%D0%BA%D0%BE%D0%BC%D0%BF%D0%BB%D0%B5%D0%BA%D1%81+%D0%9F%D0%B0%D0%BD%D0%BE%D1%80%D0%B0%D0%BC%D0%B0&s658b1f54ef9be%5BhotelInfoTranslations%5D%5B0%5D%5BhotelDescription%5D=%D0%9E%D0%BF%D0%B8%D1%81+1+PanoramaPanoramaPanorama&s658b1f54ef9be%5BhotelInfoTranslations%5D%5B0%5D%5BhotelAddressStreet%5D=%D0%9F%D1%80%D0%B8%D0%B4%D0%BD%D1%96%D0%BF%D1%80%D0%BE%D0%B2%D1%81%D1%8C%D0%BA%D0%B8%D0%B9+%D1%83%D0%B7%D0%B2%D1%96%D0%B7%2C+2%D0%B0&s658b1f54ef9be%5BhotelInfoTranslations%5D%5B0%5D%5BhotelAddressCity%5D=%D0%A5%D0%B5%D1%80%D1%81%D0%BE%D0%BD&s658b1f54ef9be%5BhotelInfoTranslations%5D%5B0%5D%5Blanguage%5D=uk&s658b1f54ef9be%5BhotelInfoTranslations%5D%5B1%5D%5BhotelName%5D=Panorama&s658b1f54ef9be%5BhotelInfoTranslations%5D%5B1%5D%5BhotelDescription%5D=Description+2+PanoramaPanoramaPanorama&s658b1f54ef9be%5BhotelInfoTranslations%5D%5B1%5D%5BhotelAddressStreet%5D=Prydniprovs\'kyi+descent%2C+2%D0%B0&s658b1f54ef9be%5BhotelInfoTranslations%5D%5B1%5D%5BhotelAddressCity%5D=Kherson&s658b1f54ef9be%5BhotelInfoTranslations%5D%5B1%5D%5Blanguage%5D=en&s658b1f54ef9be%5BhotelServices%5D%5B0%5D=hotelServices0014&s658b1f54ef9be%5BhotelServices%5D%5B1%5D=hotelServices0112&s658b1f54ef9be%5BhotelServices%5D%5B2%5D=hotelServices0001&s658b1f54ef9be%5BhotelServices%5D%5B3%5D=hotelServices0002&s658b1f54ef9be%5BhotelServices%5D%5B4%5D=hotelServices0025&s658b1f54ef9be%5BhotelServices%5D%5B5%5D=hotelServices0027&s658b1f54ef9be%5BhotelServices%5D%5B6%5D=hotelServices0050&_tab=tab_s658b183c4ce95_1494968676_2&s658b1f54ef9be%5B_token%5D=97.IeGRXtKGP5mw8BZci_Tu95Vb1yttroTWM8F9omYebRA.E63TF6axdM_HonMb_YCPxeMOkAYj3tOMX_gX7xZKQClMk9Usl7JNqtuULg&_xml_http_request=true' \
  --compressed
Symfony\Component\Form\Exception\InvalidArgumentException:
The name &quot;�Doctrine\Common\Collections\ArrayCollection�elements &quot;contains illegal characters. Names should start with a letter, digit or underscore and only contain letters, digits, numbers, underscores (&quot;_ &quot;), hyphens (&quot;-&quot;) and colons (&quot;:&quot;).

  at vendor/symfony/form/FormConfigBuilder.php:793
  at Symfony\Component\Form\FormConfigBuilder::validateName('' . &quot;\0 &quot;. 'Doctrine\\Common\\Collections\\ArrayCollection' . &quot;\0 &quot;. 'elements')
     (vendor/symfony/form/FormConfigBuilder.php:114)
  at Symfony\Component\Form\FormConfigBuilder-&gt;__construct('' . &quot;\0 &quot;. 'Doctrine\\Common\\Collections\\ArrayCollection' . &quot;\0 &quot;. 'elements', 'App\\Document\\HotelInfoTranslation', object(EventDispatcher), array('block_name' => null, 'disabled' => false, 'label' => null, 'label_format' => null, 'label_translation_parameters' => array(), 'attr_translation_parameters' => array(), 'translation_domain' => null, 'trim' => true, 'required' => true, 'mapped' => true, 'by_reference' => true, 'inherit_data' => false, 'compound' => true, 'method' => 'POST', 'post_max_size_message' => 'The uploaded file was too large. Please try to upload a smaller file.', 'allow_file_upload' => false, 'help_translation_parameters' => array(), 'invalid_message' => 'This value is not valid.', 'invalid_message_parameters' => array(), 'error_mapping' => array(), 'allow_extra_fields' => false, 'extra_fields_message' => 'This form should not contain extra fields.', 'csrf_protection' => true, 'csrf_field_name' => '_token', 'csrf_message' => 'The CSRF token is invalid. Please try to resubmit the form.', 'csrf_token_manager' => object(CsrfTokenManager), 'csrf_token_id' => null, 'sonata_admin' => null, 'label_render' => true, 'horizontal_label_class' => '', 'horizontal_label_offset_class' => '', 'horizontal_input_wrapper_class' => '', 'delete_options' => array('type' => 'Symfony\\Component\\Form\\Extension\\Core\\Type\\CheckboxType', 'type_options' => array('required' => false, 'mapped' => false)), 'btn_add' => 'link_add', 'btn_list' => 'link_list', 'btn_delete' => 'link_delete', 'btn_translation_domain' => 'SonataAdminBundle', 'block_prefix' => null, 'row_attr' => array(), 'label_html' => false, 'attr' => array(), 'auto_initialize' => false, 'priority' => 0, 'form_attr' => false, 'data_class' => 'App\\Document\\HotelInfoTranslation', 'empty_data' => object(Closure), 'property_path' => '[' . &quot;\0 &quot;. 'Doctrine\\Common\\Collections\\ArrayCollection' . &quot;\0 &quot;. 'elements]', 'error_bubbling' => true, 'label_attr' => array(), 'action' => '', 'upload_max_size_message' => object(Closure), 'help' => null, 'help_attr' => array(), 'help_html' => false, 'is_empty_callback' => null, 'getter' => null, 'setter' => null, 'validation_groups' => null, 'constraints' => array(), 'legacy_error_messages' => true, 'sonata_field_description' => object(FieldDescription), 'delete' => true, 'btn_catalogue' => 'SonataAdminBundle', 'collection_by_reference' => false, 'data' => array('Doctrine\ODM\MongoDB\PersistentCollectionsnapshot' => array(), 'Doctrine\ODM\MongoDB\PersistentCollectionowner' => null, 'Doctrine\ODM\MongoDB\PersistentCollectionmapping' => array('fieldName' => 'hotelInfoTranslations', 'name' => 'hotelInfoTranslations', 'type' => 'many', 'nullable' => false, 'options' => array(), 'strategy' => 'pushAll', 'notSaved' => false, 'embedded' => true, 'targetDocument' => 'App\\Document\\HotelInfoTranslation', 'discriminatorField' => null, 'discriminatorMap' => null, 'defaultDiscriminatorValue' => null, 'collectionClass' => null, 'isCascadeRemove' => true, 'isCascadePersist' => true, 'isCascadeRefresh' => true, 'isCascadeMerge' => true, 'isCascadeDetach' => true, 'association' => 4, 'isOwningSide' => true, 'isInverseSide' => false), 'Doctrine\ODM\MongoDB\PersistentCollectionisDirty' => true, 'Doctrine\ODM\MongoDB\PersistentCollectioninitialized' => true, 'Doctrine\ODM\MongoDB\PersistentCollectioncoll' => object(ArrayCollection), 'Doctrine\ODM\MongoDB\PersistentCollectiondm' => object(DocumentManager), 'Doctrine\ODM\MongoDB\PersistentCollectionuow' => object(UnitOfWork), 'Doctrine\ODM\MongoDB\PersistentCollectionmongoData' => array(), 'Doctrine\ODM\MongoDB\PersistentCollectionhints' => array(), object(HotelInfoTranslation))))
     (vendor/symfony/form/FormBuilder.php:45)
  at Symfony\Component\Form\FormBuilder-&gt;__construct('' . &quot;\0 &quot;. 'Doctrine\\Common\\Collections\\ArrayCollection' . &quot;\0 &quot;. 'elements', 'App\\Document\\HotelInfoTranslation', object(EventDispatcher), object(FormFactory), array('block_name' => null, 'disabled' => false, 'label' => null, 'label_format' => null, 'label_translation_parameters' => array(), 'attr_translation_parameters' => array(), 'translation_domain' => null, 'trim' => true, 'required' => true, 'mapped' => true, 'by_reference' => true, 'inherit_data' => false, 'compound' => true, 'method' => 'POST', 'post_max_size_message' => 'The uploaded file was too large. Please try to upload a smaller file.', 'allow_file_upload' => false, 'help_translation_parameters' => array(), 'invalid_message' => 'This value is not valid.', 'invalid_message_parameters' => array(), 'error_mapping' => array(), 'allow_extra_fields' => false, 'extra_fields_message' => 'This form should not contain extra fields.', 'csrf_protection' => true, 'csrf_field_name' => '_token', 'csrf_message' => 'The CSRF token is invalid. Please try to resubmit the form.', 'csrf_token_manager' => object(CsrfTokenManager), 'csrf_token_id' => null, 'sonata_admin' => null, 'label_render' => true, 'horizontal_label_class' => '', 'horizontal_label_offset_class' => '', 'horizontal_input_wrapper_class' => '', 'delete_options' => array('type' => 'Symfony\\Component\\Form\\Extension\\Core\\Type\\CheckboxType', 'type_options' => array('required' => false, 'mapped' => false)), 'btn_add' => 'link_add', 'btn_list' => 'link_list', 'btn_delete' => 'link_delete', 'btn_translation_domain' => 'SonataAdminBundle', 'block_prefix' => null, 'row_attr' => array(), 'label_html' => false, 'attr' => array(), 'auto_initialize' => false, 'priority' => 0, 'form_attr' => false, 'data_class' => 'App\\Document\\HotelInfoTranslation', 'empty_data' => object(Closure), 'property_path' => '[' . &quot;\0 &quot;. 'Doctrine\\Common\\Collections\\ArrayCollection' . &quot;\0 &quot;. 'elements]', 'error_bubbling' => true, 'label_attr' => array(), 'action' => '', 'upload_max_size_message' => object(Closure), 'help' => null, 'help_attr' => array(), 'help_html' => false, 'is_empty_callback' => null, 'getter' => null, 'setter' => null, 'validation_groups' => null, 'constraints' => array(), 'legacy_error_messages' => true, 'sonata_field_description' => object(FieldDescription), 'delete' => true, 'btn_catalogue' => 'SonataAdminBundle', 'collection_by_reference' => false, 'data' => array('Doctrine\ODM\MongoDB\PersistentCollectionsnapshot' => array(), 'Doctrine\ODM\MongoDB\PersistentCollectionowner' => null, 'Doctrine\ODM\MongoDB\PersistentCollectionmapping' => array('fieldName' => 'hotelInfoTranslations', 'name' => 'hotelInfoTranslations', 'type' => 'many', 'nullable' => false, 'options' => array(), 'strategy' => 'pushAll', 'notSaved' => false, 'embedded' => true, 'targetDocument' => 'App\\Document\\HotelInfoTranslation', 'discriminatorField' => null, 'discriminatorMap' => null, 'defaultDiscriminatorValue' => null, 'collectionClass' => null, 'isCascadeRemove' => true, 'isCascadePersist' => true, 'isCascadeRefresh' => true, 'isCascadeMerge' => true, 'isCascadeDetach' => true, 'association' => 4, 'isOwningSide' => true, 'isInverseSide' => false), 'Doctrine\ODM\MongoDB\PersistentCollectionisDirty' => true, 'Doctrine\ODM\MongoDB\PersistentCollectioninitialized' => true, 'Doctrine\ODM\MongoDB\PersistentCollectioncoll' => object(ArrayCollection), 'Doctrine\ODM\MongoDB\PersistentCollectiondm' => object(DocumentManager), 'Doctrine\ODM\MongoDB\PersistentCollectionuow' => object(UnitOfWork), 'Doctrine\ODM\MongoDB\PersistentCollectionmongoData' => array(), 'Doctrine\ODM\MongoDB\PersistentCollectionhints' => array(), object(HotelInfoTranslation))))
     (vendor/symfony/form/ResolvedFormType.php:210)
  at Symfony\Component\Form\ResolvedFormType-&gt;newBuilder('' . &quot;\0 &quot;. 'Doctrine\\Common\\Collections\\ArrayCollection' . &quot;\0 &quot;. 'elements', 'App\\Document\\HotelInfoTranslation', object(FormFactory), array('block_name' => null, 'disabled' => false, 'label' => null, 'label_format' => null, 'label_translation_parameters' => array(), 'attr_translation_parameters' => array(), 'translation_domain' => null, 'trim' => true, 'required' => true, 'mapped' => true, 'by_reference' => true, 'inherit_data' => false, 'compound' => true, 'method' => 'POST', 'post_max_size_message' => 'The uploaded file was too large. Please try to upload a smaller file.', 'allow_file_upload' => false, 'help_translation_parameters' => array(), 'invalid_message' => 'This value is not valid.', 'invalid_message_parameters' => array(), 'error_mapping' => array(), 'allow_extra_fields' => false, 'extra_fields_message' => 'This form should not contain extra fields.', 'csrf_protection' => true, 'csrf_field_name' => '_token', 'csrf_message' => 'The CSRF token is invalid. Please try to resubmit the form.', 'csrf_token_manager' => object(CsrfTokenManager), 'csrf_token_id' => null, 'sonata_admin' => null, 'label_render' => true, 'horizontal_label_class' => '', 'horizontal_label_offset_class' => '', 'horizontal_input_wrapper_class' => '', 'delete_options' => array('type' => 'Symfony\\Component\\Form\\Extension\\Core\\Type\\CheckboxType', 'type_options' => array('required' => false, 'mapped' => false)), 'btn_add' => 'link_add', 'btn_list' => 'link_list', 'btn_delete' => 'link_delete', 'btn_translation_domain' => 'SonataAdminBundle', 'block_prefix' => null, 'row_attr' => array(), 'label_html' => false, 'attr' => array(), 'auto_initialize' => false, 'priority' => 0, 'form_attr' => false, 'data_class' => 'App\\Document\\HotelInfoTranslation', 'empty_data' => object(Closure), 'property_path' => '[' . &quot;\0 &quot;. 'Doctrine\\Common\\Collections\\ArrayCollection' . &quot;\0 &quot;. 'elements]', 'error_bubbling' => true, 'label_attr' => array(), 'action' => '', 'upload_max_size_message' => object(Closure), 'help' => null, 'help_attr' => array(), 'help_html' => false, 'is_empty_callback' => null, 'getter' => null, 'setter' => null, 'validation_groups' => null, 'constraints' => array(), 'legacy_error_messages' => true, 'sonata_field_description' => object(FieldDescription), 'delete' => true, 'btn_catalogue' => 'SonataAdminBundle', 'collection_by_reference' => false, 'data' => array('Doctrine\ODM\MongoDB\PersistentCollectionsnapshot' => array(), 'Doctrine\ODM\MongoDB\PersistentCollectionowner' => null, 'Doctrine\ODM\MongoDB\PersistentCollectionmapping' => array('fieldName' => 'hotelInfoTranslations', 'name' => 'hotelInfoTranslations', 'type' => 'many', 'nullable' => false, 'options' => array(), 'strategy' => 'pushAll', 'notSaved' => false, 'embedded' => true, 'targetDocument' => 'App\\Document\\HotelInfoTranslation', 'discriminatorField' => null, 'discriminatorMap' => null, 'defaultDiscriminatorValue' => null, 'collectionClass' => null, 'isCascadeRemove' => true, 'isCascadePersist' => true, 'isCascadeRefresh' => true, 'isCascadeMerge' => true, 'isCascadeDetach' => true, 'association' => 4, 'isOwningSide' => true, 'isInverseSide' => false), 'Doctrine\ODM\MongoDB\PersistentCollectionisDirty' => true, 'Doctrine\ODM\MongoDB\PersistentCollectioninitialized' => true, 'Doctrine\ODM\MongoDB\PersistentCollectioncoll' => object(ArrayCollection), 'Doctrine\ODM\MongoDB\PersistentCollectiondm' => object(DocumentManager), 'Doctrine\ODM\MongoDB\PersistentCollectionuow' => object(UnitOfWork), 'Doctrine\ODM\MongoDB\PersistentCollectionmongoData' => array(), 'Doctrine\ODM\MongoDB\PersistentCollectionhints' => array(), object(HotelInfoTranslation))))
     (vendor/symfony/form/ResolvedFormType.php:108)
  at Symfony\Component\Form\ResolvedFormType-&gt;createBuilder(object(FormFactory), '' . &quot;\0 &quot;. 'Doctrine\\Common\\Collections\\ArrayCollection' . &quot;\0 &quot;. 'elements', array('block_name' => null, 'disabled' => false, 'label' => null, 'label_format' => null, 'label_translation_parameters' => array(), 'attr_translation_parameters' => array(), 'translation_domain' => null, 'trim' => true, 'required' => true, 'mapped' => true, 'by_reference' => true, 'inherit_data' => false, 'compound' => true, 'method' => 'POST', 'post_max_size_message' => 'The uploaded file was too large. Please try to upload a smaller file.', 'allow_file_upload' => false, 'help_translation_parameters' => array(), 'invalid_message' => 'This value is not valid.', 'invalid_message_parameters' => array(), 'error_mapping' => array(), 'allow_extra_fields' => false, 'extra_fields_message' => 'This form should not contain extra fields.', 'csrf_protection' => true, 'csrf_field_name' => '_token', 'csrf_message' => 'The CSRF token is invalid. Please try to resubmit the form.', 'csrf_token_manager' => object(CsrfTokenManager), 'csrf_token_id' => null, 'sonata_admin' => null, 'label_render' => true, 'horizontal_label_class' => '', 'horizontal_label_offset_class' => '', 'horizontal_input_wrapper_class' => '', 'delete_options' => array('type' => 'Symfony\\Component\\Form\\Extension\\Core\\Type\\CheckboxType', 'type_options' => array('required' => false, 'mapped' => false)), 'btn_add' => 'link_add', 'btn_list' => 'link_list', 'btn_delete' => 'link_delete', 'btn_translation_domain' => 'SonataAdminBundle', 'block_prefix' => null, 'row_attr' => array(), 'label_html' => false, 'attr' => array(), 'auto_initialize' => false, 'priority' => 0, 'form_attr' => false, 'data_class' => 'App\\Document\\HotelInfoTranslation', 'empty_data' => object(Closure), 'property_path' => '[' . &quot;\0 &quot;. 'Doctrine\\Common\\Collections\\ArrayCollection' . &quot;\0 &quot;. 'elements]', 'error_bubbling' => true, 'label_attr' => array(), 'action' => '', 'upload_max_size_message' => object(Closure), 'help' => null, 'help_attr' => array(), 'help_html' => false, 'is_empty_callback' => null, 'getter' => null, 'setter' => null, 'validation_groups' => null, 'constraints' => array(), 'legacy_error_messages' => true, 'sonata_field_description' => object(FieldDescription), 'delete' => true, 'btn_catalogue' => 'SonataAdminBundle', 'collection_by_reference' => false, 'data' => array('Doctrine\ODM\MongoDB\PersistentCollectionsnapshot' => array(), 'Doctrine\ODM\MongoDB\PersistentCollectionowner' => null, 'Doctrine\ODM\MongoDB\PersistentCollectionmapping' => array('fieldName' => 'hotelInfoTranslations', 'name' => 'hotelInfoTranslations', 'type' => 'many', 'nullable' => false, 'options' => array(), 'strategy' => 'pushAll', 'notSaved' => false, 'embedded' => true, 'targetDocument' => 'App\\Document\\HotelInfoTranslation', 'discriminatorField' => null, 'discriminatorMap' => null, 'defaultDiscriminatorValue' => null, 'collectionClass' => null, 'isCascadeRemove' => true, 'isCascadePersist' => true, 'isCascadeRefresh' => true, 'isCascadeMerge' => true, 'isCascadeDetach' => true, 'association' => 4, 'isOwningSide' => true, 'isInverseSide' => false), 'Doctrine\ODM\MongoDB\PersistentCollectionisDirty' => true, 'Doctrine\ODM\MongoDB\PersistentCollectioninitialized' => true, 'Doctrine\ODM\MongoDB\PersistentCollectioncoll' => object(ArrayCollection), 'Doctrine\ODM\MongoDB\PersistentCollectiondm' => object(DocumentManager), 'Doctrine\ODM\MongoDB\PersistentCollectionuow' => object(UnitOfWork), 'Doctrine\ODM\MongoDB\PersistentCollectionmongoData' => array(), 'Doctrine\ODM\MongoDB\PersistentCollectionhints' => array(), object(HotelInfoTranslation))))
     (vendor/symfony/form/FormFactory.php:69)
  at Symfony\Component\Form\FormFactory-&gt;createNamedBuilder('' . &quot;\0 &quot;. 'Doctrine\\Common\\Collections\\ArrayCollection' . &quot;\0 &quot;. 'elements', object(ResolvedFormType), null, array('sonata_field_description' => object(FieldDescription), 'data_class' => 'App\\Document\\HotelInfoTranslation', 'empty_data' => object(Closure), 'collection_by_reference' => false, 'property_path' => '[' . &quot;\0 &quot;. 'Doctrine\\Common\\Collections\\ArrayCollection' . &quot;\0 &quot;. 'elements]', 'data' => array('Doctrine\ODM\MongoDB\PersistentCollectionsnapshot' => array(), 'Doctrine\ODM\MongoDB\PersistentCollectionowner' => null, 'Doctrine\ODM\MongoDB\PersistentCollectionmapping' => array('fieldName' => 'hotelInfoTranslations', 'name' => 'hotelInfoTranslations', 'type' => 'many', 'nullable' => false, 'options' => array(), 'strategy' => 'pushAll', 'notSaved' => false, 'embedded' => true, 'targetDocument' => 'App\\Document\\HotelInfoTranslation', 'discriminatorField' => null, 'discriminatorMap' => null, 'defaultDiscriminatorValue' => null, 'collectionClass' => null, 'isCascadeRemove' => true, 'isCascadePersist' => true, 'isCascadeRefresh' => true, 'isCascadeMerge' => true, 'isCascadeDetach' => true, 'association' => 4, 'isOwningSide' => true, 'isInverseSide' => false), 'Doctrine\ODM\MongoDB\PersistentCollectionisDirty' => true, 'Doctrine\ODM\MongoDB\PersistentCollectioninitialized' => true, 'Doctrine\ODM\MongoDB\PersistentCollectioncoll' => object(ArrayCollection), 'Doctrine\ODM\MongoDB\PersistentCollectiondm' => object(DocumentManager), 'Doctrine\ODM\MongoDB\PersistentCollectionuow' => object(UnitOfWork), 'Doctrine\ODM\MongoDB\PersistentCollectionmongoData' => array(), 'Doctrine\ODM\MongoDB\PersistentCollectionhints' => array(), object(HotelInfoTranslation)), 'auto_initialize' => false))
     (vendor/symfony/form/FormFactory.php:39)
  at Symfony\Component\Form\FormFactory-&gt;createNamed('' . &quot;\0 &quot;. 'Doctrine\\Common\\Collections\\ArrayCollection' . &quot;\0 &quot;. 'elements', 'Sonata\\AdminBundle\\Form\\Type\\AdminType', null, array('sonata_field_description' => object(FieldDescription), 'data_class' => 'App\\Document\\HotelInfoTranslation', 'empty_data' => object(Closure), 'collection_by_reference' => false, 'property_path' => '[' . &quot;\0 &quot;. 'Doctrine\\Common\\Collections\\ArrayCollection' . &quot;\0 &quot;. 'elements]', 'data' => array('Doctrine\ODM\MongoDB\PersistentCollectionsnapshot' => array(), 'Doctrine\ODM\MongoDB\PersistentCollectionowner' => null, 'Doctrine\ODM\MongoDB\PersistentCollectionmapping' => array('fieldName' => 'hotelInfoTranslations', 'name' => 'hotelInfoTranslations', 'type' => 'many', 'nullable' => false, 'options' => array(), 'strategy' => 'pushAll', 'notSaved' => false, 'embedded' => true, 'targetDocument' => 'App\\Document\\HotelInfoTranslation', 'discriminatorField' => null, 'discriminatorMap' => null, 'defaultDiscriminatorValue' => null, 'collectionClass' => null, 'isCascadeRemove' => true, 'isCascadePersist' => true, 'isCascadeRefresh' => true, 'isCascadeMerge' => true, 'isCascadeDetach' => true, 'association' => 4, 'isOwningSide' => true, 'isInverseSide' => false), 'Doctrine\ODM\MongoDB\PersistentCollectionisDirty' => true, 'Doctrine\ODM\MongoDB\PersistentCollectioninitialized' => true, 'Doctrine\ODM\MongoDB\PersistentCollectioncoll' => object(ArrayCollection), 'Doctrine\ODM\MongoDB\PersistentCollectiondm' => object(DocumentManager), 'Doctrine\ODM\MongoDB\PersistentCollectionuow' => object(UnitOfWork), 'Doctrine\ODM\MongoDB\PersistentCollectionmongoData' => array(), 'Doctrine\ODM\MongoDB\PersistentCollectionhints' => array(), object(HotelInfoTranslation)), 'auto_initialize' => false))
     (vendor/symfony/form/Form.php:884)
  at Symfony\Component\Form\Form-&gt;add('' . &quot;\0 &quot;. 'Doctrine\\Common\\Collections\\ArrayCollection' . &quot;\0 &quot;. 'elements', 'Sonata\\AdminBundle\\Form\\Type\\AdminType', array('sonata_field_description' => object(FieldDescription), 'data_class' => 'App\\Document\\HotelInfoTranslation', 'empty_data' => object(Closure), 'collection_by_reference' => false, 'property_path' => '[' . &quot;\0 &quot;. 'Doctrine\\Common\\Collections\\ArrayCollection' . &quot;\0 &quot;. 'elements]', 'data' => array('Doctrine\ODM\MongoDB\PersistentCollectionsnapshot' => array(), 'Doctrine\ODM\MongoDB\PersistentCollectionowner' => null, 'Doctrine\ODM\MongoDB\PersistentCollectionmapping' => array('fieldName' => 'hotelInfoTranslations', 'name' => 'hotelInfoTranslations', 'type' => 'many', 'nullable' => false, 'options' => array(), 'strategy' => 'pushAll', 'notSaved' => false, 'embedded' => true, 'targetDocument' => 'App\\Document\\HotelInfoTranslation', 'discriminatorField' => null, 'discriminatorMap' => null, 'defaultDiscriminatorValue' => null, 'collectionClass' => null, 'isCascadeRemove' => true, 'isCascadePersist' => true, 'isCascadeRefresh' => true, 'isCascadeMerge' => true, 'isCascadeDetach' => true, 'association' => 4, 'isOwningSide' => true, 'isInverseSide' => false), 'Doctrine\ODM\MongoDB\PersistentCollectionisDirty' => true, 'Doctrine\ODM\MongoDB\PersistentCollectioninitialized' => true, 'Doctrine\ODM\MongoDB\PersistentCollectioncoll' => object(ArrayCollection), 'Doctrine\ODM\MongoDB\PersistentCollectiondm' => object(DocumentManager), 'Doctrine\ODM\MongoDB\PersistentCollectionuow' => object(UnitOfWork), 'Doctrine\ODM\MongoDB\PersistentCollectionmongoData' => array(), 'Doctrine\ODM\MongoDB\PersistentCollectionhints' => array(), object(HotelInfoTranslation)), 'auto_initialize' => false))
     (vendor/sonata-project/form-extensions/src/EventListener/ResizeFormListener.php:84)
  at Sonata\Form\EventListener\ResizeFormListener-&gt;preSetData(object(PreSetDataEvent), 'form.pre_set_data', object(EventDispatcher))
     (vendor/symfony/event-dispatcher/EventDispatcher.php:230)
  at Symfony\Component\EventDispatcher\EventDispatcher-&gt;callListeners(array(object(Closure)), 'form.pre_set_data', object(PreSetDataEvent))
     (vendor/symfony/event-dispatcher/EventDispatcher.php:59)
  at Symfony\Component\EventDispatcher\EventDispatcher-&gt;dispatch(object(PreSetDataEvent), 'form.pre_set_data')
     (vendor/symfony/event-dispatcher/ImmutableEventDispatcher.php:33)
  at Symfony\Component\EventDispatcher\ImmutableEventDispatcher-&gt;dispatch(object(PreSetDataEvent), 'form.pre_set_data')
     (vendor/symfony/form/Form.php:354)
  at Symfony\Component\Form\Form-&gt;setData(object(ArrayCollection))
     (vendor/symfony/form/Extension/Core/DataMapper/DataMapper.php:57)
  at Symfony\Component\Form\Extension\Core\DataMapper\DataMapper-&gt;mapDataToForms(object(Hotel), object(RecursiveIteratorIterator))
     (vendor/symfony/form/Form.php:388)
  at Symfony\Component\Form\Form-&gt;setData(object(Hotel))
     (vendor/sonata-project/admin-bundle/src/Admin/AdminHelper.php:197)
  at Sonata\AdminBundle\Admin\AdminHelper-&gt;appendFormFieldElement(object(HotelAdmin), object(Hotel), 's658b1f54ef9be_hotelInfoTranslations')
     (vendor/sonata-project/admin-bundle/src/Action/AppendFormFieldElementAction.php:68)
  at Sonata\AdminBundle\Action\AppendFormFieldElementAction-&gt;__invoke(object(Request))
     (vendor/symfony/http-kernel/HttpKernel.php:163)
  at Symfony\Component\HttpKernel\HttpKernel-&gt;handleRaw(object(Request), 1)
     (vendor/symfony/http-kernel/HttpKernel.php:75)
  at Symfony\Component\HttpKernel\HttpKernel-&gt;handle(object(Request), 1, true)
     (vendor/symfony/http-kernel/Kernel.php:202)
  at Symfony\Component\HttpKernel\Kernel-&gt;handle(object(Request))
     (public/index.php:20)              
smilesrg commented 6 months ago

I changed the field description to:

                ->add('hotelInfoTranslations', CollectionType::class, [
                    'modifiable' => true,
                    'by_reference' => false,
                ])

By removing

                    'edit' => 'inline',
                    'inline' => 'table',

And I can see the list of embedded objects and related data. But what is strange is that I can see two "Add element" buttons at the bottom of the list (which is weird). Clicking any of them opens the window with the form, which is expected, but element is not added. There are two methods that exist for adding and replacing elements:

    /**
     * @param iterable<HotelInfoTranslation> $hotelInfoTranslations
     */
    public function setHotelInfoTranslations(iterable $hotelInfoTranslations): self
    {
        $this->hotelInfoTranslations = new ArrayCollection((array)$hotelInfoTranslations);

        return $this;
    }

    public function addHotelInfoTranslation(HotelInfoTranslation $hotelInfoTranslation): self
    {
        $this->hotelInfoTranslations->add($hotelInfoTranslation);

        return $this;
    }

here is the request:

curl 'http://localhost:8081/admin/app/hotelinfotranslation/create?uniqid=s658c948b1c63f' \
  -H 'Accept: application/json' \
  -H 'Accept-Language: uk,en-US;q=0.9,en;q=0.8,ru;q=0.7' \
  -H 'Cache-Control: no-cache' \
  -H 'Connection: keep-alive' \
  -H 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8' \
  -H 'Cookie: sonata_sidebar_hide=0; PHPSESSID=f5dcffa54ecc75eb992c78491334e2f3' \
  -H 'Origin: http://localhost:8081' \
  -H 'Pragma: no-cache' \
  -H 'Referer: http://localhost:8081/admin/app/hotel/12/edit?_tab=tab_s658c948a0e66d_1426885114_4' \
  -H 'Sec-Fetch-Dest: empty' \
  -H 'Sec-Fetch-Mode: cors' \
  -H 'Sec-Fetch-Site: same-origin' \
  -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36' \
  -H 'X-Requested-With: XMLHttpRequest' \
  -H 'sec-ch-ua: "Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120"' \
  -H 'sec-ch-ua-mobile: ?0' \
  -H 'sec-ch-ua-platform: "macOS"' \
  --data-raw 's658c948b1c63f%5BhotelName%5D=TestTestTest&s658c948b1c63f%5BhotelDescription%5D=TestTestTestTestTestTestTestTestTestTestTest&s658c948b1c63f%5BhotelAddressStreet%5D=TestTestTestTestTest&s658c948b1c63f%5BhotelAddressCity%5D=TestTestTestTestTest&s658c948b1c63f%5Blanguage%5D=ab&s658c948b1c63f%5B_token%5D=669c012c0.KAUInNP4ASSdQgKsClUrh5d5LPdAWC6bPBpdeQ5fJ1o.RExA5eGoMAnVA0neXAoa7aJKQYQWb0_wXXUoF2wxHjtrZ3vMnLxIbMkkcQ&_xml_http_request=true' \
  --compressed

and the response is:

{
    "result": "ok",
    "objectId": "000000000000023c0000000000000000",
    "objectName": "App\\Document\\HotelInfoTranslation:000000000000023c0000000000000000"
}

But the object itself is embedded, it probably should not work like that

smilesrg commented 6 months ago

Closing as invalid. Resolved:

    /**
     * @param iterable<HotelInfoTranslation> $hotelInfoTranslations
     */
    public function setHotelInfoTranslations(iterable $hotelInfoTranslations): self
    {
        $this->hotelInfoTranslations = $hotelInfoTranslations instanceof Collection
            ? $hotelInfoTranslations
            : new ArrayCollection($hotelInfoTranslations);

        return $this;
    }