Magento - get product collection of all products - php

I need a custom product collection of all products. Currently there are no categories which contain all products of the store (as there are 8000 products we can not add them in to one extra category).
What I need is on a particular CMS page the product collection of all products is displayed.
So far I have a CMS page with the block:
{{block type="catalog/product_list" template="catalog/product/list.phtml"}}
I have created an module to override 'Mage_Catalog_Block_Product_List'
I believe the function I need to edit would be 'protected function _getProductCollection()'
As we can see in the block call theres no category specified. What I need is in the overidden _getProductCollection function is all products in the store returned.
Is there any way this can be achieved?

There are several ways you can get the list of products from a store.
Try this way :
<?php
$_productCollection = Mage::getModel('catalog/product')
->getCollection()
->addAttributeToSort('created_at', 'DESC')
->addAttributeToSelect('*')
->load();
foreach ($_productCollection as $_product){
echo $_product->getId().'</br>';
echo $_product->getName().'</br>';
echo $_product->getProductUrl().'</br>';
echo $_product->getPrice().'</br>';
}
?>

Don't override the List block, this will have an effect on the real product listing pages.
The simple way to to copy the file to the local namespace and rename it:
from:
app/code/core/Mage/Catalog/Block/Product/List.php
to:
app/code/local/Mage/Catalog/Block/Product/Fulllist.php
You can then use your new block without having to make a full module, and it will mean your List block will work the same and not break anything on your store.
You can then safely modify the as required:
/**
* Retrieve loaded category collection
*
* #return Mage_Eav_Model_Entity_Collection_Abstract
*/
protected function _getProductCollection()
{
$collection = Mage::getModel('catalog/product')->getCollection();
// this now has all products in a collection, you can add filters as needed.
//$collection
// ->addAttributeToSelect('*')
// ->addAttributeToFilter('attribute_name', array('eq' => 'value'))
// ->addAttributeToFilter('another_name', array('in' => array(1,3,4)))
//;
// Optionally filter as above..
return $collection;
}
You can then use your new block like so:
{{block type="catalog/product_fulllist" template="catalog/product/list.phtml"}}

Related

How to change product by a storeview in magento 2

In the backend you can set different settings for a product by a storeview.
But how can you get those products by a storeview.
Getting a product could be done like this, but how to get the product data from a different storeview
$product = $objectManager->create('Magento\Catalog\Model\Product')->load($product->getId());
The other answer here uses the ObjectManager directly and the deprecated load function, so for a more best-practices approach you can use the ProductRepositoryInterface to load product within a specific store scope.
After injecting an instance of ProductRepositoryInterface (e.g. called $_productRepository) into your class, use the following with $storeId set to the ID of your desired store view.
$oProduct = $_productRepository->get('mysku',false, $storeId, false);
Or to fetch by ID:
$oProduct = $_productRepository->getById($productId,false, $storeId, false);
Use ->setStoreId(0)
Single product
To load a single product by storeview use this code
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$product = $objectManager->create('Magento\Catalog\Model\Product')->setStoreId(0)->load($product->getId());
Product collection
To load multiple products by a storeview, you could use the product collection like this:
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$collection = $productCollection->create()
->addAttributeToSelect('*')
->setStoreId(0)
->load();
Change in ->setStoreId(0) the 0 to your storeview ID
Use store id 0 to change te product default data

Magento: Build custom product collection of all configurable products in stock

I'm trying to build a product collection of all configurable products which are 'in-stock' or 'is-saleable'. These require two different models to be used. My working method is:
$collectionConfigurable = Mage::getResourceModel('catalog/product_collection')->addAttributeToFilter('type_id', array('eq' => 'configurable'));
foreach ($collectionConfigurable as $_configurableproduct) {
$product = Mage::getModel('catalog/product')->load($_configurableproduct->getId());
if ($product->isSaleable()) {
// do something
}
}
However this script is REALLY slow and I have a feeling it's wasting resources running as it will be loading and going through EVERY configurable product.
What I'm trying to achieve is to get the $collectionConfigurable and make it in-stock items only.
Another resource cites this as a method to get in stock items.
Mage::getSingleton('cataloginventory/stock')->addInStockFilterToCollection($this->_productCollection);
But I'm not sure how to combine them or use it properly, I've tried this:
$collectionConfigurable = Mage::getResourceModel('catalog/product_collection')->addAttributeToFilter('type_id', array('eq' => 'configurable'));
$instockConfigs = Mage::getSingleton('cataloginventory/stock')->addInStockFilterToCollection($collectionconfigurable);
This returns with the following error:
Fatal error: Call to a member function joinField() on a non-object in /srv/magento/app/code/core/Mage/CatalogInventory/Model/Resource/Stock.php on line 197
My "naive to the finer details of the stock system" approach would be to
Create a stock item collection, grabbing only the in stock items.
Use that collection to create an array of instock product IDs
Create a product collection with the configurable filter, as well as an entity_id filter using the collected product IDs
The code for that would look like this.
//create a stock item collection with a `is_in_stock` filter
$collection = Mage::getModel('cataloginventory/stock')
->getItemCollection()
->addFieldToFilter('is_in_stock');
//capture the product ids of the in stock stock items
$product_ids = array();
foreach($collection as $item)
{
$product_ids[] = $item->getProductId();
}
$products = Mage::getModel('catalog/product')
->getCollection()
->addAttributeToSelect('*')
->addFieldToFilter('entity_id',array('in'=>$product_ids))
->addFieldToFilter('type_id','configurable');
foreach($products as $product)
{
var_dump($product->getData());
}
That said, your code is slow, in part, because you're reloading each product inside the loop, generating a new series of SQL statements
$product = Mage::getModel('catalog/product')->load($_configurableproduct->getId());
Also, the addInStockFilterToCollection only works with a Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Link_Product_Collection collection. Take a look at the doc block on the method.
/**
* Adds filtering for collection to return only in stock products
*
* #param Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Link_Product_Collection $collection
* #return Mage_CatalogInventory_Model_Stock $this
*/
public function addInStockFilterToCollection($collection)
{
$this->getResource()->setInStockFilterToCollection($collection);
return $this;
}

Magento - Adding a random product to .../template/catalog/product/view.phtml

I would like to add 3 links to random products on the .../template/catalog/product/view.phtml template.
Based on list.phtml, I tried adding:
<?php
$_productCollection=$this->getLoadedProductCollection();
foreach ($_productCollection as $_randomProduct) {
echo $_randomProduct->getProductUrl();
}
?>
But I'm not getting a list back of URL's. How can I get an array of other product's links and images?
That code lets you down because $this in view.phtml is not the same $this as in list.phtml.
If you wanted to get some products relevant to the current product's category try this:
$_productCollection = $_product->getCategory()->getProductCollection();
Alternatively if you didn't care where they come from:
$_productCollection = Mage::getResourceModel('catalog/product_collection')
->setStore(Mage::app()->getStore());
To get the randomness this little trick will help:
$_productCollection->setPageSize(3)
->getSelect()->order('RAND()');
Now you can use the collection in a foreach loop.

Magento - load only configurable products

I have the following code:
$_productCollection = $this->getLoadedProductCollection();
foreach ($_productCollection as $_product)
{
if ($_product->_data['type_id'] == 'configurable')
{
...
}
}
While it does what it's supposed to do, it greatly slows down page load time. Is it possible to load only configurable products and remove the check for 'configurable'? The store has 12000 products, about 700 are configurable and the rest are child simple products.
I found the following code which returns all configurable products. I need only the products within the current category:
$collectionConfigurable = Mage::getResourceModel('catalog/product_collection')
->addAttributeToFilter('type_id', array('eq' => 'configurable'));
The problem with getLoadedProductCollection() is it's already loaded - the products' data has already been retrieved from the database. Just using the current category's product collection isn't good enough either, that will ignore the "layers" (attribute filters). The trick is to remove the loaded products from the list first.
// First make a copy, otherwise the rest of the page might be affected!
$_productCollection = clone $this->getLoadedProductCollection();
// Unset the current products and filter before loading the next.
$_productCollection->clear()
->addAttributeToFilter('type_id', 'configurable')
->load();
print_r($_productCollection) has it's issues too, you're not just outputting the products but also all details of the resource that is the database connection, and cached values, and the products' individual resources, and so on...
In this case I think you would be happier with:
print_r($_productCollection->toArray())
All those solutions didn't work for me, try this:
$_productCollection1 = Mage::getResourceModel('catalog/product_collection')
->addAttributeToSelect('*')
->addAttributeToFilter('type_id','configurable');
foreach ($_productCollection1 as $product1) {
echo $product1->getName();
...
}
It works but don't know if it's correct (I'm new to Magento). Let me know please.
The way you're doing this requires all products to be loaded before you parse through and filter them. This is probably closer to what you're looking for:
$_productCollection = $this ->getLoadedProductCollection()
->addAttributeToFilter('type_id','configurable');
Try following
$collection = Mage::getModel('catalog/product')->getCollection();
$collection->addAttributeToFilter('type_id','configurable');
foreach($collection as $product)
{
}
For loading configurable and simple as well try
$collection->addAttributeToFilter('type_id', array('in' => array('configurable','simple')));
Here is the code for getting only configurable products:
$Config_products = Mage::getModel('catalog/product')->getCollection()
->addAttributeToFilter('type_id','configurable');
Use \Magento\Catalog\Model\ResourceModel\Product\Collection $_productcollection,
public function getConfigProducts() {
$configproducts = $this->_productcollection;
$configproducts->addAttributeToSelect('*');
$configproducts->addAttributeToFilter('status',\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED);
$configproducts->addAttributeToFilter('show_in_price_page', array('eq' => 1));
$configproducts->addAttributeToFilter('type_id', array('eq' => "configurable"));
return $configproducts;
}
If you change Visibility of simple product to "Not Visible Individually", Magento will not load it to display in product list page.

Copy and Paste Category in Magento

I want to copy my first category to a second category in Magento.
What should I do?
Thanks,
Wesley.
By code:
<?php
$category = Mage::getModel('catalog/category')
->load(123); // The ID of the category you want to copy.
$copy = clone $category;
$copy->setId(null) // Remove the ID.
->save();
If you want to do it in a programmatic way you can use the Magento API.
Use:
catalog_category.info - to read a category
catalog_category.create - to create a new one by copying data from existing.
Here are the docs for category API
I wouldn't clone the category object, but rather do something like this (using the Magento API - http://www.magentocommerce.com/wiki/doc/webservices-api/catalog_category ):
get the category which must be copied
$source_category = Mage::getModel('catalog/category')->load($id);
Create a new category using the API
$CategoryApi = new Mage_Catalog_Model_Category_Api();
$parent_id = /* Location for the new category */
$new_category_id = $CategoryApi->create(
$parent_id,
array(
/* Attributes to fill with source category values. */
)
);
Get the source category products and place them in the new category, again with the API.
$products = $CategoryApi->assignedProducts(source_category->getId());
foreach($products as $product)
{
$CategoryApi->assignProduct($product->getId())
}
Above must be done recursively for each subcategory.
Note: Using the API ensures your code will still work when you upgrade the Magento core.
All the replies here were not complete. I did a script that does the total Creating the new category, subcategories and assigning the products to them.
public function run()
{
$categoryId = 123;
// Change this if you want the copy to be under another category than the default
$baseCategoryId = 2;
$category = Mage::getModel('catalog/category')->load($categoryId);
$defaultCategory = Mage::getModel('catalog/category')->load($baseCategoryId);
$this->duplicate($category, $defaultCategory, 1);
}
private function duplicate($categoryToClone, $parentCategory, $level)
{
// This will clone the clild and assign it to the new parent
$newCategory = clone $categoryToClone;
$newCategory->setPath($parentCategory->getPath())
->setParentId($parentCategory->getId())
->setId(null);
// Optional, Only change the new with suffix with "new" for the first
if ($level == 1) {
$newCategory->setUrlKey($categoryToClone->getUrlKey() . '-new')
->setName($categoryToClone->getName() . '(new)');
}
// Assign all products from the cloned category to the new
$newCategory->setPostedProducts($categoryToClone->getProductsPosition());
$newCategory->save();
// Applies the changes to the subcategories infinite levels
$subcategories = $categoryToClone->getChildrenCategories();
if (count($subcategories) > 0) {
foreach ($subcategories as $subcategory) {
$this->duplicate($subcategory, $newCategory, ++$level);
}
}
}
You can't with the admin interface, you need. to create a script with the category api.
Sorry you cannot copy/paste Category directly in Magento Admin panel through the interface, which Catalog Products can offer with the help of "Duplicate" button.
I suppose you will need to write a script fetching the category details by first loading the Category model with the required Category ID.
This forum post contains instructions and code for importing your categories from a CSV file.
Good luck,
JD
I think you want to export products from a specific cat and import it to another one. if it's so use the steps bellow:
login to magento backend
navigate to System -> Import/Export
Create a new advanced profile for your cat
export it
now import it in the same fashion
Sometime we need to copy same products to another category.(Like we have two stores with same category or within same store need to copy the category products to somewhere else)
Adding product from back-end is very time consuming process you can do it by code.
You can create a file in your root directory copy-products.php with the following code to copy product:
<?php
require_once ( "app/Mage.php" );
umask(0);
// Initialize Magento
Mage::app();
$category = Mage::getModel('catalog/category');
$category->load('24'); // Category id you want to copy
$collection = $category->getProductCollection();
$collection->addAttributeToSelect('*');
foreach ($collection as $product) {
$product->getId();// Now get category ids and add a specific category to them and save?
$categories = $product->getCategoryIds();
$categories[] = 29; // Category id you want to add
$product->setCategoryIds($categories);
$product->save();
}
?>

Categories