使用 symfony3、doctrine2 和 stofDoctrineExtensionsBundle 按任意字段对 Gedmo 树进行排序
Sort Gedmo Tree by arbitrary field using symfony3, doctrine2 and stofDoctrineExtensionsBundle
简介
我正在使用:
- Windows 10 专业版
- XAMPP 与 PHP v7.0.9
- Symfony v3.1.7
- Doctrine v2.5.4
- StofDoctrineExtensionsBundle [1] 为了管理树结构。
正在设置
为了设置树结构,我使用了 Symfony.com [2] followed by documentation on GitHub [3]. Then I proceeded with tree setup - used tree entity from example [4] and used code in [5] 上的文档来创建树。
我确实设置了名为 FileTree
的树结构(代表目录和文件)。我向树中添加了几个自定义字段:item_name
、item_extension
和 is_file
。删除了 title
因为我有 item_name
...
我的 FileTree
实体:
<?php
namespace AppBundle\Entity;
use Gedmo\Mapping\Annotation as Gedmo;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\ORM\Mapping\ManyToOne;
use Doctrine\ORM\Mapping\JoinColumn;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\Common\Collections\ArrayCollection as ArrayCollection;
/**
* @Gedmo\Tree(type="nested")
* @ORM\Table(name="file_tree")
* use repository for handy tree functions
* @ORM\Entity(repositoryClass="AppBundle\Repository\FileTreeRepository")
*/
class FileTree
{
/**
* @ORM\Column(type="integer")
* @ORM\Id
* @ORM\GeneratedValue
*/
private $id;
/**
* @ORM\Column(type="string", length=1024)
*
* @var string
*/
private $item_path;
/**
* @ORM\Column(type="string", length=240)
*
* @var string
*/
private $item_name;
/**
* @ORM\Column(type="string", length=20)
*
* @var string
*/
private $item_extension;
/**
* @ORM\Column(type="boolean")
*/
private $is_file;
/**
* @Gedmo\TreeLeft
* @ORM\Column(type="integer")
*/
private $lft;
/**
* @Gedmo\TreeLevel
* @ORM\Column(type="integer")
*/
private $lvl;
/**
* @Gedmo\TreeRight
* @ORM\Column(type="integer")
*/
private $rgt;
/**
* @Gedmo\TreeRoot
* @ORM\ManyToOne(targetEntity="FileTree")
* @ORM\JoinColumn(referencedColumnName="id", onDelete="CASCADE")
*/
private $root;
/**
* @Gedmo\TreeParent
* @ORM\ManyToOne(targetEntity="FileTree", inversedBy="children")
* @ORM\JoinColumn(referencedColumnName="id", onDelete="CASCADE")
*/
private $parent;
/**
* @ORM\OneToMany(targetEntity="FileTree", mappedBy="parent")
* @ORM\OrderBy({"lft" = "ASC"})
*/
private $children;
/**
* @ManyToOne(targetEntity="Project", inversedBy="file_tree")
* @JoinColumn(name="project_id", referencedColumnName="id")
*/
private $project;
/**
* Constructor
*/
public function __construct()
{
$this->children = new ArrayCollection();
}
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set itemPath
*
* @param string $itemPath
*
* @return FileTree
*/
public function setItemPath($itemPath)
{
$this->item_path = $itemPath;
return $this;
}
/**
* Get itemPath
*
* @return string
*/
public function getItemPath()
{
return $this->item_path;
}
/**
* Set itemName
*
* @param string $itemName
*
* @return FileTree
*/
public function setItemName($itemName)
{
$this->item_name = $itemName;
return $this;
}
/**
* Get itemName
*
* @return string
*/
public function getItemName()
{
return $this->item_name;
}
/**
* Set isFile
*
* @param boolean $isFile
*
* @return FileTree
*/
public function setIsFile($isFile)
{
$this->is_file = $isFile;
return $this;
}
/**
* Get isFile
*
* @return boolean
*/
public function getIsFile()
{
return $this->is_file;
}
/**
* Set lft
*
* @param integer $lft
*
* @return FileTree
*/
public function setLft($lft)
{
$this->lft = $lft;
return $this;
}
/**
* Get lft
*
* @return integer
*/
public function getLft()
{
return $this->lft;
}
/**
* Set lvl
*
* @param integer $lvl
*
* @return FileTree
*/
public function setLvl($lvl)
{
$this->lvl = $lvl;
return $this;
}
/**
* Get lvl
*
* @return integer
*/
public function getLvl()
{
return $this->lvl;
}
/**
* Set rgt
*
* @param integer $rgt
*
* @return FileTree
*/
public function setRgt($rgt)
{
$this->rgt = $rgt;
return $this;
}
/**
* Get rgt
*
* @return integer
*/
public function getRgt()
{
return $this->rgt;
}
/**
* Set root
*
* @param \AppBundle\Entity\FileTree $root
*
* @return FileTree
*/
public function setRoot(\AppBundle\Entity\FileTree $root = null)
{
$this->root = $root;
return $this;
}
/**
* Get root
*
* @return \AppBundle\Entity\FileTree
*/
public function getRoot()
{
return $this->root;
}
/**
* Set parent
*
* @param \AppBundle\Entity\FileTree $parent
*
* @return FileTree
*/
public function setParent(\AppBundle\Entity\FileTree $parent = null)
{
$this->parent = $parent;
return $this;
}
/**
* Get parent
*
* @return \AppBundle\Entity\FileTree
*/
public function getParent()
{
return $this->parent;
}
/**
* Add child
*
* @param \AppBundle\Entity\FileTree $child
*
* @return FileTree
*/
public function addChild(\AppBundle\Entity\FileTree $child)
{
$this->children[] = $child;
return $this;
}
/**
* Remove child
*
* @param \AppBundle\Entity\FileTree $child
*/
public function removeChild(\AppBundle\Entity\FileTree $child)
{
$this->children->removeElement($child);
}
/**
* Get children
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getChildren()
{
return $this->children;
}
/**
* Set project
*
* @param \AppBundle\Entity\Project $project
*
* @return FileTree
*/
public function setProject(\AppBundle\Entity\Project $project = null)
{
$this->project = $project;
return $this;
}
/**
* Get project
*
* @return \AppBundle\Entity\Project
*/
public function getProject()
{
return $this->project;
}
/**
* toString
*
* @return string
*/
public function __toString()
{
return $this->getItemName();
}
/**
* Set itemExtension
*
* @param string $itemExtension
*
* @return FileTree
*/
public function setItemExtension($itemExtension)
{
$this->item_extension = $itemExtension;
return $this;
}
/**
* Get itemExtension
*
* @return string
*/
public function getItemExtension()
{
return $this->item_extension;
}
}
问题
我需要按文件类型对树文件夹中的文件进行排序 - 即:按 item_extension
然后按 item_name
。目前 Gedmo Nestedset Tree
按 root
和 lft
排序,如下一个代码块所示。
public function getFileTreeNodeArray($file_tree_root_id)
{
$em = $this->getEntityManager();
$query = $em
->createQueryBuilder()
->select('ft')
->from('AppBundle:FileTree', 'ft')
->where('ft.root = :root')
->setParameter('root', $file_tree_root_id)
->orderBy('ft.root, ft.lft', 'ASC')
->getQuery();
$query->setHint(\Doctrine\ORM\Query::HINT_INCLUDE_META_COLUMNS, true);
$build_my_tree = $query->getArrayResult();
return $build_my_tree;
}
遗憾的是添加额外的 ->orderBy('ft.item_extension', 'ASC')
没有产生任何结果...
然后我了解到 有 2 个函数可以帮助我完成这项工作 reorderAll
和 reorder
。我尝试了两个,但遗憾的是项目没有改变它们的顺序,它们仍然按 root
和 lft
.
排序
我的代码来自 Upload Listener
:
$repo_file_tree = $this->entityManager->getRepository('AppBundle:FileTree');
$root_node_id = $repo_file_tree->getFileTreeRootNodeIdByProjectId($selected_node_parent_id);
$root_node = $repo_file_tree->findOneBy(array('id' => $root_node_id));
$repo_file_tree->reorder($root_node, 'item_extension, item_name', 'ASC');
$this->entityManager->flush();
或
$repo_file_tree = $this->entityManager->getRepository('AppBundle:FileTree');
$repo_file_tree->reorderAll('item_extension, item_name', 'ASC');
$this->entityManager->flush();
问题
如何获取包含 item_extension, item_name
订购的 FileTree
项的数组?
我很高兴以太正确的 Doctrine 查询(最好)或解释包含函数 reorder
和 reorderAll
.
的代码块有什么问题
结论
我错过了什么?
请指教
感谢您的时间和知识。
刚刚将我的项目更新为 Symfony v3.2.0
现在我得到错误
Invalid sort options specified: field - item_extension, item_name, direction - ASC
500 Internal Server Error - InvalidArgumentException
使用reorder
时使用上述代码。
我不确定它是刚刚发生(升级后)还是 Symfony v3.1.x
也发生过。
无论如何 - 很明显 reorder
确实只使用一个字段来对树枝进行排序。不像我之前尝试的那样有多个字段。
所以答案是:在调用 reorder
函数时不要使用多个排序字段。
$repo_file_tree = $this->entityManager->getRepository('AppBundle:FileTree');
$root_node_id = $repo_file_tree->getFileTreeRootNodeIdByProjectId($selected_node_parent_id);
$root_node = $repo_file_tree->findOneBy(array('id' => $root_node_id));
$repo_file_tree->reorder($root_node, 'item_extension', 'ASC');
$this->entityManager->flush();
简介
我正在使用:
- Windows 10 专业版
- XAMPP 与 PHP v7.0.9
- Symfony v3.1.7
- Doctrine v2.5.4
- StofDoctrineExtensionsBundle [1] 为了管理树结构。
正在设置
为了设置树结构,我使用了 Symfony.com [2] followed by documentation on GitHub [3]. Then I proceeded with tree setup - used tree entity from example [4] and used code in [5] 上的文档来创建树。
我确实设置了名为 FileTree
的树结构(代表目录和文件)。我向树中添加了几个自定义字段:item_name
、item_extension
和 is_file
。删除了 title
因为我有 item_name
...
我的 FileTree
实体:
<?php
namespace AppBundle\Entity;
use Gedmo\Mapping\Annotation as Gedmo;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\ORM\Mapping\ManyToOne;
use Doctrine\ORM\Mapping\JoinColumn;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\Common\Collections\ArrayCollection as ArrayCollection;
/**
* @Gedmo\Tree(type="nested")
* @ORM\Table(name="file_tree")
* use repository for handy tree functions
* @ORM\Entity(repositoryClass="AppBundle\Repository\FileTreeRepository")
*/
class FileTree
{
/**
* @ORM\Column(type="integer")
* @ORM\Id
* @ORM\GeneratedValue
*/
private $id;
/**
* @ORM\Column(type="string", length=1024)
*
* @var string
*/
private $item_path;
/**
* @ORM\Column(type="string", length=240)
*
* @var string
*/
private $item_name;
/**
* @ORM\Column(type="string", length=20)
*
* @var string
*/
private $item_extension;
/**
* @ORM\Column(type="boolean")
*/
private $is_file;
/**
* @Gedmo\TreeLeft
* @ORM\Column(type="integer")
*/
private $lft;
/**
* @Gedmo\TreeLevel
* @ORM\Column(type="integer")
*/
private $lvl;
/**
* @Gedmo\TreeRight
* @ORM\Column(type="integer")
*/
private $rgt;
/**
* @Gedmo\TreeRoot
* @ORM\ManyToOne(targetEntity="FileTree")
* @ORM\JoinColumn(referencedColumnName="id", onDelete="CASCADE")
*/
private $root;
/**
* @Gedmo\TreeParent
* @ORM\ManyToOne(targetEntity="FileTree", inversedBy="children")
* @ORM\JoinColumn(referencedColumnName="id", onDelete="CASCADE")
*/
private $parent;
/**
* @ORM\OneToMany(targetEntity="FileTree", mappedBy="parent")
* @ORM\OrderBy({"lft" = "ASC"})
*/
private $children;
/**
* @ManyToOne(targetEntity="Project", inversedBy="file_tree")
* @JoinColumn(name="project_id", referencedColumnName="id")
*/
private $project;
/**
* Constructor
*/
public function __construct()
{
$this->children = new ArrayCollection();
}
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set itemPath
*
* @param string $itemPath
*
* @return FileTree
*/
public function setItemPath($itemPath)
{
$this->item_path = $itemPath;
return $this;
}
/**
* Get itemPath
*
* @return string
*/
public function getItemPath()
{
return $this->item_path;
}
/**
* Set itemName
*
* @param string $itemName
*
* @return FileTree
*/
public function setItemName($itemName)
{
$this->item_name = $itemName;
return $this;
}
/**
* Get itemName
*
* @return string
*/
public function getItemName()
{
return $this->item_name;
}
/**
* Set isFile
*
* @param boolean $isFile
*
* @return FileTree
*/
public function setIsFile($isFile)
{
$this->is_file = $isFile;
return $this;
}
/**
* Get isFile
*
* @return boolean
*/
public function getIsFile()
{
return $this->is_file;
}
/**
* Set lft
*
* @param integer $lft
*
* @return FileTree
*/
public function setLft($lft)
{
$this->lft = $lft;
return $this;
}
/**
* Get lft
*
* @return integer
*/
public function getLft()
{
return $this->lft;
}
/**
* Set lvl
*
* @param integer $lvl
*
* @return FileTree
*/
public function setLvl($lvl)
{
$this->lvl = $lvl;
return $this;
}
/**
* Get lvl
*
* @return integer
*/
public function getLvl()
{
return $this->lvl;
}
/**
* Set rgt
*
* @param integer $rgt
*
* @return FileTree
*/
public function setRgt($rgt)
{
$this->rgt = $rgt;
return $this;
}
/**
* Get rgt
*
* @return integer
*/
public function getRgt()
{
return $this->rgt;
}
/**
* Set root
*
* @param \AppBundle\Entity\FileTree $root
*
* @return FileTree
*/
public function setRoot(\AppBundle\Entity\FileTree $root = null)
{
$this->root = $root;
return $this;
}
/**
* Get root
*
* @return \AppBundle\Entity\FileTree
*/
public function getRoot()
{
return $this->root;
}
/**
* Set parent
*
* @param \AppBundle\Entity\FileTree $parent
*
* @return FileTree
*/
public function setParent(\AppBundle\Entity\FileTree $parent = null)
{
$this->parent = $parent;
return $this;
}
/**
* Get parent
*
* @return \AppBundle\Entity\FileTree
*/
public function getParent()
{
return $this->parent;
}
/**
* Add child
*
* @param \AppBundle\Entity\FileTree $child
*
* @return FileTree
*/
public function addChild(\AppBundle\Entity\FileTree $child)
{
$this->children[] = $child;
return $this;
}
/**
* Remove child
*
* @param \AppBundle\Entity\FileTree $child
*/
public function removeChild(\AppBundle\Entity\FileTree $child)
{
$this->children->removeElement($child);
}
/**
* Get children
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getChildren()
{
return $this->children;
}
/**
* Set project
*
* @param \AppBundle\Entity\Project $project
*
* @return FileTree
*/
public function setProject(\AppBundle\Entity\Project $project = null)
{
$this->project = $project;
return $this;
}
/**
* Get project
*
* @return \AppBundle\Entity\Project
*/
public function getProject()
{
return $this->project;
}
/**
* toString
*
* @return string
*/
public function __toString()
{
return $this->getItemName();
}
/**
* Set itemExtension
*
* @param string $itemExtension
*
* @return FileTree
*/
public function setItemExtension($itemExtension)
{
$this->item_extension = $itemExtension;
return $this;
}
/**
* Get itemExtension
*
* @return string
*/
public function getItemExtension()
{
return $this->item_extension;
}
}
问题
我需要按文件类型对树文件夹中的文件进行排序 - 即:按 item_extension
然后按 item_name
。目前 Gedmo Nestedset Tree
按 root
和 lft
排序,如下一个代码块所示。
public function getFileTreeNodeArray($file_tree_root_id)
{
$em = $this->getEntityManager();
$query = $em
->createQueryBuilder()
->select('ft')
->from('AppBundle:FileTree', 'ft')
->where('ft.root = :root')
->setParameter('root', $file_tree_root_id)
->orderBy('ft.root, ft.lft', 'ASC')
->getQuery();
$query->setHint(\Doctrine\ORM\Query::HINT_INCLUDE_META_COLUMNS, true);
$build_my_tree = $query->getArrayResult();
return $build_my_tree;
}
遗憾的是添加额外的 ->orderBy('ft.item_extension', 'ASC')
没有产生任何结果...
然后我了解到 reorderAll
和 reorder
。我尝试了两个,但遗憾的是项目没有改变它们的顺序,它们仍然按 root
和 lft
.
我的代码来自 Upload Listener
:
$repo_file_tree = $this->entityManager->getRepository('AppBundle:FileTree');
$root_node_id = $repo_file_tree->getFileTreeRootNodeIdByProjectId($selected_node_parent_id);
$root_node = $repo_file_tree->findOneBy(array('id' => $root_node_id));
$repo_file_tree->reorder($root_node, 'item_extension, item_name', 'ASC');
$this->entityManager->flush();
或
$repo_file_tree = $this->entityManager->getRepository('AppBundle:FileTree');
$repo_file_tree->reorderAll('item_extension, item_name', 'ASC');
$this->entityManager->flush();
问题
如何获取包含 item_extension, item_name
订购的 FileTree
项的数组?
我很高兴以太正确的 Doctrine 查询(最好)或解释包含函数 reorder
和 reorderAll
.
结论
我错过了什么?
请指教
感谢您的时间和知识。
刚刚将我的项目更新为 Symfony v3.2.0
现在我得到错误
Invalid sort options specified: field - item_extension, item_name, direction - ASC
500 Internal Server Error - InvalidArgumentException
使用reorder
时使用上述代码。
我不确定它是刚刚发生(升级后)还是 Symfony v3.1.x
也发生过。
无论如何 - 很明显 reorder
确实只使用一个字段来对树枝进行排序。不像我之前尝试的那样有多个字段。
所以答案是:在调用 reorder
函数时不要使用多个排序字段。
$repo_file_tree = $this->entityManager->getRepository('AppBundle:FileTree');
$root_node_id = $repo_file_tree->getFileTreeRootNodeIdByProjectId($selected_node_parent_id);
$root_node = $repo_file_tree->findOneBy(array('id' => $root_node_id));
$repo_file_tree->reorder($root_node, 'item_extension', 'ASC');
$this->entityManager->flush();