How to get views / clicks of a specific product - magento

As the title suggests, how do I get the number of views / clicks / impressions of a specific product in Magento. Any help is welcome.

This simple example will give you a list of products that have been viewed between the dates you specify + their view counts:
$fromDate = '2010-01-01';
$toDate = now();
$viewedProducts = Mage::getResourceModel('reports/product_collection')
->addViewsCount($fromDate, $toDate);
foreach($viewedProducts as $product) {
echo "ID: " . $product->getData('entity_id') . " - View Count: " . $product->getData('views') . "<br/>";
}

It helped me, get views just for one product.
$resource = Mage::getResourceModel('reports/event');
$select = $resource->getReadConnection()->select()
->from(array('ev' => $resource->getMainTable()), array(
'product_id' => 'object_id',
'view_count' => new Zend_Db_Expr('COUNT(*)')
))
->join(
array('et' => $resource->getTable('reports/event_type')),
"ev.event_type_id=et.event_type_id AND et.event_name='catalog_product_view'",'')
->group('ev.object_id')
->where('ev.object_id IN(?)', [$entity_id])
->where('ev.logged_at >= ?', $from)
->where('ev.logged_at <= ?', $to);
$views = $resource->getReadConnection()->fetchPairs($select);
$views = !empty($views[$entity_id]) ? $views[$entity_id] : 0;

Related

Avoiding repeated data in laravel querybuilder result

I am trying to write code to return the number of diseases diagnosed in a clinic after a given period either weekly, monthly or daily using jimmyjs laravel-report-generator using the code bellow,
$fromDate = $request->fromDate;
$toDate = $request->toDate;
$sortBy = 'updated_at';
$title = 'CHATTHE GROUP'; // Report title
$subTitle = 'Mobidity Report';
$total = 0;
$meta = [ // For displaying filters description on header
''=> $subTitle,
'From' => $fromDate . ' To: ' . $toDate,
'Generated By' => Auth::user()->name
];
$queryBuilder = Diagnosis::select(['diagnosis', 'updated_at']) // Do some querying..
->whereBetween('updated_at', [$fromDate, $toDate])
->distinct('diagnosis')
->orderBy($sortBy, 'ASC');
$columns = [ // Set Column to be displayed
'DISEASE' => 'diagnosis',
'NO OF CASES' => function($result){
return Diagnosis::where('diagnosis',$result->diagnosis)->count();
}, // if no column_name specified, this will automatically seach for snake_case of column name (will be registered_at) column from query result
'% TOTAL' => function($result){
return (Diagnosis::where('diagnosis',$result->diagnosis)->count()/$result->count()*100);
}
];
return ExcelReport::of($title, $meta, $queryBuilder, $columns)
->editColumns(['DISEASE', '% TOTAL'], [ // Mass edit column
'class' => 'right bold'
])
->showHeader(true)
->simple()
->download('mobidityReport');
This produces the following excel file
Which has the diseases repeated just as they repeat in the table, is there anyway to avoid this? I tried using distinct() but that gave an error.

How to get id of last purchase with multiple addresses?

I have a payment method that needs to be redirected to the page it like paypal, I can add a code block on the page of success but need to know if petido that was just completed was paid with my payment method, so I can redirect.
Note: several people say it is not possible to redirect payments with multishipping.
I just want to get the id of the application of the current purchase being multishipping.
I got this way, but it's not exactly what I want:
$fromDate = date('Y-m-d') . ' 0:0:0';
$toDate = date('Y-m-d H:i:s');
$orderCollection = Mage::getModel('sales/order')->getCollection()
->addFieldToFilter('customer_id', array('eq' => array(Mage::getSingleton('customer/session')->getCustomer()->getId())));
$orderCollection = $orderCollection->addAttributeToFilter('created_at', array('from'=>$fromDate, 'to'=>$toDate));
foreach($orderCollection as $order_row){
Solution:
$last_quote_id = Mage::getSingleton('checkout/session')->getLastQuoteId();
$orderCollection = Mage::getModel('sales/order')->getCollection()
->addFieldToFilter('customer_id', array('eq' => array(Mage::getSingleton('customer/session')->getCustomer()->getId())));
$orderCollection = $orderCollection->addFilter('quote_id', $last_quote_id);
foreach($orderCollection as $order_row){
if($order_row->getPayment()->getMethodInstance()->getTitle() == 'PagSeguro'){ $pagseguro = 1; }
echo $order_row->getId() . ' - ' . $order_row->getPayment()->getMethodInstance()->getTitle() . '<br />';
}

How to customize product URL?

How to customize the product URL to add certain attribute such as EAN on URL part? For example I want make url like `[domain]/cars/[sku]/tata-suv.html
Thanks
So, I am gonna be short and quick here.
1) You have to customize Mage_Catalog_Model_Url::getProductRequestPath. You have add following statements.
$sku = $product->getSku();
$requestPath = 'cars/' . $sku . "/" . $requestPath;
May be Add this just before following line:
if (strlen($requestPath) > self::MAX_REQUEST_PATH_LENGTH + self::ALLOWED_REQUEST_PATH_OVERFLOW) {
$requestPath = substr($requestPath, 0, self::MAX_REQUEST_PATH_LENGTH);
}
2) Customize the collection Mage_Catalog_Model_Resource_Url::_getProducts add sku in select field list:
$select = $adapter->select()
->useStraightJoin(true)
->from(array('e' => $this->getTable('catalog/product')), array('entity_id', 'sku'))
->join(
array('w' => $this->getTable('catalog/product_website')),
'e.entity_id = w.product_id AND w.website_id = :website_id',
array()
)
->where('e.entity_id > :entity_id')
->order('e.entity_id')
->limit($this->_productLimit);
Notice, sku in array('entity_id', 'sku')

Magento get products next by price

I need to get a collection of products next by price for specific product in some category.
For example: I have product White Shoes, it is located in Shoes category. I need to get next five products, that has higher price than White Shoes in Shoes category, and five products that has lower price.
Thanks for your help!
This can probably be cleaned up from an efficiency standpoint, but hopefully you get the gist of it. There are two variables you'll need to set, $product which is probably your White Shoes product as a Mage_Catalog_Model_Product object and $category which is your Shoes category as a Mage_Catalog_Model_Category object.
UPDATE
This is a better way to do it without loading the entire product collection for $category.
// Load up to 5 products with price <= $product
$fiveLower = Mage::getModel('catalog/product')->getCollection()
// Add whatever attributes you want here
->addAttributeToSelect(array(
'name',
'product_url',
'small_image',
))
// $category is an instance of Mage_Catalog_Model_Category
->addCategoryFilter($category)
// Both of these are required to get the price
->addMinimalPrice()
->addFinalPrice()
// Filter out the current product by id
->addAttributeToFilter('entity_id', array('neq' => $product->getId()));
// Filter by final_price <= $product and limit to 5.
$fiveLower->getSelect()
->having('final_price <= ?', $product->getFinalPrice())
->order('final_price')
->limit(5, 0);
// Load up to 5 products with price > $product
$fiveHigher = Mage::getModel('catalog/product')->getCollection()
->addAttributeToSelect(array(
'name',
'product_url',
'small_image',
))
->addCategoryFilter($category)
->addMinimalPrice()
->addFinalPrice();
$fiveHigher->getSelect()
->having('final_price > ?', $product->getFinalPrice())
->order('final_price')
->limit(5, 0);
echo 'These are the lower priced items:' . PHP_EOL;
foreach ($fiveLower as $item) {
echo $item->getName() . ' - ' . $item->getFinalPrice() . PHP_EOL;
}
echo 'These are the higher priced items:' . PHP_EOL;
foreach ($fiveHigher as $item) {
echo $item->getName() . ' - ' . $item->getFinalPrice() . PHP_EOL;
}
I had similar task, and here what I've done:
$customerGroupId = Mage::helper('customer')->getCustomer()->getGroupId();
$websiteId = Mage::app()->getStore()->getWebsiteId();
$finalPrice = $product->getFinalPrice();
$coreResource = Mage::getSingleton('core/resource');
$adapter = $coreResource->getConnection('catalog_read');
$prevSelect = $adapter->select()
->from(array('i' => $coreResource->getTableName('catalog/product_index_price')), array())
->join(
array('p' => $coreResource->getTableName('catalog/category_product')),
'p.product_id = i.entity_id',
array('product_id')
)
->where('p.category_id = ?', $categoryId)
->where('i.customer_group_id = ?', $customerGroupId)
->where('i.website_id = ?', $websiteId)
->where('p.product_id != ?', $product->getId())
->where('i.final_price < ?', $finalPrice)
->order('i.final_price DESC')
->limit(self::PRODUCTS_BLOCK_SIZE);
$lowerIds = array_reverse($adapter->fetchCol($prevSelect));
$nextSelect = $adapter->select()
->from(array('i' => $coreResource->getTableName('catalog/product_index_price')), array())
->join(
array('p' => $coreResource->getTableName('catalog/category_product')),
'p.product_id = i.entity_id',
array('product_id')
)
->where('p.category_id = ?', $categoryId)
->where('i.customer_group_id = ?', $customerGroupId)
->where('i.website_id = ?', $websiteId)
->where('p.product_id != ?', $product->getId())
->where('i.final_price > ?', $finalPrice)
->order('i.final_price ASC')
->limit(self::PRODUCTS_BLOCK_SIZE);
$higherIds = $adapter->fetchCol($nextSelect);
$lowerSliced = array_slice($lowerIds, -self::PRODUCTS_BLOCK_SIZE);
$requiredFromHigher = self::PRODUCTS_BLOCK_SIZE - count($lowerSliced);
$similarIds = array_merge(
$lowerSliced,
array_slice($higherIds, 0, $requiredFromHigher)
);
$collection = Mage::getResourceModel('catalog/product_collection')
->addAttributeToSelect('name')
->addAttributeToSelect('small_image')
->addAttributeToSelect('product_url')
->addAttributeToFilter('entity_id', array('in' => $similarIds))
->setPage(1, self::PRODUCTS_BLOCK_SIZE);

Magento filter product collection by multiple categories

Is there an easy way to filter a product collection by multiple categories? To get all items in any of the listed categories? addCategoryFilter doesn't seem to allow an array.
Is the only way to get the collections for each category of interest separately then merge them?
I understand it used to be possible with something like
addAttributeToFilter('category_ids',array('finset'=>array('1','2')))
or similar, but that this is no longer possible since 1.4.
Note: I am using 1.6, and in case it's of any use, I'm using something like this:
$product = Mage::getModel('catalog/product');
$_productCollection = $product->getCollection()
->addAttributeToSelect('*')
->addAttributeToFilter('status',1)
->addStoreFilter();
Here's a method that doesn't require modifications to core.
It's taken from this post with the addition of the 'group' clause to handle duplicate product records.
$categories = array(7,45,233);
$collection = Mage::getModel('catalog/product')->getCollection()
->addAttributeToSelect('*')
->joinField('category_id',
'catalog/category_product',
'category_id',
'product_id=entity_id',
null,
'left')
->addAttributeToFilter('category_id', array('in' => $categories));
$collection->getSelect()->group('e.entity_id');
The way Magento works now, is to get the Store, and on the store, you can get the categories from the storecollection like $oStoreCollection->addCategoryFilter(array('1','2'));
I came across a solution that might help you, found here at:
http://www.magentocommerce.com/boards/&/viewthread/201114/#t329230
The code they use, looks like this:
Override Mage/Catalog/Model/Resource/Eav/Mysql4/Product/Collection, and add the following methods:
public function addCategoriesFilter($categories)
{
$this->_productLimitationFilters['category_ids'] = $categories;
if ($this->getStoreId() == Mage_Core_Model_App::ADMIN_STORE_ID) {
$this->_applyZeroStoreProductLimitations();
} else {
$this->_applyProductLimitations();
}
return $this;
}
protected function _applyProductLimitations()
{
$this->_prepareProductLimitationFilters();
$this->_productLimitationJoinWebsite();
$this->_productLimitationJoinPrice();
$filters = $this->_productLimitationFilters;
// Addition: support for filtering multiple categories.
if (!isset($filters['category_id']) && !isset($filters['category_ids']) && !isset($filters['visibility'])) {
return $this;
}
$conditions = array(
'cat_index.product_id=e.entity_id',
$this->getConnection()->quoteInto('cat_index.store_id=?', $filters['store_id'])
);
if (isset($filters['visibility']) && !isset($filters['store_table'])) {
$conditions[] = $this->getConnection()
->quoteInto('cat_index.visibility IN(?)', $filters['visibility']);
}
// Addition: support for filtering multiple categories.
if (!isset($filters['category_ids'])) {
$conditions[] = $this->getConnection()
->quoteInto('cat_index.category_id=?', $filters['category_id']);
if (isset($filters['category_is_anchor'])) {
$conditions[] = $this->getConnection()
->quoteInto('cat_index.is_parent=?', $filters['category_is_anchor']);
}
} else {
$conditions[] = $this->getConnection()->quoteInto('cat_index.category_id IN(' . implode(',', $filters['category_ids']) . ')', "");
}
$joinCond = join(' AND ', $conditions);
$fromPart = $this->getSelect()->getPart(Zend_Db_Select::FROM);
if (isset($fromPart['cat_index'])) {
$fromPart['cat_index']['joinCondition'] = $joinCond;
$this->getSelect()->setPart(Zend_Db_Select::FROM, $fromPart);
}
else {
$this->getSelect()->join(
array('cat_index' => $this->getTable('catalog/category_product_index')),
$joinCond,
array('cat_index_position' => 'position')
);
}
$this->_productLimitationJoinStore();
Mage::dispatchEvent('catalog_product_collection_apply_limitations_after', array(
'collection' => $this
));
return $this;
}
protected function _applyZeroStoreProductLimitations()
{
$filters = $this->_productLimitationFilters;
// Addition: supprot for filtering multiple categories.
$categoryCondition = null;
if (!isset($filters['category_ids'])) {
$categoryCondition = $this->getConnection()->quoteInto('cat_pro.category_id=?', $filters['category_id']);
} else {
$categoryCondition = $this->getConnection()->quoteInto('cat_pro.category_id IN(' . implode(',', $filters['category_ids']) . ')', "");
}
$conditions = array(
'cat_pro.product_id=e.entity_id',
$categoryCondition
);
$joinCond = join(' AND ', $conditions);
$fromPart = $this->getSelect()->getPart(Zend_Db_Select::FROM);
if (isset($fromPart['cat_pro'])) {
$fromPart['cat_pro']['joinCondition'] = $joinCond;
$this->getSelect()->setPart(Zend_Db_Select::FROM, $fromPart);
}
else {
$this->getSelect()->join(
array('cat_pro' => $this->getTable('catalog/category_product')),
$joinCond,
array('cat_index_position' => 'position')
);
}
return $this;
}
It then gets called like this:
$collection = Mage::getModel('catalog/product')->getCollection()
->addAttributeToSelect('*')
->distinct(true) // THIS IS WHAT YOU NEED TO ADD
->addCategoriesFilter($category->getAllChildren(true)); // Make sure you don't forget to retrieve your category here.
HTH
If you want to filter on multiple categories, using AND (so a product must be in categorie A, B and C to show up, you need to have multiple joins:
$products = Mage::getModel('catalog/product')->getCollection()
->joinField('category_id_1', 'catalog/category_product', 'category_id', 'product_id=entity_id', null, 'left')
->joinField('category_id_2', 'catalog/category_product', 'category_id', 'product_id=entity_id', null, 'left')
->addAttributeToFilter('category_id_1', array('eq' => 358))
->addAttributeToFilter('category_id_2', array('eq' => 252))
// etc...
;
I managed to resolve this (after much trial and error) with the following code:
$collection = Mage::getModel('catalog/product')->getCollection();
$collection->addAttributeToFilter('status', 1);
$collection->addAttributeToSelect(array('name','sku','price','small_image'));
// Filter by multiple categories
$collection->joinField('category_id','catalog/category_product','category_id','product_id=entity_id',null,'left');
$data_cats = $this->getRequest()->getParam('categories');
// Or $data_cats = array(85,86,87,88);
$filter_cats = array();
foreach ($data_cats as $value_cats) {
$filter_cats[] = array(
'attribute' => 'category_id',
'finset' => $value_cats
);
}
$collection->addAttributeToFilter($filter_cats);
Hope this helps someone ;)
Magento 1.8.0.0;
Flat catalog enabled in admin;
Make sure you've cached the block in which you'll place this;
Don't add this in paid themes ..
The inner join hard-coded here reproduces this:
$collection->setVisibility(Mage::getSingleton('catalog/product_visibility')->getVisibleInCatalogIds());
without 'cat_index.category_id=2'
$category = Mage::getModel('catalog/category')->load(100);
$allChildsIds = $category->getAllChildren($category);
$visibility = Mage::getModel('catalog/product_visibility');
$collection = Mage::getResourceModel('catalog/product_collection');
$collection = $this->_addProductAttributesAndPrices($collection)
->addStoreFilter()
->setFlag('do_not_use_category_id', true)
->setFlag('disable_root_category_filter', true)
->addAttributeToSort('created_at', 'desc');
$whereCategoryCondition = $collection->getConnection()
->quoteInto('cat_index.category_id IN(?) ', $allChildsIds);
$collection->getSelect()->where($whereCategoryCondition);
$conditions = array();
$conditions[] = "cat_index.product_id = e.entity_id";
$conditions[] = $collection->getConnection()
->quoteInto('cat_index.store_id = ? ', Mage::app()->getStore()->getStoreId());
$conditions[] = $collection->getConnection()
->quoteInto('cat_index.visibility IN(?) ', $visibility->getVisibleInCatalogIds());
$collection->getSelect()->join(
array('cat_index' => $collection->getTable('catalog/category_product_index')),
join(' AND ', $conditions),
array()
);
$collection
->setPageSize(3)
->setCurPage(1);
$collection->load();
Filter Product Collection using multiple category ids
$all_categories = array('3','13','113');
$productCollection = Mage::getModel('catalog/product')->getCollection();
$productCollection->joinField('category_id', 'catalog/category_product', 'category_id',
'product_id = entity_id', null, 'left')
->addAttributeToSelect('*')
->addAttributeToFilter('type_id', array('eq' => 'simple'))
->addAttributeToFilter('category_id', array($all_categories));
foreach($productCollection as $product)
{
echo $product->getId() .$product->getName() . "<br/>";
}
You can remove the condition for product type i.e type_id or modify it as per requirement.
Reference: https://www.fmeextensions.com/blog/get-product-collection-by-category-id-magento-2/
$ids = [1,2,3,4,5,6,7];
$collectionFactory = $objectManager->get('\Magento\Catalog\Model\ResourceModel\Product\CollectionFactory')->create();
$products = $collectionFactory->addAttributeToSelect('*')
->addCategoriesFilter(['in' => $ids]);
foreach ($products as $product) {
echo $product->getId() . "<br />";
echo $product->getName() . "<br />";
echo $product->getProductUrl() . "<br />";
}

Resources