Symfony2,PHP 在从数据库中计算许多对象时降低查询权重
Symfony2, PHP decrease query weight when counting many objects from database
所以我的数据库中有 4 个 table。产品、类别、产品类别和产品子类别。
这些 table 处于多对多关系中。
所有产品都保存在table: Product.
所有类别和子类别保存在一个table:类别中。
一个产品可以有一个没有类别的子类别,可以有两个类别,或者可以有一个没有任何子类别的类别。
ProductCategory 和 ProductSubcategory 拥有所有关系。(product_id 和 category_id/subcategory_id)
现在在我的树枝中,我想计算类别和子类别包含多少产品。为此,我正在使用 Twig Extensions。
对于子类别:
计算一个子类别中有多少产品很容易,而且行得通。
在 Twig 中:
{% for subcategory in categories.children %}
[{{ getProductsBySubcategory(subcategory.id) }}]
{% endfor %}
函数:
public function getProductsBySubcategory($id)
{
$products = 0;
$subcategories = $this->doctrine->getRepository('MpShopBundle:ProductSubcategory')->findBy(array('subcategory' => $id));
foreach ($subcategories as $subcategory) {
$products++;
}
return $products;
}
类别:
类别有点不同。这里我想统计该分类下的所有商品以及该分类下所有子分类下的商品。首先,我检查该类别是否有产品,如果有,我将其添加到数组中。然后我检查这个类别是否有子类别。如果确实如此,我会从子类别中获取所有产品并将它们添加到同一个数组中。现在,如果产品同时属于类别和子类别,我不想重复计算。这就是为什么我将所有内容都存储在一个数组中(稍后 array_unique)。
我的树枝:
[{{ getProductsByCategory(categories.id)|length }}]
函数:
public function getProductsByCategory($id)
{
$category = $this->doctrine->getRepository('ApplicationSonataClassificationBundle:Category')->find($id);
$productCategories = $this->doctrine->getRepository('MpShopBundle:ProductCategory')->findBy(array('category' => $id ));
$productSubcategories = $this->doctrine->getRepository('MpShopBundle:ProductSubcategory')->findAll();
$products = array();
foreach($productCategories as $productCategory) {
array_push($products, $productCategory->getProduct()->getId());
}
foreach($productSubcategories as $productSubcategory) {
$subcategory = $productSubcategory->getSubcategory();
if($subcategory->getparent() == $category) {
array_push($products, $productSubcategory->getProduct()->getId());
}
}
$result = array_unique($products);
return $result;
}
问题:
在本地一切正常。我得到正确的号码。但是,当我切换到 Live 时,我得到 error:500。我想这可能是因为 Live 有数千种产品和分配的类别。所以 foreach 循环正在破坏服务器。或者可能是因为我将所有内容保存在数组中?
我该怎么办?是不是服务器问题,我需要增加一些东西?或者也许有一种方法可以在不使用数组和减少循环计数的情况下进行计数?但是如何检查重复项呢?
日志显示:
Allowed memory size of 536870912 bytes exhausted (tried to allocate 77 bytes) in /var/www/kd_cms/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/DataCollector/DataCollector.php on line 40
对于大型数据库对象,Dql 比 foreach 更快
// .../ProductCatRepository.php
public function findDistinctProductsByCat($catId)
{
$query = $this->createQueryBuilder('entity')
->leftjoin('entity.category', 'cat')
->andWhere('cat.id = :cat')
->setParameter('cat', $catId)
;
return $query->getQuery()->getResult();
}
// .../ProductSubCatRepository.php
public function findDistinctProductsByCatSubCat($catId)
{
$query = $this->createQueryBuilder('entity')
->leftjoin('entity.subcategory', 'subcat')
// maybe missing a leftJoin with cat idk your mapping
// ->leftJoin('subcat.category', 'cat')
// ->andWhere('cat.parent = :cat')
->andWhere('subcat.parent = :cat')
->setParameter('cat', $catId)
;
return $query->getQuery()->getResult();
}
public function getProductsByCategory($id)
{
$categoryId = $id;
$productsCat = $this->doctrine->getRepository('MpShopBundle:ProductCat')->findDistinctProductsByCat($categoryId);
$productsSubCat = $this->doctrine->getRepository('MpShopBundle:ProductSubCat')->findDistinctProductsByCatSubCat($categoryId);
// ArrayCollection::count()
return array('count_cat' => $productsCat->count(), 'product_subcat' => $productsSubCat->count(), 'result' => array_unique(array_merge($productsSubCat, $productsCat)));
}
所以我的数据库中有 4 个 table。产品、类别、产品类别和产品子类别。
这些 table 处于多对多关系中。
所有产品都保存在table: Product.
所有类别和子类别保存在一个table:类别中。
一个产品可以有一个没有类别的子类别,可以有两个类别,或者可以有一个没有任何子类别的类别。
ProductCategory 和 ProductSubcategory 拥有所有关系。(product_id 和 category_id/subcategory_id)
现在在我的树枝中,我想计算类别和子类别包含多少产品。为此,我正在使用 Twig Extensions。
对于子类别:
计算一个子类别中有多少产品很容易,而且行得通。
在 Twig 中:
{% for subcategory in categories.children %}
[{{ getProductsBySubcategory(subcategory.id) }}]
{% endfor %}
函数:
public function getProductsBySubcategory($id)
{
$products = 0;
$subcategories = $this->doctrine->getRepository('MpShopBundle:ProductSubcategory')->findBy(array('subcategory' => $id));
foreach ($subcategories as $subcategory) {
$products++;
}
return $products;
}
类别:
类别有点不同。这里我想统计该分类下的所有商品以及该分类下所有子分类下的商品。首先,我检查该类别是否有产品,如果有,我将其添加到数组中。然后我检查这个类别是否有子类别。如果确实如此,我会从子类别中获取所有产品并将它们添加到同一个数组中。现在,如果产品同时属于类别和子类别,我不想重复计算。这就是为什么我将所有内容都存储在一个数组中(稍后 array_unique)。
我的树枝:
[{{ getProductsByCategory(categories.id)|length }}]
函数:
public function getProductsByCategory($id)
{
$category = $this->doctrine->getRepository('ApplicationSonataClassificationBundle:Category')->find($id);
$productCategories = $this->doctrine->getRepository('MpShopBundle:ProductCategory')->findBy(array('category' => $id ));
$productSubcategories = $this->doctrine->getRepository('MpShopBundle:ProductSubcategory')->findAll();
$products = array();
foreach($productCategories as $productCategory) {
array_push($products, $productCategory->getProduct()->getId());
}
foreach($productSubcategories as $productSubcategory) {
$subcategory = $productSubcategory->getSubcategory();
if($subcategory->getparent() == $category) {
array_push($products, $productSubcategory->getProduct()->getId());
}
}
$result = array_unique($products);
return $result;
}
问题:
在本地一切正常。我得到正确的号码。但是,当我切换到 Live 时,我得到 error:500。我想这可能是因为 Live 有数千种产品和分配的类别。所以 foreach 循环正在破坏服务器。或者可能是因为我将所有内容保存在数组中?
我该怎么办?是不是服务器问题,我需要增加一些东西?或者也许有一种方法可以在不使用数组和减少循环计数的情况下进行计数?但是如何检查重复项呢?
日志显示:
Allowed memory size of 536870912 bytes exhausted (tried to allocate 77 bytes) in /var/www/kd_cms/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/DataCollector/DataCollector.php on line 40
对于大型数据库对象,Dql 比 foreach 更快
// .../ProductCatRepository.php
public function findDistinctProductsByCat($catId)
{
$query = $this->createQueryBuilder('entity')
->leftjoin('entity.category', 'cat')
->andWhere('cat.id = :cat')
->setParameter('cat', $catId)
;
return $query->getQuery()->getResult();
}
// .../ProductSubCatRepository.php
public function findDistinctProductsByCatSubCat($catId)
{
$query = $this->createQueryBuilder('entity')
->leftjoin('entity.subcategory', 'subcat')
// maybe missing a leftJoin with cat idk your mapping
// ->leftJoin('subcat.category', 'cat')
// ->andWhere('cat.parent = :cat')
->andWhere('subcat.parent = :cat')
->setParameter('cat', $catId)
;
return $query->getQuery()->getResult();
}
public function getProductsByCategory($id)
{
$categoryId = $id;
$productsCat = $this->doctrine->getRepository('MpShopBundle:ProductCat')->findDistinctProductsByCat($categoryId);
$productsSubCat = $this->doctrine->getRepository('MpShopBundle:ProductSubCat')->findDistinctProductsByCatSubCat($categoryId);
// ArrayCollection::count()
return array('count_cat' => $productsCat->count(), 'product_subcat' => $productsSubCat->count(), 'result' => array_unique(array_merge($productsSubCat, $productsCat)));
}