1

Problem description

I need to define object-related field (like sonata_type_model_list) inside sonata_type_immutable_array form type definition:

$formMapper->add('options', 'sonata_type_immutable_array', array(
    'keys' => array(
        array('linkName', 'text', array()),
        array('linkPath', 'sonata_type_model_list',
            array(
                'model_manager' => $linkAdmin->getModelManager(),
                'class' => $linkAdmin->getClass(),
            )
        )
    )
)

This is not working, here is error message:

Impossible to access an attribute ("associationadmin") on a NULL variable ("") in SonataDoctrineORMAdminBundle:Form:form_admin_fields.html.twig at line 60

What I found about this problem

I tryed to find any information about using sonata_type_model_list inside sonata_type_immutable_array, but there is very little information. This (https://github.com/a2lix/TranslationFormBundle/issues/155) topic helped me a bit, but doing all in the same manner I've got another error:

Impossible to invoke a method ("id") on a NULL variable ("") in SonataDoctrineORMAdminBundle:Form:form_admin_fields.html.twig at line 60

So I totally failed in uderstanding what I have to do.

My context

-- I have Doctrine ORM Mapped class called CmsLink, it defines object to which 'linkPath' field relates.

-- I have admin class for CmsLink class, it has very basic configuration:

protected function configureFormFields(FormMapper $formMapper)
{
  $formMapper
    ->add('technicalAlias')
    ->add('url')
  ;
}

-- I have Doctrine ORM Mapped class called CmsMenuItem, it defines object and 'options' filed which persists data managed by sonata_type_immutable_array form type, field type is json_array:

/**
* @var string
*
* @ORM\Column(name="options", type="json_array", nullable=true)
*/
private $options;

-- And finally I have admin class for CmsMenuItem class, here is the key code piece:

$linkAdmin = $this->configurationPool->getAdminByClass("Argon\\CMSBundle\\Entity\\CmsLink");

$formMapper
    ->add('options', 'sonata_type_immutable_array',
        array(
            'keys' => array(
                array('linkName', 'text', array()),
                array('linkPath', 'sonata_type_model_list',
                        array(
                            'model_manager' => $linkAdmin->getModelManager(),
                            'class' => $linkAdmin->getClass(),
                        )
                ),
                array('description', 'textarea', array()),
                array('image', 'sonata_media_type',
                    array(
                        'provider' => 'sonata.media.provider.image',
                        'context' => 'pages_static',
                        'required'=>false,
                    )
                )
            )
        )
    );

Question goals

  1. Find out what I need to do to bring life into this idea?
  2. Get general information and understanding abot how to include object-related field types into sonata_type_immutable_array
Arkemlar
  • 380
  • 4
  • 12
  • 1
    Did you ever solve this issue? I have the same at the moment –  Jan 15 '17 at 22:48
  • I abandoned this question because answer came too late, I used other way instead (don't remember what was it exactly), but soon I will work on some similar task, so I will investigate this problem again. Did u tried to use Adam's answer? – Arkemlar Jan 17 '17 at 21:29

1 Answers1

0

I've just come across this problem, and solved it with a custom type and data transformers.

Here's the rough outline, though you need to tailor it to your problem.

Custom Type

class YourImmutableArrayType extends ImmutableArrayType
{
    /**
     * @var YourSettingsObjectTransformer
     */
    private $transformer;

    public function __construct(YourSettingsObjectTransformer $transformer)
    {
        $this->transformer = $transformer;
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        parent::buildForm($builder, $options);
        $builder->addModelTransformer($this->transformer);
    }

    public function getName()
    {
        return 'your_type_name';
    }

    public function getParent()
    {
        return 'sonata_type_immutable_array';
    }
}

Custom model transformer

class NewsListingSettingsTransformer implements DataTransformerInterface
{

    public function __construct(ObjectManager $manager)
    {
        // You'll need the $manager to lookup your objects later
    }

    public function reverseTransform($value)
    {
        if (is_null($value)) {
            return $value;
        }

        // Here convert your objects in array to IDs

        return $value;
    }

    public function transform($value)
    {
        if (is_null($value)) {
            return $value;
        }

        // Here convert ids embedded in your array to objects, 
        // or ArrayCollection containing objects

        return $value;
    }

}

 Building form in admin class

    $formMapper->add('settings', 'your_type_name', array(
        'keys' => array(
            array(
                'collectionOfObjects',
                'sonata_type_model',
                array(
                    'class' => YourObject::class,
                    'multiple' => true,
                    'model_manager' => $this->yourObjectAdmin->getModelManager()
                )
            )
        )
    ));
}

Again, it's a rough outline, so tweak it to your needs.

Community
  • 1
  • 1
Adam
  • 5,091
  • 5
  • 32
  • 49