Editing manytomany association doctrine2 and zf2

1k Views Asked by At

I have a scenario like this: Hmo has a bidirectional Many2Many association with Hcp. What i mean is Hmo can add Hcp, Hcp should be able to view its Hmos and view some other information about an Hmo.

I have already created several Hmos and Hcps so the actual association is when editing Hmos in order to select Hcps to make association i kept getting an error:

Argument 1 passed to Hmo\Entity\Hmos::addHcp() must be an instance of Hcp\Entity\Hcps, instance of Doctrine\Common\Collections\ArrayCollection given, called in /var/www/insta/vendor/doctrine/doctrine-module/src/DoctrineModule/Stdlib/Hydrator/Strategy/AllowRemoveByValue.php on line 61 and defined in /var/www/insta/module/Hmo/src/Hmo/Entity/Hmos.php on line 58

Hcps.php

<?php
namespace Hcp\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Hmo\Entity\Hmos;

/** @ORM\Entity */
class Hcps
{
    /**
    * @ORM\Id
    * @ORM\GeneratedValue(strategy="AUTO")
    * @ORM\Column(type="integer")
    */
    protected $id;
    /** @ORM\Column(type="string") */
    protected $name;                        
    /** @ORM\Column(type="string") */
    protected $address;
    /** @ORM\Column(type="string") */
    protected $telno;
    /** @ORM\Column(type="string") */
    protected $email;
    /** @ORM\Column(type="string") */
    protected $typeoffac;
    /** @ORM\Column(type="string") */
    protected $catofreg;
    /** @ORM\Column(type="string") */
    protected $sregno;
    /** @ORM\Column(type="string") */
    protected $directorname;
    /** @ORM\Column(type="date", nullable=true) */
    protected $regdate;
    /** @ORM\Column(type="time", nullable=true) */
    protected $regtime;
    /** @ORM\Column(type="datetime", nullable=true) */
    protected $regdatetime;
    /** @ORM\Column(type="datetime", nullable=true) */
    protected $lastlogin;
    /**
        *@var \Doctrine\Common\Collections\ArrayCollection
        * @ORM\ManyToMany(targetEntity="Hmo\Entity\Hmos", mappedBy="hcp")
    */

    protected $hmo;


    public function __constructor()
    {
        $this->hmo = new ArrayCollection();
    }


    public function addHmo(Hmos $hmo)
    {
        if ($this->hmo->contains($hmo)) {
            return;
        }

        $this->hmo->add($hmo);
        $hmo->addHcp($this);
    }


    public function setHmo(Hmos $hmo = null)
    {
        $this->hmo = $hmo;
    }


    public function getHmo()
    {
        return $this->hmo;
    }    



    public function setLastlogin($lastlogin)
    {
        $this->lastlogin = $lastlogin;
        return $this;
    }

    public function getLastlogin()
    {
        return $this->lastlogin;
    }

    public function setRegDatetime($regdatetime)
    {
        $this->regdatetime = $regdatetime;
        return $this;
    }

    public function getRegdatetime()
    {
        return $this->regdatetime;
    }


    public function setRegtime($regtime)
    {
        $this->regtime = $regtime;
        return $this;
    }

    public function getRegtime()
    {
        return $this->regtime;
    }

    public function setRegdate($regdate)
    {
        $this->regdate = $regdate;
        return $this;
    }

    public function getRegdate()
    {
        return $this->regdate;
    }


    public function setId($id)
    {
        $this->id = $id;
        return $this;
    }

    public function getId()
    {
        return $this->id;
    }

    public function setDirectorname($directorname)
    {
        $this->directorname = $directorname;
        return $this;
    }

    public function getDirectorname()
    {
        return $this->directorname;
    }

    public function setSregno($sregno)
    {
        $this->sregno = $sregno;
        return $this;
    }

    public function getSregno()
    {
        return $this->sregno;
    }

    public function setCatofreg($cof)
    {
        $this->catofreg = cof;
        return $this;
    }

    public function getCatofreg()
    {
        return $this->catofreg;
    }

    public function setTypeoffac($tof)
    {
        $this->typeoffac = $tof;
        return $this;
    }

    public function getTypeoffac()
    {
        return $this->typeoffac;
    }

    public function setTelno($telno)
    {
        $this->telno = $telno;
        return $this;
    }

    public function getTelno()
    {
        return $this->telno;
    }

    public function setAddress($address)
    {
        $this->address = $address;
        return $this;
    }

    public function getAddress()
    {
        return $this->address;
    }

    public function setName($name)
    {
        $this->name = $name;
        return $name;
    }

    public function getName()
    {
        return $this->name;
    }

    public function setEmail($email)
    {
        $this->email = $email;
        return $email;
    }

    public function getEmail()
    {
        return $this->email;
    }

    public function populate($data = array()) 
    {
        $this->id = $data['id'];
        $this->name = $data['name'];
        $this->address = $data['address'];
        $this->telno = $data['telno'];
        $this->email = $data['email'];
        $this->typeoffac = $data['typeoffac'];
        $this->catofreg = $data['catofreg'];
        $this->sregno = $data['sregno'];
        $this->directorname = $data['directorname'];
    }



}

Hmos.php

<?php
namespace Hmo\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;

use Hcp\Entity\Hcps;
/** @ORM\Entity */
class Hmos 
{
    /**
    * @ORM\Id
    * @ORM\GeneratedValue(strategy="AUTO")
    * @ORM\Column(type="integer")
    */

    protected $id;
    /** @ORM\Column(type="string") */ 
    protected $nameofhmo;
    /** @ORM\Column(type="string") */
    protected $headoffice;
    /** @ORM\Column(type="string") */
    protected $telno;
    /** @ORM\Column(type="string") */
    protected $email;
    /** @ORM\Column(type="string") */
    protected $doincor;
    /** @ORM\Column(type="string") */
    protected $rcno;
    /** @ORM\Column(type="string") */
    protected $ceoname;
    /** @ORM\Column(type="string") */
    protected $bankers;
    /** @ORM\Column(type="date", nullable=true) */
    protected $regdate;
    /** @ORM\Column(type="time", nullable=true) */
    protected $regtime;
    /** @ORM\Column(type="datetime", nullable=true) */
    protected $regdatetime;
    /** @ORM\Column(type="datetime", nullable=true) */
    protected $lastlogin;

        /**
        * @ORM\ManyToMany(targetEntity="Hcp\Entity\Hcps", inversedBy="hmo")
        * @ORM\JoinTable(name="hmo_hcp",
        *               joinColumns={@ORM\JoinColumn(name="hmo_id", referencedColumnName="id")},
        *               inverseJoinColumns={@ORM\JoinColumn(name="hcp_id", referencedColumnName="id")}
        *          )
    */

    protected $hcp;

   public function __constructor()
    {
        $this->hcp = new ArrayCollection();
    }

    public function addHcp(Hcps $hcp)
    {
    //    $hcp->addHmo($this); // synchronously updating inverse side
        //$this->hcp[] = $hcp;
        // $this->hcp->add($hcp);
        //return $this->hcp;
         if ($this->hcp->contains($hcp)) {
            return;
        }

        $this->hcp->add($hcp);
        $hcp->addHmo($this);
    }

    public function removeHcp(Hcps $hcp)
    {
        $this->hcp->removeElement($hcp);
        return $this;
    }


    public function setNameofhmo($hmo)
    {
        $this->nameofhmo = $hmo;
        return $this;
    }

    public function getNameofhmo()
    {
        return $this->nameofhmo;
    }

    public function setHeadoffice($headoffice)
    {
        $this->headoffice = $headoffice;
        return $this;
    }

    public function getHeadoffice()
    {
        return $this->headoffice;
    }

    public function setTelno($telno)
    {
        $this->telno = $telno;
        return $this;
    }

    public function getTelno()
    {
        return $this->telno;
    }

    public function setEmail($email)
    {
        $this->email = $email;
        return $this;
    }

    public function getEmail()
    {
        return $this->email;
    }

    public function setDoincor($doincor)
    {
        $this->doincor = $doincor;
        return $this;
    }

    public function getDoincor()
    {
        return $this->doincor;
    }

    public function setRcno($rc)
    {
        $this->rcno = $rc;
        return $this;
    }

    public function getRcno()
    {
        return $this->rcno;
    }

    public function setCeoname($ceo)
    {
        $this->ceoname = $ceo;
        return $this;
    }

    public function getCeoname()
    {
        return $this->ceoname;
    }

    public function setBankers($bk)
    {
        $this->bankers = $bk;
        return $this;
    }

    public function getBankers()
    {
        return $this->bankers;
    }

    public function setLastlogin($lastlogin)
    {
        $this->lastlogin = $lastlogin;
        return $this;
    }

    public function getLastlogin()
    {
        return $this->lastlogin;
    }

    public function setRegDatetime($regdatetime)
    {
        $this->regdatetime = $regdatetime;
        return $this;
    }

    public function getRegdatetime()
    {
        return $this->regdatetime;
    }


    public function setRegtime($regtime)
    {
        $this->regtime = $regtime;
        return $this;
    }

    public function getRegtime()
    {
        return $this->regtime;
    }

    public function setRegdate($regdate)
    {
        $this->regdate = $regdate;
        return $this;
    }

    public function getRegdate()
    {
        return $this->regdate;
    }


    public function setId($id)
    {
        $this->id = $id;
        return $this;
        //die();
    }

    public function getId()
    {
        return $this->id;
    }

    public function populate($data = array()) 
    {
        $this->id = $data['id'];
        $this->nameofhmo = $data['nameofhmo'];
        $this->headoffice = $data['headoffice'];
        $this->telno = $data['telno'];
        $this->email = $data['email'];
        $this->doincor = $data['doincor'];
        $this->rcno = $data['rcno'];
        $this->ceoname = $data['ceoname'];
        $this->bankers = $data['bankers'];
    }




 public function setHcp(Hcps $hcp = null)
    {
       //Hmos $hmo = null
                $this->hcp = $hcp;
       return $this;
    }

    public function getHcp()
    {
        return $this->hcp;
    }    


}

HmohcpForm.php

class HmohcpForm extends Form{
    public function __construct(ObjectManager $objectManager){
        parent::__construct('filmForm');

        $this->setAttribute('method','post')
             ->setHydrator(new DoctrineHydrator($objectManager,'\Hmo\Entity\Hmos'))
             ->setObject(new Hmos());
       $this->add(array(
            'name' => 'id',
            'type' => 'hidden'
        )); 

        $this->add(
            array(
            'type' => 'DoctrineModule\Form\Element\ObjectSelect',
                'name' => 'hcp',
                'attributes' => array(
                'multiple' => 'multiple',
                'class'=>'form-control',

                ),                
                'options' => array(
                    'object_manager' => $objectManager,
                    'target_class'   => 'HCP\Entity\Hcps',
                    'property'       => 'name',
                    'label'          => 'HCP: ',
                ),
            )
        );                      

        $this->add(array(
            'name' => 'submit',
            'attributes' => array(
                'type'  => 'submit',
                'value' => 'Add HCPs to HMO',
                'id' => 'submitbutton',
                'class' => 'btn btn-primary',

            ),
        ));

}

hcptohmo.php

<?php
    $form = $this->form;
    $form->prepare();
    $form->setAttribute('action', $this->url(NULL,
    array('controller'=>'Index', 'action' => 'hcptohmos','id'=> $this->id)));
    $form->setAttribute('method', 'post');
?>
<?php //echo $?>
 <div class="row">
                        <article class="contact-form col-md-8 col-sm-7  page-row">                            
                            <h3 class="title">Register HMO</h3>
                              <?php     echo $this->form()->openTag($form); ?>
                                <?php echo $this->formInput($form->get('id')); ?>


  <div class="form-group name">
                                   <?php
        echo $this->formElement($form->get('hcp'));
        ?>
                                </div><!--//form-group-->

<?php
        echo $this->formElement($form->get('submit'));
        echo $this->formElementErrors($form->get('submit'));
        ?>
                            <?php echo $this->form()->closeTag() ?>                  
                        </article><!--//contact-form-->
</div>

IndexController.php

<?php
    public function hcptohmoAction()
    {
    $id = $this->params()->fromRoute('id');
    if(!$id) {
            return $this->redirect()->toRoute('admin', array(
                'action' => 'index'
            ));
    }

    $hu= $this->getEntityManager()->find('Hmo\Entity\Hmos',$id);

    $form = new HmohcpForm($this->getEntityManager());
    $form->bind($hu);
    $request = $this->getRequest();
    if ($request->isPost()) {

        $form->setData($request->getPost());
        if ($form->isValid())
        {
             $form->bindValues();
            $entity = $form->getData();
            print_r($entity->getHcp());

        }
    }
    return new ViewModel(array('id'=>$id,'form' => $form));

    }

I thought print_r($entity->getHcp()) is supposed to return an object of selected Hcps? i have toggled the parameter of addHcp() to an arraycollection and Hcps but still shooting same error. is something wrong with this codes pls?

2

There are 2 best solutions below

2
On BEST ANSWER

you should pass an ArrayCollection to the add-methods - I think that is the problem. Modify your add-methods to look like this:

public function addHcp(Collection $hcps)
{
    foreach($hcps as $hcp) {
        if( ! $this->hcp->contains($hcp)) {
            $this->hcp->add($hcp);
            $hcp->addHmo(new ArrayCollection(array($this));
        }
    }
}

Also your remove-methods (the same way):

public function removeHcp(Collection $hcps) 
{
    foreach($hcps as $hcp) {
        $this->hcp->removeElement($hcp);
        $hcp->removeHmo(new ArrayCollection(array(this)));
    }
}

Doctrine also passes Collections to the add-/remove-methods, that's why it is not working

1
On

I think the problem lies in your entity methods.

I would advice to read the documentation on the Doctrine ObjectHydrator and then you will most likely find out what goes wrong. From a quick look I would say the mistake is in the setHcp and setHmo methods. Since you have a ManyToMany association you are not supposed to use set methods in your associations at all. Check the comment at setTags here in this chapter of the documentation. You should actually only use addHcps, addHcp, removeHcp and removeHcps methods.

Collections should never be swapped.