【问题标题】:Magento - cms/page collection - apply filter to return only pages which are unique to a given store id (ie not also assigned to other stores)Magento - cms/page collection - 应用过滤器以仅返回给定商店 id 唯一的页面(即未分配给其他商店)
【发布时间】:2012-05-13 11:59:55
【问题描述】:

我可以使用:

Mage::getModel('cms/page')->getCollection()->addStoreFilter($store_id);

检索按商店 ID 过滤的 CMS 页面集合。

但是我如何让它删除那些也分配给其他商店的?

ie:我不希望它返回具有“所有商店视图”作为商店视图的项目。 (或分配给该 CMS 页面的任何其他附加商店 ID。)它必须只返回该商店唯一的页面。

我正在扩展 Aitoc 权限模块,因此商店管理员无法查看或编辑可能影响其他商店的 CMS 页面和静态块。这涉及从网格中过滤这些项目。

【问题讨论】:

    标签: magento magento-1.5


    【解决方案1】:

    没有本地收集方法可以做到这一点,所以你需要

    1. cms_page_store 表中查询给定商店独有的页面

    2. 在您的过滤器中使用上述结果

    我没有对以下内容进行全面测试,但它应该工作(如果不能,它将为您自己的查询提供一个良好的开端)

    $page     = Mage::getModel('cms/page');
    $resource = $page->getResource();
    $read     = $resource->getReadConnection();
    
    #$select   = $read->query('SELECT page_id FROM ' . $resource->getTable('cms/page_store') . ' GROUP BY store_id');
    
    //set total count to look for.  1 means the page only appears once.
    $total_stores_count_to_look_for = '1';
    
    //get the table name.  Need to pass through getTable to ensure any prefix used is added
    $table_name                     = $resource->getTable('cms/page_store');
    
    //aggregate count select from the cmd_page_store database
    //greater than 0 ensures the "all stores" pages aren't selected
    $select = $read->query('SELECT page_id as total
    FROM '.$table_name.' 
    WHERE store_id > 0 
    GROUP BY page_id
    HAVING count(page_id) = ?',array($total_stores_count_to_look_for));
    
    //fetch all the rows, which will be page ids
    $ids   = $select->fetchAll(); 
    
    //query for pages using IDs from above
    $pages = Mage::getModel('cms/page')->getCollection()->addFieldToFilter('page_id',array('in'=>$ids));
    
    foreach($pages as $page)
    {
        var_dump($page->getData());
    }
    

    如果您有成千上万个 CMS 页面,那么更改 cms/page 集合的 select 以加入聚合表数据可能是值得的。我将把它作为练习留给读者,因为这些连接可能会变得很棘手。

    【讨论】:

    • @Vitaly Muminov 在下面说什么。
    • 谢谢 - 这是一个非常有见地的答案。
    【解决方案2】:
    $collection = Mage::getModel('cms/page')->getCollection();
    $collection->getSelect()
        ->join(
            array('cps' => $collection->getTable('cms/page_store')),
            'cps.page_id = main_table.page_id AND cps.store_id != 0',
            array('store_id')
        )
        ->columns(array('stores_count' => new Zend_Db_Expr('COUNT(cps.store_id)')))
        ->group('main_table.page_id')
        ->having('stores_count = ?', 1)
        ->having('cps.store_id = ?', $storeId)
    ;
    

    【讨论】:

    • 这看起来是一个不错的解决方案,但它会产生错误:未找到列:1054 Unknown column 'stores_count' in 'have Clause' 当我尝试它时。这看起来很奇怪,因为它看起来像是在它上面的数组中声明的。
    • 哎呀,我犯了一个错误。答案现在包含正确的查询。
    • 感谢您的检查 - 在“有子句”中仍然得到“未知列 'stores_count'。我在 Magento 1.5 上做这件事——所以它可能是问题的一部分。
    【解决方案3】:

    将 Alan 和 Vitaly 提出的解决方案的一些元素与我自己的繁琐理解融合在一起,我通过以下代码实现了我所需要的。

    具体来说,我正在扩展 Aitoc 权限模块,以便商店管理员无法查看或编辑可能影响其他商店的 CMS 页面和静态块。这涉及从网格中过滤这些项目。

    $collection = Mage::getModel('cms/page')->getCollection();
    $collection->addStoreFilter(Mage::helper('aitpermissions')->getStoreIds());
    $conn = Mage::getSingleton('core/resource')->getConnection('core_read');
    $page_ids = array();
    foreach($collection as $key=>$item) {
        $page_id = $item->getId();
        $results = $conn->fetchAll("SELECT * FROM cms_page_store 
                                    WHERE page_id = ".$page_id.";");
        $count = 0;
        $arr_stores = array();
        foreach($results as $row) {
            $arr_stores[] = $row['store_id'];
            $count++;
        }
    
        //We dont want to show the item if any of the following are true:
           //The store id = 0 (Means its assigned to All Stores)
           //There is more than one store assigned to this CMS page         
        if( in_array('0',$arr_stores) || $count>1) {
                //This removes results from the grid (but oddly not the paging)
            $collection->removeItemByKey($key); 
        }
        else {
            //build an array which we will use to remove results from the paging
            $page_ids[] = $page_id; 
        }
    }
    
    //This removes results from paging (but not the grid)
    $collection->addFieldToFilter('page_id',array('in'=>$page_ids)); 
    

    我不知道为什么我需要使用两种不同的方法来过滤分页和网格。 该站点使用 magento 1.5,因此可能存在与此相关的问题。

    无论哪种方式,这个解决方案都对我有用。

    【讨论】:

      【解决方案4】:

      我的解决方案是通过join将字段store_id添加到页面集合中,并使用集合方法addFieldToFilter()。

      $pages = Mage::getModel('cms/page')->getCollection();
      
      $pages->getSelect()->joinInner(
           array('cms_page_store' => 'cms_page_store'),
           'main_table.page_id = cms_page_store.page_id',
           array()
      );
      
      $pages->addFieldToFilter('store_id', ['in' => [1, 2]]);
      

      【讨论】:

        猜你喜欢
        • 2014-02-22
        • 1970-01-01
        • 2020-08-08
        • 2023-04-06
        • 1970-01-01
        • 1970-01-01
        • 2016-01-19
        • 2017-10-06
        • 1970-01-01
        相关资源
        最近更新 更多