best way to get products by storeviews - php

That's my doubt. I have to export one XML file for each storeview on a magento hosting. This catalog has to contain all products available by storeview. The info that i need to export is at least: SKU, name, description,images url, categories which each product belongs and products URL.
I already have done the logic, but I am having problems with filtering the products, what I am doing now it's :
public function getXmlForAllStores()
{
foreach ($this->_storeManagerInterface->getWebsites() as $site):{
foreach ($site->getGroups() as $store): {
$rootCategoryId = $store->getRootCategoryId();
$rootCategory = $this->_rootCategory->load($rootCategoryId);
$catIdArray = $this->toIntArray($rootCategory->getAllChildren(true));
foreach ($store->getStores() as $storeview):{$collection = $this->_categoryLayer
->setCurrentCategory($rootCategory)
->getProductCollection()
->addWebsiteFilter($site);
//get xml string
$xmlData= $this->toXml($collection, $store, $storeview);
$fileName = $storeview->getCode()."feed.xml";
echo "filename: ". $fileName. "<br>";
//make file
$this->makeFile($xmlData,$fileName);
}endforeach;
}endforeach;
}endforeach;
return "ok";
}
as you can see, i am iterating on lowest scope to get different xml files for all storeviews on all stores-group contained on each website. but i can't find the way to retrieve data according the storeview, like name, description and more critical, the product url according the storeview.
the setstoreid filter doesn't work for what i want.
any help would be great, thanks for reading!

This feature is already available by default in Magento. For getting products for a particular store view, do the following:
Go to your Catalog > Products
Select a store view above the product list.
You are now viewing all products included in this store view.
Once you have the correct store view selected, select the products you want to Enable or Disable using the checkbox on the left.
Now, using the Actions dropdown menu on top right of the product list, choose 'Change Status', select 'Disabled' or 'Enabled' and hit the Submit button.

Related

How to pass array values from a function and populate on-the-fly a temporary Shop page?

friends.
I'm a newb dev building a website using Wordpress, WooCommerce, Gravity Forms, JetEngine and JetWooBuilder. The service is online photo printing, with the ability to upload user photos and choose between black or white paper.
I have the following situation:
Users upload files thru Gravity Forms.
Function hooked to gform_confirmation gets those files and generates a new product for each file. Function returns array of new products ids. (Function runs on Snippets plugin)
Here comes the trouble: Users must be able to select a color variation before adding the generated products to the cart. But how?
Possible scenarios:
Auto-add new products to cart and allow for variation selection directly on cart.
Could not make that work using my image swatches on cart.
Show custom boolean/switcher field on form page (either before submitting files, on the same page of the file upload form; or after submitting the files, on a second page of the form) and then somehow map that field to the correct variation and add to cart. I guess this could work but seems too much for my capabilities.
Use the product IDs that the function is returning and populate a temporary Shop page with these products, so the user can set the desired variation and add products to the cart. (hence the title of this post) This would work since the Shop page already has everything set up as far as styling, variation swatches and so on.
But how do I get those array values to do that? Could I pass thru an URL redirect after the function runs? And how to tell the Shop page to behave correctly?
I am using JetWooBuilder for a custom Shop page, so any solution that could include it would be the perfect match. But of course I am open to any help that comes on my way.
Thank you everyone in advance!
Below I leave that function for reference:
add_action( 'gform_confirmation', 'create_new_products_for_every_upload', 10, 4 );
function create_new_products_for_every_upload( $confirmation, $form, $entry, $ajax ) {
// Get uploaded-file ids from Media Library and loop thru
$file_ids = gp_media_library()->get_file_ids_by_entry( $entry, $form );
$fresh_prints_ids = array(); // Declare array to collect new product id's
if( $file_ids ) {
foreach( $file_ids as $field_id => $_file_ids ) {
foreach( $_file_ids as $file_id ) {
// Clone product template for each uploaded file
$duplicate_product = new WC_Admin_Duplicate_Product;
$new_product = $duplicate_product -> product_duplicate( wc_get_product( '3552' ) );
$new_product_id = $new_product->get_id(); // Get new product ID
$fresh_prints_ids[] = $new_product_id;
// Get current user details
$current_user = wp_get_current_user(); // Get WP_User object
$display_name = $current_user->display_name; // Get Display name
// Update new product
$new_product->set_status( 'private' );
$new_product->set_name( 'Photo by '.$display_name );
$new_product->set_image_id( $file_id );
$new_product->save();
}
}
}
return $fresh_prints_ids;
return $confirmation;
}
Footnote:
I am generating a new product for every uploaded file to allow users to set and order different quantities for each upload. Also this way users can order different variations of the same upload and they will display nicely separated on the cart. I found that this approach allows me to use as much as possible of the core WooCommerce capabilities, without the need for much further customization when dealing with the cart and checkout system. For security reasons, the products are private and direct access to media files are blocked thru a plugin. Image files stored on Gravity Forms folders are auto-erased after the products are created.
I couldn't really "pass the values", but I ended up using the following workaround:
Before the foreach loop:
Create new temporary category using wp_insert_term.
Set "Unique ID field" value from form to category name and slug.
Inside the foreach loop:
Assign temporary category to newly created products using wp_set_object_terms.
On "Confirmation" settings page of the Gravity form:
Redirect to site_url/category/{Unique_ID} using merge-tags to pull value from form entry.
This allowed me to present the user with a temporary Shop page using the same JetWoo Builder templates I already had set up, which was just what I needed. I still have some work to do, namely on bulk adding presented products to cart with one click and then cleaning up after all the process is done.

Display recently clicked/viewed product data on homepage Magento

I have two custom blocks in my homepage of Magento. One of the blocks displays all the products. And the other block should display the product which was recently clicked on/viewed.
I have created the observer for the event to get the clicked product data.
How can I use this data from observer to show that product's data in my second block in the homepage? I have to pass the data from the observer somehow.
Observer.php
<?php
include 'C:\wamp64\www\magento1924\app\code\local\Company\Namespace\Block\Recommended.php';
class Company_Namespace_Model_Observer {
public function getProductData($observer) {
//Uncomment the line below to log what is contained here:
//Mage::log($observer);
$data = new Company_Namespace_Block_Recommended();
$product = $observer->getProduct();
$pId = $product->getId();
$pName = $product->getName();
//Mage::log($pId);
Mage::log($pName);
$data->recommended($pId, $pName);
}
}
?>
Block file Recommended.php
<?php
class Company_Namespace_Block_Recommended extends Mage_Core_Block_Template
{
public function recommended($pId, $pName){
echo $pId;
echo $pName;
echo "Test!";
}
}
?>
Recommended.phtml
<h1>Recently viewed</h1>
<?php
$this->recommended();
?>
So I'm using this function recommended() to print out the clicked product's data. When I'm in the homepage and I click something, it takes me to the product view page in which I can also see (in the upper part) the product's name and id and also "Test!"(which was also echoed out in the function).
What I want to have is that since I'm also callin the same function recommended() out in the homepage (in the phtml file) I should see the products id, name and also "Test!". The problem is it is only showing the "Test!".
Am I doing something totally wrong?
I will suggested you to use cookies. Once a person clicks on a Product, save their IDs in cookie. And in the block class read the cookie values and grab the product collection like this:
$productIds = array('384','385','385'); // Dummy ids, fetch them from cookies
$products = Mage::getModel('catalog/product')
->getCollection()
->addAttributeToSelect('*')
->addAttributeToFilter('status', 1)
->addAttributeToFilter('visibility', 4)
->addIdFilter($productIds);
;
I hope this will give you an idea.
Please follow below step to get recently clicked/viewed on home page:
1- Click on CMS->Widgets
2- Click on the 'Add new widget instance'
3- Select Type->Recently Viewed Products
4- Select Design Package Theme->Your Theme
5- Click on Continue Button
6- In Frontend Properties
a. Give the Widget Instance Title
b. Assign to store views->All Store Views
c. Scroll a little down and you will notice a 'Layout updates' section
i. Click on Add Layout Updates
ii. Display On -> Specified Page (you can select any other option too)
Page->(Select your desired page)
Block Reference->(Select your reference to show it)
7- In Widget Options
a. Set 'Number of Products to display'
8- Click on 'Save' button and check your specified page. Don't forget to clear the cache if you don't see anything.

Unable to set product's category by code

According to
Mage::app()->getWebsite(true)->getDefaultStore()->getRootCategoryId();
ID of the default product category is '2' but:
public function initProduct(Varien_Event_Observer $observer)
// catalog_product_new_action event
{
$product = $observer->getEvent()->getProduct();
(...)
$productCatalog = Mage::getModel('catalog/product')->load($product->getId());
$productCatalog->setCategoryIds(array("2"));
$productCatalog->save();
$product->save();
(...)
doesn't change product's category at all. It's either wrong ID or wrong way of changing the category.
in the part of code you show, first you load a product, then you load a copy of the product, you change the categories of that copy, you save the copy and then, you save the original where the categories haven't been set.
the idea is to load the $product completely with $product->load() (I do not think it is necessary just for categories) and to change everything on that product and then save it. Or, keep the logic you did and not save the original product. The problem comes, in my opinion, from the double save with an unchanged product.

classification & display options in Magento - tags, categories, etc

In a Magento Shop, I would like to be able to classify products by some Classification mechanism (example: Tag, Category, Related products or somthing else?)
Then I could build a block that will show all classification titles. User can then click and get a page of all products in this classification.
Example:
Honda
Toyota
Chevrolet
Hyundai
Chrysler
We already use Categories, so using this classification mechanism would generate a list with many unwanted entries. I was thinking using
the tag system, but I have not found any references on the web that discusses using tags in this way. Maybe performnace is not good?
Here is a first attempt
// Here is a first attempt - I get all products with Category=4
// which is a "taggable" category. Then I list all related tags
require_once('app/Mage.php'); //Path to Magento
umask(0);
Mage::app();
// Category 4 is called "Category with tags"
$_categoryId = "4";
$_productCollection = Mage::getModel('catalog/category')->load($_categoryId)
->getProductCollection()
->addAttributeToSelect('*')
->addAttributeToFilter('status', 1)
->addAttributeToFilter('visibility', 4)
->setOrder('price', 'ASC');
foreach ($_productCollection as $_product):
$model=Mage::getModel('tag/tag');
$tags= $model->getResourceCollection()
->addPopularity()
->addStatusFilter($model->getApprovedStatus())
->addProductFilter($_product->getId())
->setFlag('relation', true)
->addStoreFilter(Mage::app()->getStore()->getId())
->setActiveFilter()
->load();
if(isset($tags) && !empty($tags)):
foreach($tags as $tag):
echo $tag->getName(). '<br/>';
endforeach;
endif;
endforeach;
Anyone have any code samples for listing tags, or a better way to do this?
A quick look in the database convinced me that maybe by-passing Magento's wonderful prodcutivity functions may be in order here...
$sql = "SELECT * FROM tag WHERE status = '1'";
$connection = Mage::getSingleton('core/resource')->getConnection('core_read');
foreach ($connection->fetchAll($sql) as $arr_row) {
print $arr_row['name'];
}
Have you tried Layered Navigation? It creates classification mechanism based on product attributes. When entering a category with Layered Navigation enabled, you are presented a list of product attributes that are set to appear there, and their possible values.
To enable Layered Navigation, go to Catalog -> Categories -> Manage Categories. There, select some category, go to Display Settings tab and set Is Anchor to Yes.
To allow or prevent a product attribute from showing in the Layered Navigation list, go to Catalog -> Attributes -> Manage Attributes. There, select an attribute you want and set Use In Layered Navigation option to a desired value.
It may not be exactly what you want, but is worth checking out.

Magento custom block takes long time to load with high number of SKU's

I had a freelancer code a block which shows a slider of featured products, with tabs corresponding to the sub-categories within.
.phtml file is here: http://pastebin.com/6jEexZxu
Here's an example of the page loading with only 20 or so SKU's (it may be a little slow, this installation hasn't been optimized at all): http://crunchconcepts.com.au/test_store/magento/
The category structure is as follows:
Slider (id=3)
-> PS3
-->Featured
-->Latest Added
-->On Sale
-> Xbox
-->Featured
-->Latest Added
-->On Sale
...and so on. This automatically loads a new slider for any sub-category of "Slider", and a new tab for every sub-sub-category.
This works great (although loading the products on demand when clicking to the next tab would be much better) when the store only had 100 or so SKU's, but when we imported 1000 test SKU's, the page loading hangs only when the homepage is accessed. The store runs fine on all other pages and functions, and only when the slider block is removed from the homepage, does it return to normal speeds.
It's running on a VPS at the moment, and the server load can spike up to 7-8 when trying to reteive the slider products.
Can anyone see why this is happening, and what I can do to fix this?
The freelancer has basically stopped responding to emails now that he has his money, so his advice is out of the equation!
Update:
Ok, so I'm trying to start from scratch, and I think I'm getting there... Or, at least, I'm learning a lot!
<?php
$categoryId = 3; // a category id that you can get from admin
$category = Mage::getModel('catalog/category')->load($categoryId);
$parentCat = Mage::getModel('catalog/category')->load($categoryId);
$childCategories = $parentCat->getChildren(); //Child category IDs separated by commas
$children1 = explode(',', $childCategories);
foreach ($children1 as $subCat1){
echo "<br/>";
$parentCat1 = Mage::getModel('catalog/category')->load($subCat1);
$childCategories1 = $parentCat1->getChildren(); //Child category IDs separated by commas
$mainCatName = $parentCat1->getName();
$children2 = explode(',', $childCategories1);
echo "<br/><br/>".$mainCatName;
foreach($children2 as $tabs){
$tab = Mage::getModel('catalog/category')->load($tabs);
echo "<br/><br/>".$tab->getName()."<br/>";
$_category = Mage::getModel('catalog/category')->load($tabs);
$_productCollection = Mage::getResourceModel('catalog/product_collection')
->addStoreFilter()
->addCategoryFilter($_category)
->addAttributeToSelect(array('name','url','small_image'));
if(!empty($_productCollection))
{
foreach ($_productCollection as $_product):
echo $_product->getName(); //get product name
endforeach;
}else{
echo "nothing!";}
}
}
?>
I've got this, and it displays the category names and ids, but whenever I try to load products, it loads every product in the store! I tried a couple other ways, but it loads the wrong product from a random category. Help!
The approach needs to be changed. Code like this should not be in a phtml template file. This needs to be rewritten as a proper Magento module with the Block class doing all the collection retrieval and filtering to get what you want. And the phtml only rendering your product slider display. Also, then proper block caching can be added so your pages load in finite time when cache is enabled.
There should almost never be a need to perform raw SQL on standard Magento entities such as products. Magento provides a good range of collection filters in the resource models that can be used to retrieve products and their information given a set of conditions. Also, special care needs to be taken to test this kind of code with both flat catalog categories and products enabled to make sure you can use this mode as it improves your Magento store performance for large numbers of SKUs.
Its slow because you are running multiple queries with a massive result set, then repeatedly loading entire models.
Something like this would be slightly more appropriate.
$_catId = 999;
$_category = Mage::getModel('catalog/category')->load($_catId);
$_productCollection = Mage::getResourceModel('catalog/product_collection')
->addStoreFilter()
->addCategoryFilter($_category);
Then you can iterate through that product collection.
BUT it should really be bundled into its own extension and given a block and model for the specific job - where you could programatically pass variables to it, making the code modular and re-usable.
Then it means you only need 1 template file and could do something as simple as this wherever you need it
{{block type='mynamespace/mymodule' template='mymodule/slider_template.phtml' cat_id="5" limit="3"}}

Categories