Symfony / Doctrine:getJoinTableName()必须是数组类型,给定null

时间:2016-12-21 09:35:38

标签: php orm doctrine-orm symfony

我有两个类,它们之间有ManyToMany关联:

Nursery.php         

namespace VS\CrmBundle\Entity;

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

/**
 * Nursery
 *
 * @ORM\Table(name="Nursery")
 * @ORM\Entity(repositoryClass="VS\CrmBundle\Repository\NurseryRepository")
 */
class Nursery
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

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

    /**
     * @var string
     *
     * @ORM\Column(name="phone_number", type="string", length=15, nullable=true)
     */
    private $phoneNumber;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="created_at", type="datetime")
     */
    private $createdAt;

    /**
     * @var \DateTime
     *
     * @ORM\Column(name="updated_at", type="datetime", nullable=true)
     */
    private $updatedAt;

    /**
     * @var Address
     *
     * @ORM\OneToOne(targetEntity="Address", inversedBy="nursery", cascade={"persist"})
     * @ORM\JoinColumn(name="fk_address_id", referencedColumnName="id")
     */
    private $address;


    /**
     * @var ArrayCollection
     *
     * @ORM\ManyToMany(targetEntity="Staff", mappedBy="nurseries", cascade={"persist"})
     */
    private $staff;

    /**
     * @var ArrayCollection
     *
     * @ORM\OneToMany(targetEntity="Schedule", mappedBy="nursery", cascade={"persist"})
     */
    private $schedule;

    /**
     * @var ArrayCollection
     *
     * @ORM\OneToMany(targetEntity="Contact", mappedBy="nursery", cascade={"persist"})
     */
    private $contacts;

    /**
     * @var ArrayCollection
     *
     * @ORM\OneToMany(targetEntity="RegisterRecord", mappedBy="nursery", cascade={"persist"})
     */
    private $registerRecords;

    /**
     * Nursery constructor.
     */
    public function __construct()
    {
        $this->staff = new ArrayCollection();
        $this->schedule = new ArrayCollection();
        $this->createdAt = new \DateTime();
        $this->contacts = new ArrayCollection();
        $this->registerRecord = new ArrayCollection();
    }

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

    /**
     * Set name
     *
     * @param string $name
     *
     * @return Nursery
     */
    public function setName($name)
    {
        $this->name = $name;

        return $this;
    }

    /**
     * Get name
     *
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * Set phoneNumber
     *
     * @param string $phoneNumber
     *
     * @return Nursery
     */
    public function setPhoneNumber($phoneNumber)
    {
        $this->phoneNumber = $phoneNumber;

        return $this;
    }

    /**
     * Get phoneNumber
     *
     * @return string
     */
    public function getPhoneNumber()
    {
        return $this->phoneNumber;
    }

    /**
     * Set createdAt
     *
     * @param \DateTime $createdAt
     *
     * @return Nursery
     */
    public function setCreatedAt($createdAt)
    {
        $this->createdAt = $createdAt;

        return $this;
    }

    /**
     * Get createdAt
     *
     * @return \DateTime
     */
    public function getCreatedAt()
    {
        return $this->createdAt;
    }

    /**
     * Set updatedAt
     *
     * @param \DateTime $updatedAt
     *
     * @return Nursery
     */
    public function setUpdatedAt($updatedAt)
    {
        $this->updatedAt = $updatedAt;

        return $this;
    }

    /**
     * Get updatedAt
     *
     * @return \DateTime
     */
    public function getUpdatedAt()
    {
        return $this->updatedAt;
    }

    /**
     * Set address
     *
     * @param \VS\CrmBundle\Entity\Address $address
     *
     * @return Nursery
     */
    public function setAddress(\VS\CrmBundle\Entity\Address $address = null)
    {
        $this->address = $address;

        return $this;
    }

    /**
     * Get address
     *
     * @return \VS\CrmBundle\Entity\Address
     */
    public function getAddress()
    {
        return $this->address;
    }

    /**
     * Add staff
     *
     * @param \VS\CrmBundle\Entity\Staff $staff
     *
     * @return Nursery
     */
    public function addStaff(\VS\CrmBundle\Entity\Staff $staff)
    {
        $this->staff[] = $staff;

        return $this;
    }

    /**
     * Remove staff
     *
     * @param \VS\CrmBundle\Entity\Staff $staff
     */
    public function removeStaff(\VS\CrmBundle\Entity\Staff $staff)
    {
        $this->staff->removeElement($staff);
    }

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

    /**
     * Add schedule
     *
     * @param \VS\CrmBundle\Entity\Schedule $schedule
     *
     * @return Nursery
     */
    public function addSchedule(\VS\CrmBundle\Entity\Schedule $schedule)
    {
        $this->schedule[] = $schedule;

        return $this;
    }

    /**
     * Remove schedule
     *
     * @param \VS\CrmBundle\Entity\Schedule $schedule
     */
    public function removeSchedule(\VS\CrmBundle\Entity\Schedule $schedule)
    {
        $this->schedule->removeElement($schedule);
    }

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

    public function __toString()
    {
        $stringDeMalade = $this->getName().' '.$this->getAddress()->getLocality()->getPostalCode().' '.$this->getAddress()->getLocality()->getName();
        return $stringDeMalade;
    }

    /**
     * Add contact
     *
     * @param \VS\CrmBundle\Entity\Contact $contact
     *
     * @return Nursery
     */
    public function addContact(\VS\CrmBundle\Entity\Contact $contact)
    {
        $this->contacts[] = $contact;

        return $this;
    }

    /**
     * Remove contact
     *
     * @param \VS\CrmBundle\Entity\Contact $contact
     */
    public function removeContact(\VS\CrmBundle\Entity\Contact $contact)
    {
        $this->contacts->removeElement($contact);
    }

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

    /**
     * Add registerRecord
     *
     * @param \VS\CrmBundle\Entity\RegisterRecord $registerRecord
     *
     * @return Nursery
     */
    public function addRegisterRecord(\VS\CrmBundle\Entity\RegisterRecord $registerRecord)
    {
        $this->registerRecords[] = $registerRecord;

        return $this;
    }

    /**
     * Remove registerRecord
     *
     * @param \VS\CrmBundle\Entity\RegisterRecord $registerRecord
     */
    public function removeRegisterRecord(\VS\CrmBundle\Entity\RegisterRecord $registerRecord)
    {
        $this->registerRecords->removeElement($registerRecord);
    }

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

Staff.php

<?php

namespace VS\CrmBundle\Entity;

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

/**
 * Staff
 *
 * @ORM\Table(name="staff")
 * @ORM\Entity(repositoryClass="VS\CrmBundle\Repository\StaffRepository")
 */
class Staff extends User
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @var string
     *
     * @ORM\Column(name="staff_role", type="string", length=100)
     */
    private $staffRole;

    /**
     * @var ArrayCollection
     *
     * @ORM\ManyToMany(targetEntity="Nursery", inversedBy="staff", cascade={"persist"})
     * @ORM\JoinTable(name="nursery_staff")
     */
    private $nurseries;

    /**
     * Staff constructor.
     */
    public function __construct()
    {
        parent::__construct();
        $this->nurseries = new ArrayCollection();
    }

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

    /**
     * Set staffRole
     *
     * @param string $staffRole
     *
     * @return Staff
     */
    public function setStaffRole($staffRole)
    {
        $this->staffRole = $staffRole;

        return $this;
    }

    /**
     * Get staffRole
     *
     * @return string
     */
    public function getStaffRole()
    {
        return $this->staffRole;
    }

    /**
     * @param Nursery $nursery
     */
    public function addNurseries(Nursery $nursery)
    {
        $this->nurseries[] = $nursery;
    }

    /**
     * @param Nursery $nursery
     */
    public function removeNurseries(Nursery $nursery)
    {
        $this->nurseries->removeElement($nursery);
    }

    /**
     * @return ArrayCollection
     */
    public function getNurseries()
    {
        return $this->nurseries;
    }
}

然后我想显示一个与托儿所经理(员工role = ROLE_MANAGER)相关的所有托儿所的下拉菜单,所以我有控制器

<?php

namespace VS\CrmBundle\Controller;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use VS\CrmBundle\Entity\Staff;
use VS\CrmBundle\Form\StaffType;

class ManagerController extends Controller
{
    public function dashboardAction($nursery_id)
    {
        $currentUser = $this->get('security.token_storage')->getToken()->getUser();
        $nurseryRepo = $this->getDoctrine()->getRepository('VSCrmBundle:Nursery');

        $nursery = $nurseryRepo->findOneBy(array(
            'id' => $nursery_id,
            'staff' => $currentUser
        ));

        if(!$nursery)
        {
            throw $this->createNotFoundException("The nursery has not been found or you are not allowed to access it.");
        }

        return $this->render("VSCrmBundle:Manager:dashboard.html.twig", array(
            'nursery' => $nursery
        ));
    }
}

我可以在视图中显示我的下拉列表:

    <li class="dropdown">
                        <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dashboards<span class="caret"></span></a>
                        <ul class="dropdown-menu">
                            {% if is_granted('ROLE_MANAGER') %}
                                <li class="dropdown-header">Nurseries</li>
                                {% for nursery in app.user.nurseries %}
                                    <li><a href="{{ path('vs_crm_manager_dashboard', {'nursery_id' : nursery.id}) }}">{{ nursery.name }} dashboard</a></li>
                                {% endfor %}
{% endif %}
    </ul>
    </li>

但是当我点击一个随机的托儿所时,我有错误

  

可捕获致命错误:传递给Doctrine \ ORM \ Mapping \ DefaultQuoteStrategy :: getJoinTableName()的参数1必须是数组类型,给定null,在C:\ wamp64 \ www \ app \ vendor \ doctrine \ orm \中调用第1669行的lib \ Doctrine \ ORM \ Persisters \ Entity \ BasicEntityPersister.php并定义   500内部服务器错误 - ContextErrorException **

日志:

[1] Symfony\Component\Debug\Exception\ContextErrorException: Catchable Fatal Error: Argument 1 passed to Doctrine\ORM\Mapping\DefaultQuoteStrategy::getJoinTableName() must be of the type array, null given, called in C:\wamp64\www\app\vendor\doctrine\orm\lib\Doctrine\ORM\Persisters\Entity\BasicEntityPersister.php on line 1669 and defined
    at n/a
        in C:\wamp64\www\app\vendor\doctrine\orm\lib\Doctrine\ORM\Mapping\DefaultQuoteStrategy.php line 97

    at Symfony\Component\Debug\ErrorHandler->handleError('4096', 'Argument 1 passed to Doctrine\ORM\Mapping\DefaultQuoteStrategy::getJoinTableName() must be of the type array, null given, called in C:\wamp64\www\app\vendor\doctrine\orm\lib\Doctrine\ORM\Persisters\Entity\BasicEntityPersister.php on line 1669 and defined', 'C:\wamp64\www\app\vendor\doctrine\orm\lib\Doctrine\ORM\Mapping\DefaultQuoteStrategy.php', '97', array())
        in C:\wamp64\www\app\vendor\doctrine\orm\lib\Doctrine\ORM\Mapping\DefaultQuoteStrategy.php line 97

    at Doctrine\ORM\Mapping\DefaultQuoteStrategy->getJoinTableName(null, object(ClassMetadata), object(MySQL57Platform))
        in C:\wamp64\www\app\vendor\doctrine\orm\lib\Doctrine\ORM\Persisters\Entity\BasicEntityPersister.php line 1669

    at Doctrine\ORM\Persisters\Entity\BasicEntityPersister->getSelectConditionStatementColumnSQL('staff', null)
        in C:\wamp64\www\app\vendor\doctrine\orm\lib\Doctrine\ORM\Persisters\Entity\BasicEntityPersister.php line 1582

    at Doctrine\ORM\Persisters\Entity\BasicEntityPersister->getSelectConditionStatementSQL('staff', object(Staff), null)
        in C:\wamp64\www\app\vendor\doctrine\orm\lib\Doctrine\ORM\Persisters\Entity\BasicEntityPersister.php line 1724

    at Doctrine\ORM\Persisters\Entity\BasicEntityPersister->getSelectConditionSQL(array('id' => '4', 'staff' => object(Staff)), null)
        in C:\wamp64\www\app\vendor\doctrine\orm\lib\Doctrine\ORM\Persisters\Entity\BasicEntityPersister.php line 1058

    at Doctrine\ORM\Persisters\Entity\BasicEntityPersister->getSelectSQL(array('id' => '4', 'staff' => object(Staff)), null, null, '1', null, null)
        in C:\wamp64\www\app\vendor\doctrine\orm\lib\Doctrine\ORM\Persisters\Entity\BasicEntityPersister.php line 710

    at Doctrine\ORM\Persisters\Entity\BasicEntityPersister->load(array('id' => '4', 'staff' => object(Staff)), null, null, array(), null, '1', null)
        in C:\wamp64\www\app\vendor\doctrine\orm\lib\Doctrine\ORM\EntityRepository.php line 196

    at Doctrine\ORM\EntityRepository->findOneBy(array('id' => '4', 'staff' => object(Staff)))
        in C:\wamp64\www\app\src\VS\CrmBundle\Controller\ManagerController.php line 21

    at VS\CrmBundle\Controller\ManagerController->dashboardAction('4')
        in  line 

    at call_user_func_array(array(object(ManagerController), 'dashboardAction'), array('4'))
        in C:\wamp64\www\app\vendor\symfony\symfony\src\Symfony\Component\HttpKernel\HttpKernel.php line 153

    at Symfony\Component\HttpKernel\HttpKernel->handleRaw(object(Request), '1')
        in C:\wamp64\www\app\vendor\symfony\symfony\src\Symfony\Component\HttpKernel\HttpKernel.php line 68

    at Symfony\Component\HttpKernel\HttpKernel->handle(object(Request), '1', true)
        in C:\wamp64\www\app\vendor\symfony\symfony\src\Symfony\Component\HttpKernel\Kernel.php line 169

    at Symfony\Component\HttpKernel\Kernel->handle(object(Request))
        in C:\wamp64\www\app\web\app_dev.php line 28

那么我做错了什么?也许这样做是错的?

2 个答案:

答案 0 :(得分:2)

请添加具有相对列名的joinColumnsinverseJoinColumns

<强> Staff.php

/**
 * @var ArrayCollection
 *
 * @ORM\ManyToMany(targetEntity="Nursery", inversedBy="staff", cascade={"persist"})
 * @ORM\JoinTable(name="nursery_staff",
 *   joinColumns={@ORM\JoinColumn(name="nursery_id", referencedColumnName="id")},
 *   inverseJoinColumns={@ORM\JoinColumn(name="staff_id", referencedColumnName="id")}
 * )
*/
private $nurseries;

Ref Here

答案 1 :(得分:1)

通过更改控制器解决了问题:

    public function dashboardAction($nursery_id)
{
    //$currentUser = $this->get('security.token_storage')->getToken()->getUser();
    $nurseryRepo = $this->getDoctrine()->getRepository('VSCrmBundle:Nursery');

    $nursery = $nurseryRepo->findOneBy(array('id' => $nursery_id));

    if(!$nursery)
    {
        throw $this->createNotFoundException("The nursery has not been found or you are not allowed to access it.");
    }

    return $this->render("VSCrmBundle:Manager:dashboard.html.twig", array(
        'nursery' => $nursery
    ));
}

如果您使用findOneBy关联中的属性进行搜索,我认为ManyToMany方法不起作用。