简体   繁体   中英

Symfony 4 + sonata admin bundle + relations. Form is deleting children but not only parentId

Good day everyone. I encounter some problem. I have sonata admin + symfony 4 + some entities with manytoone relations. I have 3 simple tables named banner videobanner photobanner and now i want to create admin part which will be created from 1 2 or 3 simple banners video banners or photobbanners. It is almost done but the form have some bugs, I can create simple banner and it is ok record created sucessfully but parentId is empty because it does not have any parents for now but later when im set in in admin parentId is createing in child table but later when im trying to delete the relation sonata admin deletes it with a child record. but i want sonata admin to delete only parentId child record must stay with parentId = NULL.

<?php

namespace App\Admin\Action\Banner;

use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Sonata\AdminBundle\Form\Type\ModelType;
use Sonata\AdminBundle\Admin\AbstractAdmin;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Datagrid\ListMapper;
use App\Cms\Entity\Banner\NestedBanner;
use App\Admin\Form\DataTransformer\BannerDataTransformer;
use App\Cms\Entity\Banner\Banner;

/**
 * 
 * Class NestedBannerAdmin.
 */
class NestedBannerAdmin extends AbstractAdmin
{
    /**
     * 
     * @param FormMapper $formMapper
     */
    protected function configureFormFields(FormMapper $formMapper)
    {
        $formMapper->add('title', TextType::class);
        $formMapper->add('description', TextareaType::class);
        $formMapper->add('banners');
        $formMapper->add('photoBanners');
        $formMapper->add('videoBanners');
        $formMapper->add('promoBlockBanners');

//        $formMapper
//            ->get('banners')
//            ->addModelTransformer(new BannerDataTransformer($this->getSubject()));

    }

    /**
     * 
     * @param DatagridMapper $datagridMapper
     */
    protected function configureDatagridFilters(DatagridMapper $datagridMapper)
    {
        $datagridMapper->add('title');
        $datagridMapper->add('description');
        $datagridMapper->add('banners');
        $datagridMapper->add('photoBanners');
        $datagridMapper->add('videoBanners');
        $datagridMapper->add('promoBlockBanners');
    }

    /**
     * 
     * @param ListMapper $listMapper
     */
    protected function configureListFields(ListMapper $listMapper)
    {
        $listMapper->addIdentifier('title');
        $listMapper->addIdentifier('description');
        $listMapper->add(
            'banners',
            null,
            [
                'label' => 'Banners',
                'sortable' => false,
                'allow_add' => false,
                'allow_delete' => false,
            ]
        );
        $listMapper->add(
            'photoBanners',
            null,
            [
                'label' => 'Photo banners',
                'sortable' => false,
                'allow_add' => true,
                'allow_delete' => false,
            ]
        );
        $listMapper->add(
            'videoBanners',
            null,
            [
                'label' => 'Video banners',
                'sortable' => false,
                'allow_add' => true,
                'allow_delete' => false,
            ]
        );
        $listMapper->add(
            'promoBlockBanners',
            null,
            [
                'label' => 'Promo block banners',
                'sortable' => false,
                'allow_add' => true,
                'allow_delete' => false,
            ]
        );
    }
    
    public function preUpdate($object)
    {
//        dd($object);
        if($object instanceof NestedBanner){
            foreach ($object->getBanners() as $banner) {
                $nestedBanner = $banner->getNestedBanner();
                if(null == $nestedBanner){
                    $banner->setNestedBanner($object);
                }
            }
            foreach ($object->getVideoBanners() as $banner) {
                $nestedBanner = $banner->getNestedBanner();
                if(null == $nestedBanner){
                    $banner->setNestedBanner($object);
                }
            }
            foreach ($object->getPhotoBanners() as $banner) {
                $nestedBanner = $banner->getNestedBanner();
                if(null == $nestedBanner){
                    $banner->setNestedBanner($object);
                }
            }
            foreach ($object->getPromoBlockBanners() as $banner) {
                $nestedBanner = $banner->getNestedBanner();
                if(null == $nestedBanner){
                    $banner->setNestedBanner($object);
                }
            }
        }
    }
}



<?php

namespace App\Cms\Entity\Banner;

use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\ArrayCollection;
use App\Cms\Entity\Banner\Banner;
use App\Cms\Entity\Banner\PhotoBanner;
use App\Cms\Entity\Banner\VideoBanner;
use App\Cms\Entity\Banner\PromoBlockBanner;

/**
 * 
 * @ORM\Entity(repositoryClass="App\Cms\Repository\Banner\NestedBannerRepository")
 * @ORM\Table(name="nested_banner")
 */
class NestedBanner {

    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(name="title", type="string", length=255)
     */
    private $title;

    /**
     * @ORM\Column(name="description", type="string", length=255)
     */
    private $description;
    
    /**
     * @var bannerMaps
     *
     * @ORM\OneToMany(
     *     targetEntity="App\Cms\Entity\Banner\Banner",
     *     mappedBy="nestedBanner",
     *     orphanRemoval=true,
     *     cascade={"persist"}
     * )
     *
     * @ORM\JoinColumn(onDelete="CASCADE")
     */
    private $banners;

    /**
     * @var bannerMaps
     *
     * @ORM\OneToMany(
     *     targetEntity="App\Cms\Entity\Banner\VideoBanner",
     *     mappedBy="nestedBanner",
     *     orphanRemoval=true,
     *     cascade={"persist"})
     *
     * @ORM\JoinColumn(onDelete="CASCADE")
     */
    private $videoBanners;

    /**
     * @var bannerMaps
     *
     * @ORM\OneToMany(
     *     targetEntity="App\Cms\Entity\Banner\PhotoBanner",
     *     mappedBy="nestedBanner",
     *     cascade={"persist"}),
     *     orphanRemoval=false
     *
     * @ORM\JoinColumn(onDelete="CASCADE")
     */
    private $photoBanners;

    /**
     * @var bannerMaps
     *
     * @ORM\OneToMany(
     *     targetEntity="App\Cms\Entity\Banner\PromoBlockBanner",
     *     mappedBy="nestedBanner",
     *     cascade={"persist"})
     *
     * @ORM\JoinColumn(onDelete="CASCADE")
     */
    private $promoBlockBanners;

    /**
     * 
     * @param type $id
     * @param type $title
     * @param type $description
     * @param Collection $bannerMaps
     */
    public function __construct() {
//        $this->banners = new ArrayCollection();
//        $this->videoBanners = new ArrayCollection();
//        $this->photoBanners = new ArrayCollection();
//        $this->promoBlockBanners = new ArrayCollection();
    }

    /**
     * 
     * @return int
     */
    public function getId(): ?int 
    {
        return $this->id;
    }

    /**
     * 
     * @return string
     */
    public function getTitle(): ?string
    {
        return $this->title;
    }

    /**
     * 
     * @return string
     */
    public function getBanners(): ?Collection
    {
        return $this->banners;
    }

    /**
     * 
     * @return string
     */
    public function getVideoBanners(): ?Collection
    {
        return $this->videoBanners;
    }

    /**
     * 
     * @return string
     */
    public function getPhotoBanners(): ?Collection
    {
        return $this->photoBanners;
    }

    /**
     * 
     * @return string
     */
    public function getPromoBlockBanners(): ?Collection
    {
        return $this->promoBlockBanners;
    }

    /**
     * 
     * @return string
     */
    public function getDescription(): ?string
    {
        return $this->description;
    }

    /**
     * 
     * @param int $id
     */
    public function setId(int $id) 
    {
        $this->id = $id;
    }

    /**
     * 
     * @param string $title
     */
    public function setTitle(string $title) 
    {
        $this->title = $title;
    }

    /**
     * 
     * @param Collection $banners
     */
    public function addBanner(Banner $banner): self
    {
        dd('addBanner');
        $this->banners[] = $banner;

        return $this;
    }

    /**
     * 
     * @param Collection $banners
     */
    public function addBanners(Collection $banners): self
    {
        dd('addBanners');
        $this->banners[] = $banner;

        return $this;
    }

    /**
     * 
     * @param Collection $banners
     */
    public function setBanners(Collection $banners): self
    {
        dd('setBanners');
        foreach($banners as $banner){
            $banner->setNestedBanner($this);
        }
        $this->banners = $banners;
        
        return $this;
    }

    /**
     * 
     * @param Collection $banners
     */
    public function removeBanner(Banner $banners): self
    {
        dd('removeBanner');
        foreach($banners as $banner){
            $banner->setNestedBanner($this);
        }
        $this->banners = $banners;
        
        return $this;
    }

    /**
     * 
     * @param Collection $banners
     */
    public function banner(Banner $banners): self
    {
        dd('Banner');
        foreach($banners as $banner){
            $banner->setNestedBanner($this);
        }
        $this->banners = $banners;
        
        return $this;
    }

    /**
     * 
     * @param Collection $videoBanners
     */
    public function setVideoBanners(Collection $videoBanners): self
    {
        $this->videoBanners = $videoBanners;

        return $this;
    }

    /**
     * 
     * @param Collection $photoBanners
     */
    public function setPhotoBanners(Collection $photoBanners): self
    {
        $this->photoBanners = $photoBanners;
        
        return $this;
    }

    /**
     * 
     * @param Collection $banners
     */
    public function setPromoBlockBanners(Collection $promoBlockBanners): self
    {
        $this->promoBlockBanners = $promoBlockBanners;

        return $this;
    }

    /**
     * 
     * @param string $description
     */
    public function setDescription(string $description) 
    {
        $this->description = $description;
    }

//    public function addBanner(Banner $banner): NestedBanner
//    {
//        
//        dd($banner);
//        $this->banners->add($banner);
//
//        return $this;
//    }
//
//    public function setBanner(Banner $banner): NestedBanner
//    {
//        
//        dd($banner);
//        $this->banners->add($banner);
//
//        return $this;
//    }

//    public function addPhotoBanner(PhotoBanner $photoBanner): NestedBanner
//    {
//        $this->photoBanners->add($photoBanner);
//
//        return $this;
//    }
//
//    public function addVideoBanner(VideoBanner $videoBanner): NestedBanner
//    {
//        $this->videoBanners->add($videoBanner);
//
//        return $this;
//    }
//
//    public function addPromoBlockBanner(PromoBlockBanner $promoBlockBanner): NestedBanner
//    {
//        $this->promoBlockBanners->add($promoBlockBanner);
//
//        return $this;
//    }

//    public function removeBanner(Banner $banner): NestedBanner
//    {
//        $this->banners->removeElement($banner);
//
//        return $this;
//    }
//
//    public function removePhotoBanner(PhotoBanner $photoBanner): NestedBanner
//    {
//        $this->photoBanners->removeElement($photoBanner);
//
//        return $this;
//    }
//
//    public function removeVideoBanner(VideoBanner $videoBanner): NestedBanner
//    {
//        $this->videoBanners->removeElement($videoBanner);
//
//        return $this;
//    }
//
//    public function removePromoBlockBanner(PromoBlockBanner $promoBlockBanner): NestedBanner
//    {
//        $this->promoBlockBanners->removeElement($promoBlockBanner);
//
//        return $this;
//    }
    
    public function remove($param){
        dd($param);
    }
}




<?php

namespace App\Cms\Entity\Banner;

use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\HttpFoundation\File\File;
use Doctrine\ORM\Mapping as ORM;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use App\Cms\Entity\Banner\NestedBanner;

/**
 * 
 * @ORM\Entity(repositoryClass="App\Cms\Repository\Banner\BannerRepository")
 * @ORM\Table(name="banner")
 * @Vich\Uploadable()
 */
class Banner {

    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(name="title", type="string", length=255)
     */
    private $title;

    /**
     * @var File
     * @Vich\UploadableField(mapping="banner_background_image", fileNameProperty="backgroundImageName")
     * @Assert\Image(
     *     mimeTypes = {"image/jpeg", "image/png", "image/svg+xml"},
     *     mimeTypesMessage = "Дозволені тільки формати (jpg,png,svg)",
     *     maxSize = "2M",
     *     maxSizeMessage = "Максимальний розмір 2Mb"
     * )
     */
    private $backgroundImage;
    
    /**
     * @var string
     * @ORM\Column(type="string", nullable=true)
     */
    private $backgroundImageName;

    /**
     * @ORM\Column(name="link", type="string", length=255)
     */
    private $link;

    
    /**
     * @var $nestedBanner
     *
     * @ORM\ManyToOne(
     *     targetEntity="App\Cms\Entity\Banner\NestedBanner",
     *     inversedBy="banners")
     * 
     */
    private $nestedBanner;

    public function __construct() 
    {
    }

    /**
     * 
     * @return type
     */
    public function getId() 
    {
        return $this->id;
    }

    /**
     * 
     * @return type
     */
    public function getTitle(): ?string
    {
        return $this->title;
    }

    /**
     * 
     * @return type
     */
    public function getName(): ?string
    {
        return $this->getBackgroundImageName();
    }

    /**
     * 
     * @return type
     */
    public function getBackgroundImage(): ?File
    {
        return $this->backgroundImage;
    }

    /**
     * 
     * @return type
     */
    public function getBackgroundImageName() 
    {
        return $this->backgroundImageName;
    }

    /**
     * 
     * @return type
     */
    public function getLink() 
    {
        return $this->link;
    }
    
    /**
     * 
     * @return array
     */
    public function getNestedBanner(): ?NestedBanner 
    {
        return $this->nestedBanner;
    }

        /**
     * 
     * @param type $id
     */
    public function setId(int $id) 
    {
        $this->id = $id;
    }

    /**
     * 
     * @param string $title
     */
    public function setTitle(string $title) 
    {
        $this->title = $title;
    }

    /**
     * 
     * @param string $backgroundImage
     */
    public function setBackgroundImage(File $backgroundImage) 
    {
        $this->backgroundImage = $backgroundImage;
        if(!$this->backgroundImageName){
            $this->backgroundImageName = $backgroundImage->getClientOriginalName();
        }
    }

    /**
     * 
     * @param string $backgroundImageName
     */
    public function setBackgroundImageName($backgroundImageName) 
    {
        $this->backgroundImageName = $backgroundImageName;
    }

    /**
     * 
     * @param string $link
     */
    public function setLink(string $link) 
    {
        $this->link = $link;
    }

    /**
     * 
     * @param NestedBanner $nestedBanner
     */
    public function setNestedBanner(NestedBanner $nestedBanner) 
    {
        $this->nestedBanner = $nestedBanner;

        return $this;
    }

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

Consider taking a look at sonata's saving hooks .

It looks like you're already using the preUpdate() function and could utilize the preRemove() function to achieve what you are looking for.

You'll also likely have to remove onDelete="CASCADE" from your entity.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM