Doctrine custom repository with an objectselect fo

2019-07-04 09:16发布

问题:

This question is a possible solution for ZF2 Doctrine get manytomany relations with objectSelect, but the question it self is different and not related.

I've got a custom repository with this code:

class StoreRepository extends EntityRepository
{
    public function getCategories(array $criteria){

        return $this->createQueryBuilder("s")
        ->select('c.id,c.categoryName')
        ->innerJoin("s.categories", "c", "WITH", "s=:storeid")
            ->setParameter("storeid", $criteria['storeid'])
        ->getQuery()->getResult();
     }
}

This is my objectselect form:

    $this->add(array(
        'type' => 'DoctrineModule\Form\Element\ObjectSelect',
        'name' => 'categories',
        'attributes' => array(
            'multiple' => true,
        ),
        'options' => array(
            'object_manager' => $objectManager,
            'target_class'   => 'Application\Entity\Store',
            'label' => 'Selecteer categorieën',
            'column-size' => 'sm-9',
            'label_attributes' => array('class' => 'col-sm-3 control-label'),
            'property'       => 'categoryName',
            'is_method'      => true,
             'find_method'    => array(
                'name'   => 'getCategories',
                'params' => array(
                    'criteria' => array('storeid' => $storeid),
                ),
            ),

        ),
    ));

The query is working fine, but i'm getting:

  Method "Application\Entity\Store::getCategoryName" is not callable

My store entity looks like:

    <?php
    namespace Application\Entity;

    use Doctrine\ORM\Mapping as ORM;

    /**
     * An example entity that represents a store.
     *
     * @ORM\Entity
     * @ORM\Table(name="store")
     * @ORM\Entity(repositoryClass="Application\Repositories\StoreRepository")
     *
     */
    class Store
    {
        /**
         * @var int
         * @ORM\Id
         * @ORM\Column(type="integer")
         * @ORM\GeneratedValue(strategy="AUTO")
         */
        protected $id;

        /**
         * @var string
         * @ORM\Column(type="string", name="storeName", length=255, unique=true, nullable=true)
         */
        protected $storeName;

        /**
         * @var \Doctrine\Common\Collections\Collection
         * @ORM\ManyToMany(targetEntity="Application\Entity\Product", inversedBy="stores")
         * @ORM\JoinTable(name="product_store")
         */
        protected $products;

        /**
         * @var \Doctrine\Common\Collections\Collection
         * @ORM\ManyToMany(targetEntity="Application\Entity\Category", inversedBy="stores")
         * @ORM\JoinTable(name="category_store")
         */
        protected $categories;

        /**
         * Initialies the roles variable.
         */
        public function __construct()
        {
            $this->products = new ArrayCollection();
        }

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

        /**
         * Set the id.
         *
         * @param int $id
         *
         * @return void
         */
        public function setId($id)
        {
            $this->id = (int)$id;
        }

        /**
         * Get the store id.
         *
         * @return string
         */
        public function getStoreName()
        {
            return $this->storeName;
        }

        /**
         * Set the store id.
         *
         * @param string $storeName
         *
         * @return void
         */
        public function setStoreName($storeName)
        {
            $this->storeName = (string) $storeName;
        }

        /**
         * Get product.
         *
         * @return array
         */
        public function getProducts()
        {
            return $this->products->getValues();
        }

        /**
         * Add a product to the user.
         *
         * @param Role $product
         *
         * @return void
         */
        public function addProduct($products)
        {
            $this->products[] = $products;
        }

        /**
         * Get category.
         *
         * @return array
         */
        public function getCategories()
        {
            return $this->categories->getValues();
        }

        /**
         * Add a product to the user.
         *
         * @param Role $product
         *
         * @return void
         */
        public function addCategory($categories)
        {
            $this->categories[] = $categories;
        }

    }

and my category entity:

    <?php
    namespace Application\Entity;

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

    /**
     * An example entity that represents a category.
     *
     * @ORM\Entity
     * @ORM\Table(name="category")
     *
     */
    class Category
    {
        /**
         * @var int
         * @ORM\Id
         * @ORM\Column(type="integer")
         * @ORM\GeneratedValue(strategy="AUTO")
         */
        protected $id;

        /**
         * @var string
         * @ORM\Column(type="string", name="categoryName", length=255, unique=true, nullable=true)
         */
        protected $categoryName;

        /**
         * @var \Doctrine\Common\Collections\Collection
         * @ORM\ManyToMany(targetEntity="Application\Entity\Product", mappedBy="categories", cascade={"all"})
         */
        protected $product;

        /**
        * @ORM\OneToMany(targetEntity="Application\Entity\Category", mappedBy="parent")
        */
       private $children;

        /**
         * @var Category
         * @ORM\ManyToOne(targetEntity="Application\Entity\Category")
         * @ORM\JoinColumn(name="parent_id", referencedColumnName="id", nullable=true, onDelete="CASCADE")
         */
        protected $parent;

        /**
         * @var \Doctrine\Common\Collections\Collection
         * @ORM\ManyToMany(targetEntity="Application\Entity\Store", mappedBy="categories")
         */
        protected $stores;

        /**
         * Initialies the roles variable.
         */
        public function __construct()
        {
            $this->children = new ArrayCollection();
            $this->products = new ArrayCollection();
            $this->stores = new ArrayCollection();
        }

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

        /**
         * Set the id.
         *
         * @param int $id
         *
         * @return void
         */
        public function setId($id)
        {
            $this->id = (int)$id;
        }

        /**
         * Get the category id.
         *
         * @return string
         */
        public function getCategoryName()
        {
            return $this->categoryName;
        }

        /**
         * Set the category id.
         *
         * @param string $categoryName
         *
         * @return void
         */
        public function setCategoryName($categoryName)
        {
            $this->categoryName = (string) $categoryName;
        }

        /**
         * Get product.
         *
         * @return array
         */
        public function getProduct()
        {
            return $this->product;
        }

        /**
         * Add a product to the user.
         *
         * @param Role $product
         *
         * @return void
         */
        public function addProduct($product = null)
        {
            $product->addCategory($this);
            $this->product = $products;
        }

        /**
         * Get store.
         *
         * @return array
         */
        public function getStores()
        {
            return $this->stores->getValues();
        }


         /**
         * Add a stores to the product.
         *
         * @param Stores
         *
         * @return void
         */
        public function addStores(Collection $stores)
        {
            foreach ($stores as $store) {
                $store->addCategory($this);
                $this->stores->add($store);
            }
        }

        public function removeStores(Collection $stores){
            foreach($stores as $store){
                $this->stores->removeElement($store);
            }
        }

        /**
         * Get the parent role
         *
         * @return Role
         */
        public function getParent()
        {
            return $this->parent;
        }

        /**
         * Set the parent role.
         *
         * @param Role $parent
         *
         * @return void
         */
        public function setParent(Category $parent = null)
        {
            $this->parent = $parent;
        }

        /**
         * Get images.
         *
         * @return array
         */
        public function getChildren()
        {
            return $this->children;
        }

        /**
         * Add a image to the product.
         *
         * @param Images
         *
         * @return void
         */
        public function addChildren(Collection $children)
        {
            foreach ($children as $child) {
                $child->setCategory($this);
                $this->children->add($child);
            }
        }

        /**
         * @param Collection $images
         */
        public function removeChildren(Collection $children)
        {
            foreach ($children as $child) {
                $child->setCategory($this);
                $this->children->removeElement($child);
            }
        }

    }

回答1:

Figured it out. I had to reverse the join:

    $this->add(array(
        'type' => 'DoctrineModule\Form\Element\ObjectSelect',
        'name' => 'categories',
        'attributes' => array(
            'multiple' => true,
        ),
        'options' => array(
            'object_manager' => $objectManager,
            'target_class'   => 'Application\Entity\Category',
            'label' => 'Selecteer categorieën',
            'column-size' => 'sm-9',
            'label_attributes' => array('class' => 'col-sm-3 control-label'),
            'property'       => 'categoryName',
            'is_method'      => true,
             'find_method'    => array(
                'name'   => 'getStoreCategories',
                'params' => array(
                    'criteria' => array('storeid' => $storeid),
                ),
            ),

        ),
    ));

And my custom repository

    <?php

    namespace Application\Repositories;

    use Doctrine\ORM\EntityRepository;
    use Doctrine\ORM\Query\ResultSetMapping;
    use Doctrine\DBAL\Types\Type;


    class CategoryRepository extends EntityRepository
    {
        public function getStoreCategories(array $criteria){

            return $this->createQueryBuilder('c')
            ->select('c')
            ->innerJoin("c.stores", "s", "WITH", "s=:storeid")
                ->setParameter("storeid", $criteria['storeid'])
            ->getQuery()->getResult();
        }
    }