Hide Products without images magento - magento

I have followed this answer to hide products without images on the category listing page. It worked nicely for a while.
Now, for some reason it seems the products without images are still showing up on the listing page.
Any ideas as to why this may be happening?
Note:
The same list.phtml page is being used.
Thank you.

Add the following to list.phtm:
//$_productCollection=$this->getLoadedProductCollection();
$_productCollection = clone $this->getLoadedProductCollection();
$_productCollection->clear()
->addAttributeToFilter('small_image', array('neq' => 'no_selection'))
->load();
This answer recommended the following:
->addAttributeToFilter('image', array('neq' => 'no_selection'))
Whereas I have set it to:
->addAttributeToFilter('small_image', array('neq' => 'no_selection'))
The reason the previous answer did not work was because the product collection doesn't load the regular image, and therefore the regular image cannot be added as an attribute to filter, so instead, I added the small_image as the attribute to filter.
You can also try R.S's answer where he adds the image to the page and hence the collection. You may have to also add all attributes using:
->addAttributeToSelect('*')

There are some tricks to keeping Magento in line. One thing I've learned is that the Magento Model will change for many different reasons, and its kinda hard to figure out why. There are better ways to do this (modifying the collection, etc) but it sometimes just does not work and you don't have days to figure out why.
If you want a surefire way to make sure your image exists, use the following code... It may not be the 'magento way' but it works, and I tested it on my site (Magento EE 1.12). Put it in a function, or use it directly in your phtml if you want!
It basically just makes sure the URL exists.
$exists = false;
$entity_id = 8800;
$product = Mage::getModel('catalog/product')->load($entity_id);
$mediaUrl= Mage::getBaseUrl('media');
$imageUrl = $mediaUrl . "catalog/product" . $product->getImage();
$file_headers = #get_headers($imageUrl);
if($file_headers[0] == 'HTTP/1.1 404 Not Found') {
$exists = false;
}
else {
$exists = true;
}
var_dump($exists);
var_dump($imageUrl);
echo '<img src="' . $imageUrl . '" />';
$exists will either be true (image does exist) or false (image does not)

I think that the issue is that you are trying to get the 'image' (base image) property on the list.phtml (by default i can only access the thumbnail, small_image).
On list.phtml (not loading the full product resource like on view.pthml)
echo $_product->getImage() //null
echo $_product->getThumbnail() // path/name.jpg
echo $_product->getSmallImage() // path/name.jpg
I think you may need to add adding something like this to app/design/frontend/default/yourtheme/layout/catalog.xml
<action method="addAttribute"><name>image</name></action>
See How to get access to custom Image Attribute in list.phtml in Magento

Related

How can I make a dynamic canonical tag on Magento's internal search?

When I do a internal search in magento (i.e search for a product) and after that try to filter the results (filter by price), some querystrings are added to my URL, but Google point's out like a duplicated content.
Magento have the canonical tag feature on categories and product's, but I couldnt find it in "search" queries and filters.
My question is: How can i add canonical tags on magento's search when I filter the results?
We generally recommend to hide internal site search from getting indexed ( you can do that with the standard "NOINDEX, FOLLOW" tags).
But if for some reason you really need to index it, here is the simplest code that lets you add a canonical URL.
Please note that in this case we use the default search. In this code, the canonical URL contains only the search query, without any filters.
/app/design/frontend/{your_package}/{your_theme}/template/page/html/head.phtml
Add this code:
<?php
$controller = Mage::app()->getFrontController();
if(is_object($controller) && is_callable(array($controller, 'getAction'))){
$action = $controller->getAction();
if(is_object($action) && is_callable(array($action, 'getFullActionName'))){
$fullActionName = $action->getFullActionName();
}
}
if(!empty($fullActionName) && $fullActionName == 'catalogsearch_result_index')
{
$request = $this->getRequest();
$params = $request->getParams();
if(!empty($params['q'])){
$action = $request->getActionName();
if($action == 'index'){
$action = '';
}
$canonicalUrl = $this->getBaseUrl() . $request->getRouteName() .DS. $request->getControllerName() .DS. $action . '?q=' . $params['q'];
echo "<link rel=\"canonical\" href=\"$canonicalUrl\" />";
echo "<!--Canonical URL was added from template head.phtml-->";
}
}
?>
Also note that we recommend to use the toolbar parameter limit=all. Without it, it'll be hard to get the right Canonical URL on the pages with pagination.
In case this parameter is turned on, (you can check it under System->Configuration->Catalog->Catalog->Frontend->Allow All Products per Page), you need to add 'limit=all' to the URL.
P.S. To learn more about the topic, please read this guide by Google: http://googlewebmastercentral.blogspot.com/2013/04/5-common-mistakes-with-relcanonical.html
You can avoiding crawler through robots.txt as well
User-agent: *
Disallow: /catalogsearch/
above code will avoid search pages getting crawled in google.

Including magento header outside of magento. Problems with $this->getChildHtml()

I have researched this topic pretty thoroughly but can't find an answer.
I am trying to include a Magneto head into a WordPress page. I created a new wordpress template and added the following code to it.
try {
require_once ABSPATH . '/app/Mage.php';
if (Mage::isInstalled()) {
$mage = Mage::app();
Mage::getSingleton('core/session', array('name' => 'frontend'));
if(Mage::getDesign()->designPackageExists('xxx')) {
Mage::getDesign()->setPackageName('xxx');
Mage::getDesign()->setTheme('xxx');
}
// init translator
$mage->getTranslator()->init('frontend');
// init head
$head = $mage->getLayout()->getBlockSingleton('page/html_head');
} }
Then a bit further down in the template I have
echo $head->toHtml();
Now what is happening is some parts of the head are being echoed and some parts are not.
When I go into head.phtml and try to figure out what is happening I notice that any line that contains
$this->getChildHtml()
does not get echoed.
I looked at this example and noticed that the author is manually adding the html and CSS. Why is this? Why don't they get added automatically? Is this a related problem
Thanks
To show a block that is generated inside the header block, you need to first create it, then set it as child of the header block.
eg. Here is how I display within Wordpress a Magento header block, including the currency drop-down block that was generated by getChildHtml() inside the original header.phtml:
Mage::getSingleton('core/session', array('name' => 'frontend'));
$session = Mage::getSingleton("customer/session");
$layout = Mage::getSingleton('core/layout');
$headerBlock = $layout->createBlock('page/html_header')->setTemplate('page/html/header.phtml');
$currencyBlock = $layout->createBlock('directory/currency')->setTemplate('currency/currency.phtml');
$headerBlock->setChild('currency_selector', $currencyBlock);
$headerBlock = $headerBlock->toHtml();
Then you can write the block where you need it on the page:
echo $headerBlock;
I know it's a little late but hopefully this helps others with this issue.
Are you familiar with how magento layouts are rendered? With $head = $mage->getLayout()->getBlockSingleton('page/html_head'); you create a new block without any children. That's why the author needs to add JS and CSS again. To load the default head block have a look at this thread Load block outside Magento. You can load it with $layout->getBlock('head')->toHtml();.

Getting image for bundle product child products, currently returning placeholder

My problem:
I need to retrieve the main product image from a cut down product object which is supplied by the class: Mage_Bundle_Model_Resource_Price_Index
My code demonstrating the issue:
$_product = $this->getProduct();
$_options = Mage::helper('core')->decorateArray($this->getOptions());
foreach($_options as $_option):
$_selections = $_option->getSelections();
foreach ($_option->getSelections() as $tmpsel) {
var_dump($tmpsel->getImageUrl());
}
Which returns my placeholder image:
http://dev.dev/media/catalog/product/cache/7/image/265x/0dc2d03fe217f8c83829496872af24a0/placeholder/default/logo_3.jpg
My horrible and hacky work around:
In order to get correct image Url, I have resorted to loading a completely new product object, which is terribly inefficient.
foreach ($_option->getSelections() as $tmpsel) {
$product = Mage::getModel("catalog/product")->load($tmpsel->getId());
$image = Mage::helper('catalog/image')->init($product, 'image');
var_dump($image."");
}
This returns correctly:
http://dev.dev/media/catalog/product/cache/7/image/0dc2d03fe217f8c83829496872af24a0/M/P/MP1428219-107-Main.jpg
What I want to do:
I want to be able to use the catalog/image helper with the selection ($tmpsel), but when I try I end up getting the placeholder image again.
foreach ($_option->getSelections() as $tmpsel) {
$image = Mage::helper('catalog/image')->init($tmpsel, 'image');
var_dump($image."");
}
Extra Info:
Anything I think of that could help I will add here
Cut down product object includes some reference to image
'small_image' => string '/M/P/MP1428219-107-Main.jpg'
'thumbnail' => string '/M/P/MP1428219-107-Main.jpg'
Description of getSelection()
In: ./app/code/core/Mage/Bundle/Model/Resource/Price/Index.php
* Retrieve bundle options with selections and prices by product
The function uses low level SQL to generate the collection, so I can always extend it to add options if needed, not sure which options though.
Thank you for reading, hope someone can give me a good way of doing this, will keep updated.
Init() method require a product object
init(Mage_Catalog_Model_Product $product, $attributeName, $imageFile=null)
Try
<?php echo $this->helper('catalog/image')->init($tmpsel, 'small_image')->resize(40,40); ?>
You do not have 'image' but you do have 'small_image' attribute
See Magento - how to retrieve bundled option images
To get the full web address you can use this code:
Mage::getSingleton('catalog/product_media_config')->getMediaUrl($product->getImage());
The limitation is that bring only the main image.
Oh wow, I guess I can thank you stack overflow for making me write my thoughts down.
After comparing the full product object and the semi product object I can see that I was calling the incorrect attribute name for catalog/image
$image = Mage::helper('catalog/image')->init($tmpsel, 'image');
Should have been
$image = Mage::helper('catalog/image')->init($tmpsel, 'small_image');

Magento: How to retrieve the minimal price of (i.e.) grouped products?

I am trying to display a grouped product's price on the product view page in Magento 1.7.0.2, just as it is being displayed in the category product listing ("Starting at: xx.xx"). I thought I could just use
$this->getPriceHtml($_product, true);
to do so because it works the same way in the category product listing, but as everything I tried to do in Magento, it is not that easy because that method doesnt return anything on the product view page.
I looked a little deeper into Magento's code and figured out that the cause of this problem is the product's minimal price data not being set on the product view page ($_product->getMinimalPrice() returns null).
Therefore I did some research on how to load a product's minimal price which brought up ideas like
$_product->getPriceModel()->getMinimalPrice($_product);
which doesnt work because apparently that method was deprecated and removed in one of the last updates or
$priceModel = Mage::getResourceModel('catalogindex/price');
$priceModel->setStoreId(Mage::app()->getStore()->getId());
$priceModel->setCustomerGroupId(Mage::getSingleton('customer/session')->getCustomerGroupId());
$minimalPrices = $priceModel->getMinimalPrices(array($_product->getId()));
$minimalPrice = $minimalPrices[0];
$_product->setData('minimal_price', $minimalPrice['value']);
$_product->setData('minimal_tax_class_id', $minimalPrice['tax_class_id']);
which doesnt work either because the table 'catalogindex_minimal_price' is empty.
So my question is, how does Magento load the minimal price in the category product listing?
I looked a little deeper into Magento's code and tracked down how Magento loads the products of the product list.
When viewing the product list, the product collection is loaded by the model Mage_Catalog_Model_Layer, which adds the minimal price and other stuff to the products in the collection by adding joins to the collection’s SQL, but I have not yet found a model that does the same thing for single products instead of collections.
Because I don’t want to use a direct SQL query, I checked out the CatalogIndex module, but that module seems not to be working at all because all its indexing tables are empty or even corrupted.
$data_grouped = Mage::getModel("catalogindex/data_grouped");
$minimal = $data_grouped->getMinimalPrice(array($_product->getId()), Mage::app()->getStore());
looked good at first but it gives me the following error:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'catalog_product_index_price.value' in 'field list'
The CatalogIndex module is either deprecated or I’m just too stupid to enable it.
However, I have now created a workaround in my price.phtml template, which uses the same method to retrieve the minimal price and tax percents as the product list does:
At the beginning of the template I added the following:
$this->setProduct(
Mage::getModel("catalog/product")->getCollection()
->addAttributeToSelect(Mage::getSingleton("catalog/config")->getProductAttributes())
->addAttributeToFilter("entity_id", $this->getProduct()->getId())
->setPage(1, 1)
->addMinimalPrice()
->addFinalPrice()
->addTaxPercents()
->load()
->getFirstItem()
);
which may not be the perfect solution, but it does the job and it does it a little cleaner than iterating over all child products and finding the minimal price that way.
This isn't an answer as much as a big HTML comment on Subsurf's answer. If you're reading this, you might be implementing your own custom module to display a product list. In my case, it's a single page just for wholesalers. My goal was to get a list of my own company's products and give them a list like it was another category. I copied my template's list.phtml to my new content.phtml. But getMinimalPrice() was returning NULL, meaning that when this code calls the getPriceHtml(), price.phtml wasn't showing wholesale pricing.
I did a simple module with index controller and a content.phtml. Using the boilerplate I see all over the net, in the indexController.php file, change:
$block = $this->getLayout()->createBlock(
'Mage_Core_Block_Template',
'b2b',
array('template' => 'b2b/content.phtml')
);
to:
$block = $this->getLayout()->createBlock(
'Mage_Catalog_Block_Product_List',
'b2b',
array('template' => 'b2b/content.phtml')
);
This does a lot of the heavy lifting for you to show the products list correctly.
Now, on to the template file, in my case content.phtml, you get your product collection and then use Subsurf's code in the top of the foreach() which repeats.
$_productCollection = Mage::getModel('catalog/product')
->getCollection()
// ->addAttributeToSelect('*')
// doesn't work ->addAttributeToSelect('special_price')
->addAttributeToSelect('sku')
->addAttributeToFilter('status', 1)
->addAttributeToFilter('visibility', 4)
// http://stackoverflow.com/questions/1332742/magento-retrieve-products-with-a-specific-attribute-value
->addFieldToFilter( array(
array('attribute'=>'manufacturer','eq'=>'143')
, array('attribute'=>'manufacturer','eq'=>'139')
))
;
echo "<p>There are ".count($_productCollection)." products: </p>";
echo '<div class="category-products">';
// List mode
if($this->getMode()!='grid') {
$_iterator = 0;
echo'<ol class="products-list" id="products-list">';
foreach ($_productCollection as $_product) {
?> <li class="item<?php if( ++$_iterator == sizeof($_productCollection) ): ?> last<?php endif; ?>">
<?php
$_product=Mage::getModel("catalog/product")->getCollection()
->addAttributeToSelect(Mage::getSingleton("catalog/config")->getProductAttributes())
->addAttributeToFilter("entity_id", $_product->getId())
->setPage(1, 1)
->addMinimalPrice()
->addFinalPrice()
->addTaxPercents()
->load()
->getFirstItem()
);
echo "Minimal price: ".$_product->getMinimalPrice()."<br>\n";
Since this isn't a single product's page and I'm using other template code, $this->setProduct() didn't do anything for me. I guessed if there was a set, there might be a get, so $_product=$this->getProduct() was the magic my template's price.phtml needed to work properly. Then I noticed I could just assign the Mage:: in setProduct() directly to $_product.
Thanks, Subsurf!!!
There is another way that will still allow you to use $this->getPriceHtml($_product, true); in your template, which then handles all the complex price display rules and puts "Starting at" before grouped product prices.
I'm using this for a custom featured product block. In a block class I have this function:
class MyCompany_Catalog_Block_Product_Featured extends Mage_Catalog_Block_Product_Abstract {
public function setGroupedProductPrice($group_product) {
$prices = array();
foreach ($group_product->getTypeInstance()->getChildrenIds($group_product->getId()) as $ids) {
foreach ($ids as $id) {
$product = Mage::getModel('catalog/product')->load($id);
$prices[] = $product->getPriceModel()->getPrice($product);
}
}
ksort($prices);
$group_product->setPrice(array_pop($prices));
}
}
Then in the template:
<?php
if ($_product->getTypeId() == 'grouped')
$this->prepareGroupedProduct($_product);
echo $this->getPriceHtml($_product, true);
?>
The following does the trick without using a product collection:
$priceResource = Mage::getResourceSingleton('catalogindex/price');
$select = $priceResource->getReadConnection()->select();
$select->from(
array('price_table' => $priceResource->getMainTable())
)
->where('price_table.entity_id = ?', $_product->getId())
->where('price_table.website_id = ?', Mage::app()->getStore()->getWebsiteId())
->where('price_table.customer_group_id = ?', Mage::getSingleton('customer/session')->getCustomerGroupId());
$result = $priceResource->getReadConnection()->fetchRow($select);
This code is adapted from \Mage_CatalogIndex_Model_Resource_Price::getMinimalPrices and made suitable for one single product.

magento tracking pixel

There are two variables which are required in the tracking pixel which needs to be placed on category, product info, cart and confirmation page.
I've managed to get the Prod list and Prod working, however, the second two are causing me problems.
I can echo out the sku in the cart, however, the products are configurable products so it's duplicating the sku in the output. The code I'm using is below:
<?php
// $items = Mage::getModel('checkout/cart')->getQuote()->getAllItems();
$items = Mage::getSingleton('checkout/session')->getQuote()->getAllItems();foreach($items as $item) { echo ''.$item->getSku().' ';}
?>
How do i change this to just display the one configurable SKU?
The second element is the Category name that the product exists in, Any one got any ideas on that? I've tried multiple variations but they've either broke the page or returned nothing.
Any help would be appreciated. If someone could also give me examples of how these would work on the confirmation page as well, that would be great.
Thanks for your help.
Check for the products visibility (simple products attached to a configurable would not be visible):
$items = Mage::getSingleton('checkout/session')->getQuote()->getAllItems();
foreach($items as $item) {
if ($item->getProduct()->isVisibleInSiteVisibility()) {
echo ''.$item->getSku().' ';
}
}
With regards to the category name, a product can appear in multiple categories so im not sure how you want to handle that. Also, there is a concern that you are beginning to duplicate code across several template files. You will want to consider moving this all out to a block.
Anyway, to get the category names that the product belongs to here is at least one method of doing this...
$categoryCollection = $item->getProduct()->getCategoryCollection()
->addAttributeToSelect('name');
foreach($categoryCollection as $category) {
echo $category->getData('name') . "<br/>";
}

Resources