Symfony 4 - 用json提交的复杂形式

时间:2018-05-09 18:59:48

标签: json forms symfony

我尝试使用嵌套实体构建表单。

SRC /实体/公司

/**
* @ORM\ManyToOne(targetEntity="App\Entity\CompanyAddress", inversedBy="company")
* @Serializer\Groups({"company"})
*/
private $addresses;

/**
* @ORM\OneToOne(targetEntity="App\Entity\CompanyAddress")
* @ORM\JoinColumn(name="main_address")
*
* @Assert\NotBlank()
* @Serializer\Groups({"company"})
*/
private $mainAddress;

/**
 * @ORM\ManyToOne(targetEntity="App\Entity\User")
 * @ORM\JoinColumn(name="owner", onDelete="SET NULL", nullable=true)
 * @Serializer\Groups({"company"})
 *
 */
private $owner;

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

/**
 * @return array
 */
public function getAddresses()
{
    return $this->addresses->toArray();
}

/**
 * @param $addresses
 * @return Company
 */
public function setAddresses($addresses): self
{
    $this->addresses = $addresses;
}

/**
 * @param CompanyAddress $address
 * @return Company
 */
public function addAddress(CompanyAddress $address): self
{
    if ($this->addresses->contains($address)) return $this;

    $this->addresses->add($address);

    return $this;
}

/**
 * @param CompanyAddress $address
 * @return Company
 */
public function removeAddress(CompanyAddress $address): self
{
    if ($this->addresses->contains($address)) {
        $this->addresses->removeElement($address);
//          $address->setCompany(null);
    }


    return $this;
}

/**
 * @return mixed
 */
public function getMainAddress()
{
    return $this->mainAddress;
}

/**
 * @param CompanyAddress $address
 * @return Company
 */
public function setMainAddress(?CompanyAddress $address): self
{
    $this->mainAddress = $address;
    return $this;
}
/**
 * @return User
 */
public function getOwner(): ?User
{
    return $this->owner;
}

/**
 * @param User|null $owner
 * @return Company
 */
public function setOwner(?User $owner): self
{
    $this->owner = $owner;

    return $this;
}
// and other entity code

SRC /实体/ CompanyAddress.php

/**
* @ORM\OneToMany(targetEntity="App\Entity\Company", mappedBy="addresses", orphanRemoval=true)
*/
private $company;

/**
 * @return Company
 */
public function getCompany(): Company
{
return $this->company;
}

/**
 * @param Company $company
 * @return CompanyAddress
 */
public function setCompany(?Company $company): self
{
$this->company = $company;

return $this;
}
// some other code

现在我建立Form 的 SRC /形式/ CompanyType.php

public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
    ->add('name')
    ->add('shortName')
    ->add('nip')
    ->add('regon')
    ->add('description')
    ->add('addresses', CollectionType::class, ['entry_type' => CompanyAddressType::class, 'allow_add' => true])
    ->add('mainAddress', CompanyAddressType::class)
    ->add('accountants', CollectionType::class, ['entry_type' => CompanyAccountantType::class, 'allow_add' => true])
    ->add('owner', UserCompanyType::class, ['empty_data' => null])
;
}

public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
    'data_class' => Company::class,
]);
}

SRC /形式/ CompanyAddressType.php

public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
    ->add('country')
    ->add('city')
    ->add('street')
    ->add('house')
;
}

public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
    'data_class' => CompanyAddress::class,
]);
}

SRC /控制器/ CompanyController.php

public function new(Request $request, CompanyService $cs)
{
    // $this->denyAccessUnlessGranted('new');ump($request->getContent());

    $company = new Company();

    $form = $this->createForm(CompanyType::class, $company);
    $form->submit(json_decode($request->getContent(), true));

    if (!$form->isValid()) {
        return $this->json([
            'message' => 'Data validation error',
            'errors' => $this->normalizeFormErrors($form)
        ], Response::HTTP_UNPROCESSABLE_ENTITY);
    }

    try {
        $company = $cs->addCompany($company);
    } catch (\Exception $e) {
        return JsonResponse::create(['error' => $e->getMessage()], 406);
    }

    return JsonResponse::fromJsonString($cs->getSerializer()->serialize($company, ['id', 'company']));
}

和服务 src / Services / CompanyService.php

public function addCompany(Company $company)
{
    if ($this->companyRepository->findOneByNipOrRegon(['nip' => $company->getNip(), 'regon' => $company->getRegon()]))
        throw new \Exception($this->translator->trans('Company with given NIP or REGON exists'));

    try {

        $this->em->persist($company);
        $this->em->flush();

    } catch (\Exception $e) {
        throw new \Exception($e->getMessage());
    }

    return $company;
}

现在我正在发送json数据

{
    "name":"Long Company Name",
    "shortName":"Short Name",
    "nip":"8888888",
    "regon":"1111111",
    "description":"Description",
    "addresses": [ {
        "city":"First City",
        "street":"No street Name",
        "house":"44",
        "country":"Country"
    }, {
        "country":"Country",
        "city":"Another City",
        "street":"",
        "house":"11"
    }],
    "mainAddress": {
        "country":"Main Country",
        "city":"Main City",
        "street":"Main Street",
        "house":"1"
    },
    "accountants": [],
    "owner": {
        "id":1
    }
}

我收到错误"Expected value of type \"App\\Entity\\CompanyAddress\" for association field \"App\\Entity\\Company#$addresses\", got \"Doctrine\\Common\\Collections\\ArrayCollection\" instead."

当我发送空的地址数组并发送id作为所有者时,我公司的所有者为空:/不是从数据库获取:/当我删除选项“empty_data”时,我收到错误"Could not determine access type for property "id" in class "App\Entity\User"

我想在添加公司时添加来自实体Comapany的地址,我也想从公司实体中删除地址。

如何从该表单创建实体?或者我应该向公司实体添加哪些功能?

1 个答案:

答案 0 :(得分:2)

见这里:

/**
* @ORM\ManyToOne(targetEntity="App\Entity\CompanyAddress", inversedBy="company")
* @Serializer\Groups({"company"})
*/
private $addresses;

您的属性设置为ManyToOne,这意味着在这种情况下它需要一个CompanyAddress实例。然而,您正在为其提供一系列CompanyAddress项目。

我认为这种关系应该是OneToMany(一家公司可以有多个地址)或ManyToMany(一家公司可以有多个地址,可以与其他公司共享)

如果您不熟悉ManyToMany关系,那么应该进行一些教程搜索。