zfcampus / zf-apigility-doctrine

Doctrine-enabled services for Apigility
BSD 3-Clause "New" or "Revised" License
107 stars 51 forks source link

Inserting a new Resource in a Many2Many Relationship #301

Closed FilipeVoges closed 5 years ago

FilipeVoges commented 7 years ago

Good Morning,

I am creating an api in Apigility and am using Doctrine as the database adapter.

In simple entities or Many2One I was able to do the insertion of the records without major problems, but now I have a problem in a Many2Many relationship.

The relationship in question would be between customers and vehicles, in case a customer may have multiple vehicles and one vehicle may have multiple customers as well

My entities are like this:

ClienteEntity.php

/**
 * ClientesEntity
 *
 * @ORM\Table(name="clientes", indexes={@ORM\Index(name="flag_oculto", columns={"flag_oculto"})})
 * @ORM\Entity
 */
class ClientesEntity extends GenericEntity
{
    /**
     * @var integer
     *
     * @ORM\Column(name="codigo", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    protected $codigo;

    /**
     * @var boolean
     *
     * @ORM\Column(name="flag_oculto", type="boolean", nullable=false)
     */
    protected $flagOculto = '0';

    /**
     * @var \Doctrine\Common\Collections\Collection
     *
     * @ORM\ManyToMany(targetEntity="VeiculosEntity", inversedBy="codigoCliente")
     * @ORM\JoinTable(name="clientes_veiculos",
     *   joinColumns={
     *     @ORM\JoinColumn(name="codigo_cliente", referencedColumnName="codigo")
     *   },
     *   inverseJoinColumns={
     *     @ORM\JoinColumn(name="codigo_veiculo", referencedColumnName="codigo")
     *   }
     * )
     */
    protected $codigoVeiculo;
}

VeiculosEntity.php

/**
 * VeiculosEntity
 *
 * @ORM\Table(name="veiculos")
 * @ORM\Entity
 */
class VeiculosEntity extends GenericEntity
{
    /**
     * @var integer
     *
     * @ORM\Column(name="codigo", type="integer", nullable=false)
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    protected $codigo;

    /**
     * @var \Doctrine\Common\Collections\Collection
     *
     * @ORM\ManyToMany(targetEntity="ClientesEntity", mappedBy="codigoVeiculo")
     */
    protected $codigoCliente;
}

And in case the service that is doing the registration is the one of vehicles, therefore I will only register a new vehicle for the client and not a new client.

And so my Resource is like this:

VeiculosResource.php

class VeiculosResource extends AbstractResourceListener
{
    /**
     * \GenericResource
     */
    protected $res;

    /**
     * \EntityManager
     */
    protected $em;

    /**
     * Construct class
     *
     * @param $em | EntityManager
     */
    public function __construct($em) {
        $this->em = $em;
        $this->res = new GenericResource('Oficina\V1\Entity\VeiculosEntity', $em);
    }

    /**
     * Create a resource
     *
     * @param  mixed $data
     * @return ApiProblem|mixed
     */
    public function create($data)
    {
        $data = (array) $data;
        $resource = new VeiculosEntity($data);
        $this->res->persist($resource);
        $entityArray = $this->res->objectToArray($resource);

        return new VeiculosCollection($entityArray);
    }
}

And the method persist in the generic resource is thus:

/**
     * Outsourced function of the same role of the Entity manager
     *
     * @param $entity | Object
     * @see Doctrine\ORM\EntityManager;
     */
    public function persist($entity){
        $this->em->persist($entity);
        $this->em->flush();
    }

I'm passing the following JSON in postman as test

{
    "codigoVeiculo" : 1,
    "chassi" : 0,
    "codigoFabricante" : 1,
    "codigoModelo" : 0,
    "anoFabricacao" : 2017,
    "anoModelo" : 2018,
    "codfuncCadastro" : 0,
    "codigoCliente": 39708
}

*Other Vehicle Attributes (unrelated)

After execution the insertion is occurring only in the table of 'veiculos' and not in the intermediary table 'clientes_veiculos'

And as I see there is no error in the code, maybe not json I am sending

TomHAnderson commented 7 years ago

To add many to many entries a very good solution is to create a RPC (which you can add code to).

Don't modify the resource to do more work than it does already.