Symfony很多人都没有更新双方

时间:2018-03-28 03:57:47

标签: php symfony doctrine many-to-many

我正在使用Symfony 3.3创建资产管理Web应用程序。

我有两个实体,资产和用户。

用户:     

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use FOS\UserBundle\Model\User as BaseUser;

/**
 * User
 *
 * @ORM\Table(name="user")
 * @ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository")
 */
class User extends BaseUser
{
    /**
     * @ORM\ManyToMany(targetEntity="Asset", mappedBy="users")
     */
    private $assets;

    /**
     * Add asset
     *
     * @param \AppBundle\Entity\Asset $asset
     *
     * @return User
     */
    public function addAsset(\AppBundle\Entity\Asset $asset)
    {
        $this->assets[] = $asset;

        return $this;
    }

    /**
     * Remove asset
     *
     * @param \AppBundle\Entity\Asset $asset
     */
    public function removeAsset(\AppBundle\Entity\Asset $asset)
    {
        $this->assets->removeElement($asset);
    }

    /**
     * Get assets
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getAssets()
    {
        return $this->assets;
    }
}

资产:     

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * Asset
 *
 * @ORM\Table(name="asset")
 * @ORM\Entity(repositoryClass="AppBundle\Repository\AssetRepository")
 */
class Asset
{
    /**
     * @ORM\ManyToMany(targetEntity="User", inversedBy="assets")
     * @ORM\JoinTable(name="asset_user")
     */
    private $users;

    /**
     * Add user
     *
     * @param \AppBundle\Entity\User $user
     *
     * @return Asset
     */
    public function addUser(\AppBundle\Entity\User $user)
    {
        $this->users[] = $user;
        return $this;
    }

    /**
     * Remove user
     *
     * @param \AppBundle\Entity\User $user
     */
    public function removeUser(\AppBundle\Entity\User $user)
    {
        $this->users->removeElement($user);
    }

    /**
     * Get users
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getUsers()
    {
        return $this->users;
    }
}

他们有多对多的关系。如果我在资产中添加用户,一切都很好,但如果我在用户中添加资产。它不会坚持下去。

添加我的表单类型:

AssetUserAssignType:     

namespace AppBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;


class AssetUserAssignType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('users', CollectionType::class, array(
                    'label' => 'Custodians',
                    'entry_type' => EntityType::class,
                    'entry_options' => array(   'class'=>'AppBundle:User',
                                                'label'=>false,
                                                'choice_label'=>'employee_number',
                                                ),
                    'allow_delete' =>true,
                    'allow_add' => true,
                    'allow_delete' => true,
                    'prototype' => true,
                    'by_reference' => false,
                    'attr'=> array('class'=>'user_collection'),
                ));
    }

    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\Asset'
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getBlockPrefix()
    {
        return 'appbundle_assetassign';
    }


}

UserAssetAssignType:
    

namespace AppBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;


class UserAssetAssignType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('assets', CollectionType::class, array(
                    'label' => 'Assets',
                    'entry_type' => EntityType::class,
                    'entry_options' => array(   'class'=>'AppBundle:Asset',
                                                'label'=>false,
                                                'choice_label'=>'code',
                                                ),
                    'allow_delete' =>true,
                    'allow_add' => true,
                    'allow_delete' => true,
                    'prototype' => true,
                    'by_reference' => false,
                    'attr'=> array('class'=>'asset_collection'),
                ));
    }

    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\User'
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getBlockPrefix()
    {
        return 'appbundle_assetassign';
    }


}

如果您需要更多代码,我也会将它们粘贴到此处,但我认为这已经足够了。

2 个答案:

答案 0 :(得分:2)

这是因为在Doctrine关系中,拥有方(定义列名和inversedBy属性的实体)始终优先于inverse side(另一个)。

正如文档中所述:http://symfony.com/doc/current/doctrine/associations.html#setting-information-from-the-inverse-side一个好的做法是更新默认的setter(包括添加和删除函数),以确保两个实体始终同步。

例如:

public function addAsset(\AppBundle\Entity\Asset $asset)
{
    $this->assets[] = $asset;
    $asset->addUser($this);

    return $this;
}

public function removeAsset(\AppBundle\Entity\Asset $asset)
{
    $this->assets[] = $asset;
    $asset->removeUser($this);

    return $this;
}

由于您已经在表单中设置了by_referencefalse(需要确保由表单组件调用setter),所以它可以解决问题。

希望它会有所帮助。

答案 1 :(得分:1)

您还没有正确实现数据库,如果关系是多对多,则应该有一个关联实体,因此在User和Asset中必须有一个名为UserAsset的实体。然后用户有许多UserAsset,如果你得到一个UserAsset,那么该记录只有一个用户。一个资产可以在许多UserAsset记录中,如果您获得一个UserAsset记录,则只有一个资产应该与该记录相关联。