Symfony2集合表单类型 - 不保存新记录

时间:2015-01-14 16:15:08

标签: forms symfony persistence entity-relationship

我已经在我的应用程序中实现了'集合'表单类型,它工作得很好,包括删除从提交的数据中删除的相关记录,但是为了保存任何新添加的链接记录,我必须手动循环遍历链接实体&将所有者设置为正在编辑的实体。我确定它应该自动完成,所以我错过了什么?

你会看到......

/*****************************************************************
 * This is the bit I've had to add to persist the new entries!!! *
 *****************************************************************

...我必须手动链接AppController文件中的实体。

文件

App Entity

<?php

namespace ...\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * App
 *
 * @ORM\Table()
 * @ORM\Entity()
 */
class App
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    // ...

    /**
     * @var AppAppStoreData[]|ArrayCollection
     *
     * We use orphan removal here to remove the link data when deleting an app
     * @ORM\OneToMany(targetEntity="AppAppStoreData", mappedBy="app", cascade={"all"}, orphanRemoval=TRUE)
     */
    private $appAppStoreData;

    // ...

    /**
     * @return ArrayCollection|AppAppStoreData[]
     */
    public function getAppAppStoreData()
    {
        return $this->appAppStoreData;
    }

    /**
     * @param ArrayCollection|AppAppStoreData[] $appAppStoreData
     *
     * @return $this
     */
    public function setAppAppStoreData( $appAppStoreData )
    {
        $this->appAppStoreData = $appAppStoreData;

        return $this;
    }
}

AppStore实体

<?php

namespace ...\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;

/**
 * AppStore
 *
 * @ORM\Table()
 * @ORM\Entity()
 */
class AppStore
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    // ...

    /**
     * @var AppAppStoreData[]|ArrayCollection
     *
     * We use orphan removal here to remove the link data when deleting an app
     * @ORM\OneToMany(targetEntity="AppAppStoreData", mappedBy="appStore", cascade={"all"}, orphanRemoval=TRUE)
     */
    private $appAppStoreData;


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

    // ...

    /**
     * @return AppAppStoreData[]|ArrayCollection
     */
    public function getAppAppStoreData()
    {
        return $this->appAppStoreData;
    }

    /**
     * @param AppAppStoreData[]|ArrayCollection $appAppStoreData
     *
     * @return $this
     */
    public function setAppAppStoreData( $appAppStoreData )
    {
        $this->appAppStoreData = $appAppStoreData;

        return $this;
    }
}

AppAppStoreData实体

<?php

namespace ...\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * AppAppStoreData
 *
 * @ORM\Table()
 * @ORM\Entity()
 */
class AppAppStoreData
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var App
     *
     * @ORM\ManyToOne(targetEntity="App", inversedBy="appAppStoreData")
     * @ORM\JoinColumn(name="app_id", referencedColumnName="id")
     */
    private $app;

    /**
     * @var AppStore
     *
     * @ORM\ManyToOne(targetEntity="AppStore", inversedBy="appAppStoreData")
     * @ORM\JoinColumn(name="app_store_id", referencedColumnName="id")
     */
    private $appStore;

    /**
     * @var string
     *
     * @ORM\Column(name="app_store_uri", type="string", length=1083)
     */
    private $appUri;


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

    /**
     * Set app
     *
     * @param App $app
     *
     * @return AppAppStoreData
     */
    public function setApp(App $app)
    {
        $this->app = $app;

        return $this;
    }

    /**
     * Get app
     *
     * @return App
     */
    public function getApp()
    {
        return $this->app;
    }

    /**
     * Set appStore
     *
     * @param AppStore $appStore
     *
     * @return AppAppStoreData
     */
    public function setAppStore(AppStore $appStore)
    {
        $this->appStore = $appStore;

        return $this;
    }

    /**
     * Get appStore
     *
     * @return AppStore
     */
    public function getAppStore()
    {
        return $this->appStore;
    }

    /**
     * Set appStoreLink
     *
     * @param string $appUri
     *
     * @return AppAppStoreData
     */
    public function setAppUri( $appUri)
    {
        $this->appUri = $appUri;

        return $this;
    }

    /**
     * Get appStoreLink
     *
     * @return string
     */
    public function getAppUri()
    {
        return $this->appUri;
    }
}

AppType表格

<?php

namespace ...\Form\Type;


use ...\Entity\App;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class AppType extends AbstractType
{
    /**
     * Builds the App admin edit form
     *
     * @param FormBuilderInterface $builder
     * @param array                $options
     */
    public function buildForm( FormBuilderInterface $builder, array $options )
    {
        $builder
            // ...
            ->add( 'appAppStoreData', 'collection', [
                'type'              => new ,
                'label'             => 'App Store Links',
                'allow_add'         => true,
                'allow_delete'      => true,
                'prototype'         => true,
                'widget_add_btn'    => array( 'label' => "Add App Store Details" ),
                'widget_remove_btn' => array( 'label' => "Remove App Store Details" ),
                'show_legend'       => false, // dont show another legend of subform
                'options'           => array( // options for collection fields
                    'label_render'                   => false,
                    'widget_addon_prepend'           => array(
                        'text' => '@',
                    ),
                    'horizontal_input_wrapper_class' => "col-lg-8",
                ),
            ] );
    }

    /**
     * Sets the Entity data class
     *
     * @param OptionsResolverInterface $resolver
     */
    public function setDefaultOptions( OptionsResolverInterface $resolver )
    {
        $resolver->setDefaults(
            array(
                'data_class' => '...\Entity\App',
            )
        );
    }


    /**
     * Returns the name of this type.
     *
     * @return string The name of this type
     */
    public function getName()
    {
        return 'app';
    }
}

AppAppStoreDataFieldsType

<?php

namespace ...\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class AppAppStoreDataFieldsType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array                $options
     */
    public function buildForm( FormBuilderInterface $builder, array $options )
    {
        $builder
            ->add( 'appStore', 'entity', [
                'class'    => '...Bundle:AppStore',
                'property' => 'name',
                'label'    => 'App Store'
            ] )
            ->add( 'appUri', 'url', [
                'label' => 'App URI'
            ] );
    }

    /**
     * @param OptionsResolverInterface $resolver
     */
    public function setDefaultOptions( OptionsResolverInterface $resolver )
    {
        $resolver->setDefaults( array(
            'data_class' => '...\Entity\AppAppStoreData'
        ) );
    }

    /**
     * @return string
     */
    public function getName()
    {
        return 'app_store_data_fields';
    }
}

App Controller

<?php

namespace ...\Controller;

use ...\Entity\UploadableInterface;
use ...\Exception\RecordNotFoundException;
use ...\Exception\RedirectException;
use ...\Entity\App;
use ...\Entity\AppRepository;
use ...\Entity\ClientRepository;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

class AppController extends ClientAssetController
{
    /**
     * @param Request $request
     * @param null    $id
     *
     * @return Response
     */
    public function editAction( Request $request, $id = null )
    {
        $app = @$this->getAppRepository()->find( $id );

        // ...

        $form = $this->createForm( 'app', $app )
                     ->add( 'save', 'submit', [ 'label' => 'Save' ] );

        $form->handleRequest( $request );

        if ($form->isValid()) {
            $em = $this->getDoctrine()->getManager();
            $em->persist( $app );


            /*****************************************************************
             * This is the bit I've had to add to persist the new entries!!! *
             *****************************************************************
             /
            foreach ($app->getAppAppStoreData() as $appAppStoreDatum) {
                $appAppStoreDatum->setApp( $app );
            }


            $em->flush();

            // ... Redirect
        }

        // ... Render
    }

    // ...
}

1 个答案:

答案 0 :(得分:0)

初始化appAppStoreData

的集合
...

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