上周我开始使用Doctrine,我对此非常肯定,但我遇到了一些问题。我在MySQL:http://ftp.nchu.edu.tw/MySQL/tech-resources/articles/hierarchical-data.html中实现分层数据,我拥有的实体需要一些聚合(不确定这是不是正确的术语,也许虚拟更好)。但我需要两个额外的字段,即: Depth和ParentID。目前(使用原生查询),我通过子查询获取这些内容。Doctrine的结果是一个数组,而我想要一个对象。
这是我正在使用的表结构:
CREATE TABLE IF NOT EXISTS `category` (
`ID` int(8) unsigned NOT NULL AUTO_INCREMENT,
`Name` varchar(45) NOT NULL,
`LeftID` int(10) NOT NULL,
`RightID` int(10) NOT NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=4 ;
和三个示例类别:
INSERT INTO `category` (`ID`, `Name`, `LeftID`, `RightID`) VALUES
(1, 'cat#1', 1, 4),
(2, 'cat#2', 5, 6),
(3, 'cat#1.1', 2, 3);
我查看了doctrine (http://doctrine-orm.readthedocs.org/en/latest/cookbook/aggregate-fields.html)中的聚合字段示例,但我并不清楚真正的实现。另外,如果它是相同的,我想要的。
我现在使用的实体看起来像这样:
/**
* @ORM\Entity (repositoryClass="Application\Entity\CategoryRepository")
* @ORM\Table(name="category")
*/
class Category
{
protected $inputFilter;
/**
* @ORM\Id
* @ORM\Column(type="integer");
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $ID;
/**
* @ORM\Column(type="string")
*/
protected $Name;
/**
* @ORM\Column(type="integer")
*/
protected $LeftID;
/**
* @ORM\Column(type="integer")
*/
protected $RightID;
}
我使用神奇的setter/getter来公开受保护的属性(__set和__get),以接收我使用以下查询的数据:
SELECT
node.ID,
node.Name,
node.LeftID,
node.RightID,
(
SELECT
ID
FROM
Category subtree
WHERE
subtree.LeftID < node.LeftID
AND
subtree.RightID > node.RightID
ORDER BY
subtree.RightID - node.RightID ASC
LIMIT
0, 1
) AS ParentID,
(
SELECT
(COUNT(parent.ID) - 1)
FROM
Category AS node,
Category AS parent
WHERE
node.LeftID BETWEEN parent.LeftID AND parent.RightID
AND
node.ID = 3
GROUP BY
node.ID
ORDER BY
parent.LeftID
) As Depth
FROM
Category As node,
Category As parent
WHERE
node.ID = 3
AND
node.LeftID BETWEEN parent.LeftID AND parent.RightID
GROUP BY
node.ID
结果(对于给定的数据集)将是:
ID Name LeftID RightID ParentID Depth
3 cat#1.1 2 3 1 1
这正是我想在Doctrine实体中得到的结果,但找不到将实体作为Doctrine对象的解决方案。目前我有两个函数,一个返回数组,在那里我确实需要深度和查找,如果我需要对象,我使用默认的理论函数(例如,ParentID ),但我想要一个优雅的解决方案。另外,我认为我在将来会用到其他对象,例如:一个人的年龄(从生日开始计算)。
发布于 2016-05-11 16:53:42
这应该会让你得到你想要的(可能需要稍微修修补补):
$manager = $this->getDoctrine()->getEntityManager();
$qb = $manager->createQueryBuilder();
$expr = $qb->expr();
$query = $qb
->select('node.ID, node.Name, node.LeftID, node.RightID')
->addSelect('
(SELECT
ID
FROM
Category subtree
WHERE
subtree.LeftID < node.LeftID
AND
subtree.RightID > node.RightID
ORDER BY
subtree.RightID - node.RightID ASC
LIMIT
0, 1) AS ParentID
')
->addSelect('
(SELECT
(COUNT(parent.ID) - 1)
FROM
Category AS node,
Category AS parent
WHERE
node.LeftID BETWEEN parent.LeftID AND parent.RightID
AND
node.ID = 3
GROUP BY
node.ID
ORDER BY
parent.LeftID
) As Depth
')
->from('Category', 'node')
->join('Category', 'parent')
->where($expr->eq('node.ID', 3))
->andWhere($expr->between('node.LeftID', 'parent.LeftID', 'parent.RightID'))
->groupBy('node.ID')
->getQuery();
$result = $query->getArrayResult();
编辑:不要紧。我只是注意到你需要一个对象,而不是一个数组。
您可能想要查看以下两个扩展之一:https://github.com/Atlantic18/DoctrineExtensions/blob/master/doc/tree.md
或者,作为另一种选择,使用所需的字段创建一个新的对象类,将其标记为Doctrine的readOnly并为其创建自定义查询(您可以阅读在Doctrine中使用虚拟表的相关内容)。
https://stackoverflow.com/questions/26968809
复制相似问题