2

Below is my code following the post.

use \Magento\Catalog\Block\Product\View\AbstractView;

class ProductViewCount extends AbstractView
{ 
    /**
    * @var CollectionFactory
    */
    protected $_productRepo;


    /**
     * @var \Magento\Store\Model\StoreManagerInterface
     */
    protected $_storeManager;

    /**
     * @var \Magento\Reports\Model\ResourceModel\Product\Collection
     */
    protected $_prodCollection;


    /**
     * ProductViewCount constructor.
     *
     * @param \Magento\Catalog\Block\Product\Context $context
     * @param \Magento\Catalog\Model\ProductRepository $productRepo
     * @param \Magento\Framework\Stdlib\ArrayUtils $arrayUtils
     * @param \Magento\Reports\Model\ResourceModel\Product\Collection $prodCollection
     * @param array $data
     */
    public function __construct(
        \Magento\Catalog\Block\Product\Context $context,
        \Magento\Catalog\Model\ProductRepository $productRepo,
        \Magento\Framework\Stdlib\ArrayUtils $arrayUtils,
        \Magento\Reports\Model\ResourceModel\Product\Collection $prodCollection,
        array $data = []
    ) {
        $this->_productRepo = $productRepo;
        $this->_prodCollection = $prodCollection;
        $this->_storeManager = $context->getStoreManager();
        parent::__construct($context, $arrayUtils, $data);
    }

    /**
     * @param int $id
     *
     * @return mixed
     */
    public function getProductViewCount()
    {
        $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
        $_product = $objectManager->get('Magento\Framework\Registry')->registry('current_product');//get current product
        $productId = $_product->getId();
        /**
         * @var \Magento\Catalog\Model\Product\Interceptor $product
         */
        $prodData = $this->_prodCollection->addViewsCount()->getData();

        if (count($prodData) > 0) {
            foreach ($prodData as $product) {
                if ($product['entity_id'] == $productId) {
                    return (int) $product['views'];
                }
            }
        }

        return 0;
    }

}

In the above code, $prodData = $this->_prodCollection->addViewsCount()->getData(); always return an empty array. Please help.

1 Answer 1

3

You should specify the product attribute set id before you do the selection, like this:

$yourAttributeSet = 15; // or other
$prodData = $this->_prodCollection->setProductAttributeSetId($yourAttributeSet)->addViewsCount()->getData();

becouse in the addViewsCount method only one attribute set id is available:

$this->getSelect()->reset()->from(
        ['report_table_views' => $this->getTable('report_event')],
        ['views' => 'COUNT(report_table_views.event_id)']
    )->join(
        ['e' => $this->getProductEntityTableName()],
        $this->getConnection()->quoteInto(
            'e.entity_id = report_table_views.object_id AND e.attribute_set_id = ?',
            $this->getProductAttributeSetId()
        )
    )->where(
        'report_table_views.event_type_id = ?',
        $productViewEvent
    )->group(
        'e.entity_id'
    )->order(
        'views ' . self::SORT_ORDER_DESC
    )->having(
        'COUNT(report_table_views.event_id) > ?',
        0
    );

I think there is no way to select the data using this collection for many attribute sets.

Result sql looks like this:

SELECT COUNT(report_table_views.event_id) AS `views`,
  `e`.*
FROM `report_event` AS `report_table_views`
  INNER JOIN `catalog_product_entity` AS `e` ON e.entity_id = report_table_views.object_id AND e.attribute_set_id = '4'
WHERE (report_table_views.event_type_id = 1)
GROUP BY `e`.`entity_id`
HAVING (COUNT(report_table_views.event_id) > 0)
ORDER BY `views` DESC

As you can see the default attribute set is set to 4 (default). If we remove this condition from the select we can get statistics for the all of products:

SELECT COUNT(report_table_views.event_id) AS `views`,
  `e`.*
FROM `report_event` AS `report_table_views`
  INNER JOIN `catalog_product_entity` AS `e` ON e.entity_id = report_table_views.object_id
WHERE (report_table_views.event_type_id = 1)
GROUP BY `e`.`entity_id`
HAVING (COUNT(report_table_views.event_id) > 0)
ORDER BY `views` DESC

Result:

+-------+-----------+------------------+--------------+---------+-------------+------------------+---------------------+---------------------+
| views | entity_id | attribute_set_id | type_id      | sku     | has_options | required_options | created_at          | updated_at          |
+-------+-----------+------------------+--------------+---------+-------------+------------------+---------------------+---------------------+
|    33 |         1 |               15 | simple       | 24-MB01 |           0 |                0 | 2016-11-22 08:43:50 | 2016-11-22 08:43:50 |
|     3 |         3 |               15 | simple       | 24-MB03 |           0 |                0 | 2016-11-22 08:43:50 | 2016-11-22 08:43:50 |
|     1 |       611 |                9 | configurable | MS07    |           1 |                0 | 2016-11-22 08:44:24 | 2016-11-22 08:44:24 |
|     1 |       846 |               10 | configurable | MP09    |           1 |                0 | 2016-11-22 08:44:31 | 2016-11-22 08:44:31 |
|     1 |        20 |               11 | simple       | 24-UG01 |           0 |                0 | 2016-11-22 08:43:53 | 2016-11-22 08:43:53 |
+-------+-----------+------------------+--------------+---------+-------------+------------------+---------------------+---------------------+
5 rows in set (0.00 sec)

If you wish to get the same result you should write your own filter-method for the collection, like this (just remove the attribute set condition):

public function addViewsCount($from = '', $to = '')
{
    /**
     * Getting event type id for catalog_product_view event
     */
    $eventTypes = $this->_eventTypeFactory->create()->getCollection();
    foreach ($eventTypes as $eventType) {
        if ($eventType->getEventName() == 'catalog_product_view') {
            $productViewEvent = (int)$eventType->getId();
            break;
        }
    }

    $this->getSelect()->reset()->from(
        ['report_table_views' => $this->getTable('report_event')],
        ['views' => 'COUNT(report_table_views.event_id)']
    )->join(
        ['e' => $this->getProductEntityTableName()],
        'e.entity_id = report_table_views.object_id'
    )->where(
        'report_table_views.event_type_id = ?',
        $productViewEvent
    )->group(
        'e.entity_id'
    )->order(
        'views ' . self::SORT_ORDER_DESC
    )->having(
        'COUNT(report_table_views.event_id) > ?',
        0
    );

    if ($from != '' && $to != '') {
        $this->getSelect()->where('logged_at >= ?', $from)->where('logged_at <= ?', $to);
    }
    return $this;
}

Result in the debug window:

Result in the debug window

Example of the code:

/**
 * @var \Magento\Reports\Model\ResourceModel\Product\CollectionFactory
 */
protected $prodCollectionFactory;

/**
 * @var \Magento\Reports\Model\ResourceModel\Event\Type\CollectionFactory
 */
protected $eventTypeCollectionFactory;

/**
 * Channels constructor.
 * @param \Magento\Reports\Model\ResourceModel\Product\CollectionFactory $prodCollectionFactory
 * @param \Magento\Reports\Model\ResourceModel\Event\Type\CollectionFactory $eventTypeCollectionFactory
 * @throws Exception
 */
public function __construct(
    \Magento\Reports\Model\ResourceModel\Product\CollectionFactory $prodCollectionFactory,
    \Magento\Reports\Model\ResourceModel\Event\Type\CollectionFactory $eventTypeCollectionFactory
) {
    $this->eventTypeCollectionFactory = $eventTypeCollectionFactory;
    $this->prodCollectionFactory = $prodCollectionFactory;
}

/**
 * @param string $from
 * @param string $to
 * @return array
 * @throws Exception
 */
public function getReportData($from = '', $to = '')
{
    /** @var \Magento\Reports\Model\ResourceModel\Product\Collection $prodCollection */
    $prodCollection = $this->prodCollectionFactory->create();
    /** @var \Magento\Reports\Model\ResourceModel\Event\Type\Collection $eventTypeCollection */
    $eventTypeCollection = $this->eventTypeCollectionFactory->create();
    $catalogProductViewFilter = $eventTypeCollection->addFieldToFilter('event_name', 'catalog_product_view')->getFirstItem();
    if ($catalogProductViewFilter->getData('event_type_id')) {
        $productViewEvent = $catalogProductViewFilter->getData('event_type_id');
    } else {
        throw new Exception(__('Unknown event: catalog_product_view'));
    }

    $prodCollection->getSelect()->reset()->from(
        ['report_table_views' => $prodCollection->getTable('report_event')],
        ['views' => 'COUNT(report_table_views.event_id)']
    )->join(
        ['e' => $prodCollection->getProductEntityTableName()],
        'e.entity_id = report_table_views.object_id'
    )->where(
        'report_table_views.event_type_id = ?',
        $productViewEvent
    )->group(
        'e.entity_id'
    )->order(
        'views ' . \Magento\Framework\Data\Collection::SORT_ORDER_DESC
    )->having(
        'COUNT(report_table_views.event_id) > ?',
        0
    );

    if ($from != '' && $to != '') {
        $prodCollection->getSelect()->where('logged_at >= ?', $from)->where('logged_at <= ?', $to);
    }

    $prodData = $prodCollection->getData();

    return $prodData;
}
3
  • Could you share more specific how you setup xdebug ? Your current webserver run with xdebug in local dev enviroment
    – mrtuvn
    Jan 6, 2017 at 8:56
  • @mrtuvn you can share me your environment. I will share you. Jan 6, 2017 at 10:12
  • Hi Khoa i am using ubuntu16.10 with apache for local but can't setup xdebug work with phpstorm. Plan to setup docker include xdebug
    – mrtuvn
    Jan 6, 2017 at 10:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.