2016-01-15 56 views
0

嗨,大家好,我有两个对象当我从存储库中使用自定义DQL获得点和子点时,我想按字段ord排序点,并将子点排序到字段ord。Symfony 2 doctrine DQL order by two fields

这里是实体:

namespace George\ArchitectureBundle\Entity; 

use Doctrine\ORM\Mapping as ORM; 
use Knp\DoctrineBehaviors\Model\Translatable\Translatable; 
use Doctrine\Common\Collections\ArrayCollection; 
use Gedmo\Mapping\Annotation as Gedmo; 
use Vich\UploaderBundle\Mapping\Annotation as Vich; 
use Symfony\Component\HttpFoundation\File\File; 

/** 
* Point 
* 
* @ORM\Table() 
* @ORM\Entity(repositoryClass="George\ArchitectureBundle\Entity\PointRepository") 
* @Vich\Uploadable 
*/ 
class Point 
{ 
use Translatable; 
/** 
* @var integer 
* 
* @ORM\Column(name="id", type="integer") 
* @ORM\Id 
* @ORM\GeneratedValue(strategy="AUTO") 
*/ 
private $id; 

/** 
* @var Object 
* @Gedmo\SortableGroup 
* @ORM\ManyToOne(targetEntity="George\ObjectsBundle\Entity\Object", inversedBy="architecturespoints") 
* @ORM\JoinColumn(name="object_id", referencedColumnName="id") 
*/ 
private $object; 

/** 
* @ORM\OneToMany(targetEntity="George\ArchitectureBundle\Entity\Subpoint", mappedBy="point") 
*/ 
private $subpoints; 


/** 
* @var integer 
* @Gedmo\SortablePosition 
* @ORM\Column(name="ord", type="integer") 
*/ 
private $ord; 

/** 
* @var \DateTime 
* @Gedmo\Timestampable(on="update") 
* @ORM\Column(name="updated", type="datetime") 
*/ 
private $updated; 

/** 
* @var \DateTime 
* @Gedmo\Timestampable(on="create") 
* @ORM\Column(name="created", type="datetime") 
*/ 
private $created; 

public function __construct() 
{ 
    $this->subpoints = new ArrayCollection(); 
} 
/** 
* Get id 
* 
* @return integer 
*/ 
public function getId() 
{ 
    return $this->id; 
} 

/** 
* @return Object 
*/ 
public function getObject() 
{ 
    return $this->object; 
} 

/** 
* @param Object $object 
*/ 
public function setObject($object) 
{ 
    $this->object = $object; 
} 
/** 
* @return int 
*/ 
public function getOrd() 
{ 
    return $this->ord; 
} 

/** 
* @param int $ord 
*/ 
public function setOrd($ord) 
{ 
    $this->ord = $ord; 
} 
/** 
* @return \DateTime 
*/ 
public function getUpdated() 
{ 
    return $this->updated; 
} 

/** 
* @return \DateTime 
*/ 
public function getCreated() 
{ 
    return $this->created; 
} 

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

/** 
* NOTE: This is not a mapped field of entity metadata, just a simple property. 
* 
* @Vich\UploadableField(mapping="point_image", fileNameProperty="imageName") 
* 
* @var File 
*/ 
private $imageFile; 

/** 
* @ORM\Column(type="string", length=255, nullable=true) 
* 
* @var string 
*/ 
private $imageName; 

/** 
* If manually uploading a file (i.e. not using Symfony Form) ensure an instance 
* of 'UploadedFile' is injected into this setter to trigger the update. If this 
* bundle's configuration parameter 'inject_on_load' is set to 'true' this setter 
* must be able to accept an instance of 'File' as the bundle will inject one here 
* during Doctrine hydration. 
* 
* @param File|\Symfony\Component\HttpFoundation\File\UploadedFile $image 
*/ 
public function setImageFile(File $image = null) 
{ 
    $this->imageFile = $image; 

    if ($image) { 
     // It is required that at least one field changes if you are using doctrine 
     // otherwise the event listeners won't be called and the file is lost 
     // $this->setModefied(new \DateTime('now')) ; 
    } 
} 

/** 
* @return File 
*/ 
public function getImageFile() 
{ 
    return $this->imageFile; 
} 

/** 
* @param string $imageName 
*/ 
public function setImageName($imageName) 
{ 
    $this->imageName = $imageName; 
} 

/** 
* @return string 
*/ 
public function getImageName() 
{ 
    return $this->imageName; 
} 
} 

下点:

namespace George\ArchitectureBundle\Entity; 

use Doctrine\ORM\Mapping as ORM; 
use Knp\DoctrineBehaviors\Model as ORMBehaviors; 
use Knp\DoctrineBehaviors\Model\Translatable\Translatable; 
use Gedmo\Mapping\Annotation as Gedmo; 
use Vich\UploaderBundle\Mapping\Annotation as Vich; 
use Symfony\Component\HttpFoundation\File\File; 


/** 
* Subpoint 
* 
* @ORM\Table() 
* @ORM\Entity(repositoryClass="George\ArchitectureBundle\Entity\SubpointRepository") 
* @Vich\Uploadable 
*/ 
class Subpoint 
{ 
use Translatable; 

/** 
* @var integer 
* 
* @ORM\Column(name="id", type="integer") 
* @ORM\Id 
* @ORM\GeneratedValue(strategy="AUTO") 
*/ 
private $id; 

/** 
* @var Points 
* @Gedmo\SortableGroup 
* @ORM\ManyToOne(targetEntity="George\ArchitectureBundle\Entity\Point", inversedBy="subpoints") 
*/ 
private $point; 

/** 
* @var integer 
* @Gedmo\SortablePosition 
* @ORM\Column(name="ord", type="integer") 
*/ 
private $ord; 



/** 
* @var \DateTime 
* @Gedmo\Timestampable(on="update") 
* @ORM\Column(name="updated", type="datetime") 
*/ 
private $updated; 


/** 
* @var \DateTime 
* @Gedmo\Timestampable(on="create") 
* @ORM\Column(name="created", type="datetime") 
*/ 
private $created; 

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

/** 
* @return Points 
*/ 
public function getPoint() 
{ 
    return $this->point; 
} 

/** 
* @param Points $point 
*/ 
public function setPoint($point) 
{ 
    $this->point = $point; 
} 
/** 
* NOTE: This is not a mapped field of entity metadata, just a simple property. 
* 
* @Vich\UploadableField(mapping="point_image", fileNameProperty="imageName") 
* 
* @var File 
*/ 
private $imageFile; 

/** 
* @ORM\Column(type="string", length=255, nullable=true) 
* 
* @var string 
*/ 
private $imageName; 


/** 
* If manually uploading a file (i.e. not using Symfony Form) ensure an instance 
* of 'UploadedFile' is injected into this setter to trigger the update. If this 
* bundle's configuration parameter 'inject_on_load' is set to 'true' this setter 
* must be able to accept an instance of 'File' as the bundle will inject one here 
* during Doctrine hydration. 
* 
* @param File|\Symfony\Component\HttpFoundation\File\UploadedFile $image 
*/ 
public function setImageFile(File $image = null) 
{ 
    $this->imageFile = $image; 

    if ($image) { 
     // It is required that at least one field changes if you are using doctrine 
     // otherwise the event listeners won't be called and the file is lost 
     // $this->setModefied(new \DateTime('now')) ; 
    } 
} 

/** 
* @return File 
*/ 
public function getImageFile() 
{ 
    return $this->imageFile; 
} 

/** 
* @param string $imageName 
*/ 
public function setImageName($imageName) 
{ 
    $this->imageName = $imageName; 
} 

/** 
* @return string 
*/ 
public function getImageName() 
{ 
    return $this->imageName; 
} 
/** 
* @return \DateTime 
*/ 
public function getUpdated() 
{ 
    return $this->updated; 
} 

/** 
* @return \DateTime 
*/ 
public function getCreated() 
{ 
    return $this->created; 
} 

/** 
* @return int 
*/ 
public function getOrd() 
{ 
    return $this->ord; 
} 

/** 
* @param int $ord 
*/ 
public function setOrd($ord) 
{ 
    $this->ord = $ord; 
} 

} 

库点,在这里,我想,当我点到由奥德被oredered并通过ORD订购的subpoints:

namespace George\ArchitectureBundle\Entity; 

/** 
* PointRepository 
* 
* This class was generated by the Doctrine ORM. Add your own custom 
* repository methods below. 
*/ 
class PointRepository extends \Doctrine\ORM\EntityRepository 
{ 
public function getPointsByObject($object) 
{ 

    $em = $this->getEntityManager(); 
    $query = $em->createQuery("SELECT p FROM George\ArchitectureBundle\Entity\Point p WHERE p.object =".$object." ORDER BY p.ord ASC"); 
    return $query->getResult(); 


} 
} 

但是当我把在creatQuery在点存储库

"SELECT p FROM George\ArchitectureBundle\Entity\Point p WHERE p.object =".$object." ORDER BY p.ord ASC, p.subpoints.ord ASC " 

我得到错误:

[Semantical Error] line 0, col 107 near 'ord ASC ': Error: Class George\ArchitectureBundle\Entity\Point has no field or association named subpoints.ord 

编辑 到问题的解决方案是用这个查询器与@Yoshi和@Veve的指导:

public function getPointsByObject($object) 
{ 

    $em = $this->getEntityManager(); 
    // $query = $em->createQuery("SELECT p FROM George\ArchitectureBundle\Entity\Point p left join George\ArchitectureBundle\Entity\Subpoint s WITH s.point = p WHERE p.object =".$object." ORDER BY p.ord ASC, s.ord ASC"); 
    $qb = $em->createQueryBuilder(); 
    $qb->select('p') 
     ->from('George\ArchitectureBundle\Entity\Point','p') 
     ->where(' p.object =:object') 
     ->leftJoin('George\ArchitectureBundle\Entity\Subpoint', 's', 'WITH', 's.point = p') 
     ->orderBy('p.ord','ASC') 
     ->orderBy('s.ord','ASC'); 

    $qb->setParameters(array(
     'object' => $object 
    )); 
    $query= $qb->getQuery(); 

    return $query->getResult(); 


} 
+2

你有什么好理由使用原则,并仍然建立查询字符串*手?*?这里有严重的问题。使用['setParameter'](https://doctrine-orm.readthedocs.org/projects/doctrine-orm/en/latest/reference/dql-doctrine-query-language.html)或类似的。 – Yoshi

+0

你是对的参数,但问题是在秩序声明,它是在第二顺序不在参数对象。 –

+1

我暗示的是,当你正确地建立查询时,你一定会有更容易的时间修复订单问题。例如。使用查询生成器,您可以根据需要简单地添加'addOrderBy()'多次。也就是说,可能会添加* renderd * dql,所以我们可以在不猜测'$ object'可以做什么的情况下看到它。 – Yoshi

回答

2

你必须加入该子点以按其属性之一订购:

"SELECT p FROM George\ArchitectureBundle\Entity\Point p 
JOIN George\ArchitectureBundle\Entity\Subpoint s WITH s.point = p.id 
WHERE p.object =".$object." 
ORDER BY p.ord ASC, s.ord ASC" 

而作为Yoshicommented,您应该使用queryBuilder并添加您的参数,而不是手动建立您的查询。

+0

谢谢,我只需要用WITH –

+0

替换您说得对,已更正。 – Veve

+0

你也可以用'JOIN p.subpoints s'代替。 – xabbuh