Search code examples
phpsymfonysonata-adminsymfony-sonata

Field image is not linked to an admin


I have two entities: Product and Image and many Products can have many Images so this generates a third table ProductHasImages. Entities are right as doctrine:schema:validate command outputs:

Symfony > doctrine:schema:validate
[Mapping]  OK - The mapping files are correct.
[Database] FAIL - The database schema is not in sync with the current
mapping file.
The command terminated with an error status (2)

I've added this lines to my config.yml:

services:
  tan.common.admin.image:
    class: Tan\CommonBundle\Admin\ImageAdmin
    tags:
      - { name: sonata.admin, manager_type: orm, label: "Imagenes",
show_in_dashboard: false }
    arguments: [null, Tan\CommonBundle\Entity\Image, null]

I've have the file Tan\CommonBundle\Admin\ImageAdmin.php created with the following content:

<?php

namespace Tan\CommonBundle\Admin;

use Sonata\AdminBundle\Admin\Admin;
use Sonata\AdminBundle\Form\FormMapper;

class ImageAdmin extends Admin
{

    protected function configureFormFields(FormMapper $formMapper)
    {
        $formMapper->add('file', 'file', array('required' => false));
    }

    public function prePersist($image)
    {
        $this->manageFileUpload($image);
    }

    public function preUpdate($image)
    {
        $this->manageFileUpload($image);
    }

    private function manageFileUpload($image)
    {
        if ($image->getFile()) {
            $image->refreshUpdated();
        }
    }

}

Now I'm trying to add the image field to ProductAdmin.php as follow:

    protected function configureFormFields(FormMapper $form)
    {

        $form
            ->add('product_name', null, array('label' => 'Nombre'))
            ->add('product_description', null, array('label' => 'Descripción'))
            ->add('image', 'sonata_type_admin', array('delete' => false));
    }

But any time I try to add a new product I get this error:

The current field image is not linked to an admin. Please create one for the target entity : ``

Why? What I'm doing wrong?


Solution

  • For files the best in sonata admin use Sonata Media Bundle to handle uploads and you can reuse them in your different admin once you have configured then your mapping will be

    Entities

    • Products
    • ProductHasImages

    Now Products entity will have a mapping for ProductHasImages which can point many images (Media files from sonata media bundle) similar to

    /**
     * @Assert\NotBlank()
     * @ORM\OneToMany(targetEntity="Namespace\YourBundle\Entity\ProductHasImages", mappedBy="productImages",cascade={"persist","remove"} )
     */
    protected $images;
    
    other fields ...
    

    Generate its getter and setter methods

    removeImages()
    getImages()
    setImages()
    addImages()
    

    And now your junction entity i.e (ProductHasImages) will have a 2 mappings to point back Products and other one will point to Sonata Media

    /**
     * @var \Application\Sonata\MediaBundle\Entity\Media
     * @Assert\NotBlank()
     * @ORM\ManyToOne(targetEntity="Application\Sonata\MediaBundle\Entity\Media", cascade={"persist"}, fetch="LAZY")
     * @ORM\JoinColumn(name="media_id", referencedColumnName="id")
     */
    protected $media;
    
    /**
     * @var \Namespace\YourBundle\Entity\Products
     * @Assert\NotBlank()
     * @ORM\ManyToOne(targetEntity="Namespace\YourBundle\Entity\Products", cascade={"persist","remove"} ,inversedBy="images", fetch="LAZY" )
     * @ORM\JoinColumn(name="product_id", referencedColumnName="id",nullable=true)
     */
    protected $productImages;
    

    Generate their getters and setters

    Now create Admin class for ProductHasImages

    which has a field in configureFormFields function

    $formMapper->add('media', 'sonata_type_model_list', array('required' => false), array(
                'link_parameters' => $link_parameters
            )); //other fields too if you want to show in collection 
    

    And in your Product Admin class add this field

        ->add('images', 'sonata_type_collection', array(
                'cascade_validation' => false,
                'type_options' => array('delete' => false),
            ), array(
    
                'edit' => 'inline',
                'inline' => 'table',
                'sortable' => 'position',
                'link_parameters' => array('context' => 'default'),
                'admin_code' => 'sonata.admin.product_has_images' 
          /*here provide service name for junction admin 
            like service code for admin defined for ProductHasImages */
            )
        )
    

    You can find full code demo here Git Hub