i am not sure why the sorting of a product attribute on compare page is not working same as on product page. Like on product page the atribute sort is
on product page
1 name
2 new attribute
3 new attribute1
4 color
but on comapre page when i am comp[aring the 2 products has same attributes the attribute sort order becomes
on compare page
1 name
2 color
3 new attribute
4 new attribute1
I have googled a lot to find answer but unable to find. Please help me to fix this issue.
Below are the functions which i find
public function getComparableAttributes()
{
if (is_null($this->_comparableAttributes)) {
$this->_comparableAttributes = array();
$setIds = $this->_getAttributeSetIds();
if ($setIds) {
$attributeIds = $this->_getAttributeIdsBySetIds($setIds);
$select = $this->getConnection()->select()
->from(array('main_table' => $this->getTable('eav/attribute')))
->join(
array('additional_table' => $this->getTable('catalog/eav_attribute')),
'additional_table.attribute_id=main_table.attribute_id'
)
->joinLeft(
array('al' => $this->getTable('eav/attribute_label')),
'al.attribute_id = main_table.attribute_id AND al.store_id = ' . (int) $this->getStoreId(),
array('store_label' => $this->getConnection()->getCheckSql('al.value IS NULL', 'main_table.frontend_label', 'al.value'))
)
->where('additional_table.is_comparable=?', 1)
->where('main_table.attribute_id IN(?)', $attributeIds);
$attributesData = $this->getConnection()->fetchAll($select);
if ($attributesData) {
$entityType = Mage_Catalog_Model_Product::ENTITY;
Mage::getSingleton('eav/config')
->importAttributesData($entityType, $attributesData);
foreach ($attributesData as $data) {
$attribute = Mage::getSingleton('eav/config')
->getAttribute($entityType, $data['attribute_code']);
$this->_comparableAttributes[$attribute->getAttributeCode()] = $attribute;
}
unset($attributesData);
}
}
}
return $this->_comparableAttributes;
}
/**
* Load Comparable attributes
*
* #return Mage_Catalog_Model_Resource_Product_Compare_Item_Collection
*/
public function loadComparableAttributes()
{
$comparableAttributes = $this->getComparableAttributes();
$attributes = array();
foreach ($comparableAttributes as $attribute) {
$attributes[] = $attribute->getAttributeCode();
}
$this->addAttributeToSelect($attributes);
return $this;
}
bUt i cant understand how to filter it by sort order .Please suggest
check the modifications in function below:
the file used is vendor/magento/module-catalog/Model/ResourceModel/Product/Compare/Item/Collection.php
But this is not the best way to do it. you need to override it as per Magento Standards.
I am working on it, will update shortly.
public function getComparableAttributes()
{
if ($this->_comparableAttributes === null) {
$this->_comparableAttributes = [];
$setIds = $this->_getAttributeSetIds();
if ($setIds) {
$attributeIds = $this->_getAttributeIdsBySetIds($setIds);
$select = $this->getConnection()->select()->from(
['main_table' => $this->getTable('eav_attribute')]
)->join(
['additional_table' => $this->getTable('catalog_eav_attribute')],
'additional_table.attribute_id=main_table.attribute_id'
)->joinLeft(
['al' => $this->getTable('eav_attribute_label')],
'al.attribute_id = main_table.attribute_id AND al.store_id = ' . (int)$this->getStoreId(),
[
'store_label' => $this->getConnection()->getCheckSql(
'al.value IS NULL',
'main_table.frontend_label',
'al.value'
)
]
)
->joinLeft( //add sort order to sort the attributes as per backend sort. -- Abid
['as' => $this->getTable('eav_entity_attribute')],
'as.attribute_id = main_table.attribute_id'
)
->where(
'additional_table.is_comparable=?',
1
)->where(
'main_table.attribute_id IN(?)',
$attributeIds
)
->order('as.sort_order') //sort by sort_order -- Abid
;
$attributesData = $this->getConnection()->fetchAll($select);
if ($attributesData) {
$entityType = \Magento\Catalog\Model\Product::ENTITY;
$this->_eavConfig->importAttributesData($entityType, $attributesData);
foreach ($attributesData as $data) {
$attribute = $this->_eavConfig->getAttribute($entityType, $data['attribute_code']);
$this->_comparableAttributes[$attribute->getAttributeCode()] = $attribute;
}
unset($attributesData);
}
}
}
return $this->_comparableAttributes;
}
On product page attributes are sorted like in attribute set.
On compare page attributes are not sorted at all.
You can rewrite function getComparableAttributes in class Mage_Catalog_Model_Resource_Product_Compare_Item_Collection and implement your own sort logic.
But note, that this function differs in different Magento versions. You can try to use free extension ET Advanced Compare or take part of code from this extension (code is available on bitbucket.org. link i on extension page)
Im trying to show each price for custom option in cart-page and checkout-page.
so I have changed this file: app/code/core/Mage/Catalog/Helper/Product/Configuration.php
here at line 75
$options[] = array(
'label' => $option->getTitle(),
'value' => $group->getFormattedOptionValue($itemOption->getValue()),
'print_value' => $group->getPrintableOptionValue($itemOption->getValue()),
'option_id' => $option->getId(),
'option_type' => $option->getType(),
'custom_view' => $group->isCustomizedView(),
//##my changing
'my_price' => $option->getPrice()
);
but this works only with fields, not works when my custom option was a select-box or in radio-buttons.
can someone help, Thanks!
Open up your template file
app/design/frontend/default/theme/template/checkout/cart/item/default.phtml
Find the foreach loop:
<?php foreach ($_options as $_option) : ?>
Within that foreach loop, add this code:
<?php
$optionId = $_option['option_id'];
$product = $_item->getProduct();
$option = $product->getOptionById($optionId);
$itemOption = $_item->getOptionByCode('option_' . $option->getId());
$price = false;
foreach ($option->getValues() as $values) {
if ($values->getId() == $itemOption['value']) {
$price = $values->price;
}
}
if ($price !== false) {
echo Mage::helper('core')->currency($price);
}
?>
Not sure if you've solved your problem yet, but for reference here's what I did..
The custom option prices are only available from the product object, not from the item object (which is what's readily available from the cart/item/default.phtml template). You'll have to find the product id from the item ($_item->getProductId()) then load this product. From there you'll want to load the product options, iterate through the custom option select values (in my case) and pull out the price when the option value ids match from the product and item objects ( http://subesh.com.np/2009/12/custom-options-product-magento/ for more help ).
Hope this helps you get on your way :)
I have a model to fetch data from mysql database. I am using the table and pagination library to display data. When displaying the data there is a column called "DELETE", which is used for deleting each rows. Instead of using the text "DELETE" I want to use an image. I have tried a lot to add it in the model but it is not working. Would you please kindly help me?
Thanks in Advance :)
function batch_list()
{
$config['per_page'] = 15;
$this->db->select('batchname, class, batchinstructor');
$this->db->order_by("batchid", "desc");
$rows = $this->db->get('batch',$config['per_page'],$this->uri->segment(3))->result_array();
$sl = $this->uri->segment(3) + 1; // so that it begins from 1 not 0
foreach ($rows as $count => $row)
{
array_unshift($rows[$count], $sl.'.');
$sl = $sl + 1;
$rows[$count]['batchname'] = anchor('batch_list/get/'.$row['batchname'],$row['batchname']);
$rows[$count]['Edit'] = anchor('update_student/update/'.$row['batchname'],'Edit');
$rows[$count]['Delete'] = anchor('report/'.$row['batchname'],'<img src="base_url().support/images/icons /cross.png" alt="Delete" />"'); //<<< This is where I actually tried/want to add the image
}
return $rows;
}
Please clarify what you mean by not working.
Anyway,
for now I am guessing your problem is your escaping, try:
anchor('report/'.$row['batchname'], '<img src="'.base_url().'support/images/icons/cross.png" alt="Delete" />');
or if you are using the html helper you can use
anchor('report/'.$row['batchname'], img('support/images/icons/cross.png'));
(if you want the alt attribute you will need to use the array form)
$img = array(
'src' => 'support/images/icons/cross.png',
'alt' => 'Delete'
);
anchor('report/'.$row['batchname'], img($img));
This must be a such a simple programming task that I absolutely cannot find any information about it on the net. Basically, I'm trying to DELETE product images. I want to delete all images from a product's media gallery. Can I do this without wading through a million lines of code for such a simple task?
Please note that I've already tried this:
$attributes = $product->getTypeInstance()->getSetAttributes();
if (isset($attributes['media_gallery'])) {
$gallery = $attributes['media_gallery'];
$galleryData = $product->getMediaGallery();//this returns NULL
foreach($galleryData['images'] as $image){
if ($gallery->getBackend()->getImage($product, $image['file'])) {
$gallery->getBackend()->removeImage($product, $image['file']);
}
}
}
This absolutely does not work. I'm trying to delete images during an import so that I do not keep accruing duplicates. Any help would be greatly appreciated.
Okay, this is how I finally fixed my problem.
if ($product->getId()){
$mediaApi = Mage::getModel("catalog/product_attribute_media_api");
$items = $mediaApi->items($product->getId());
foreach($items as $item)
$mediaApi->remove($product->getId(), $item['file']);
}
This is the link that finally set my head straight: http://www.magentocommerce.com/wiki/doc/webservices-api/api/catalog_product_attribute_media
Too bad it's not as simple as $product->getImages(), eh?
In Magento 1.7.0.2 I use this code for remove all images from a product gallery:
//deleting
Mage::app()->getStore()->setId(Mage_Core_Model_App::ADMIN_STORE_ID);
$mediaApi = Mage::getModel("catalog/product_attribute_media_api");
$items = $mediaApi->items($product->getId());
$attributes = $product->getTypeInstance()->getSetAttributes();
$gallery = $attributes['media_gallery'];
foreach($items as $item){
if ($gallery->getBackend()->getImage($product, $item['file'])) {
$gallery->getBackend()->removeImage($product, $item['file']);
}
}
$product->save();
With code from Davids Tay answer, I got the error:
Fatal error: Uncaught exception ‘Mage_Eav_Model_Entity_Attribute_Exception’ with message ‘SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (base_xxx.catalog_product_entity_media_gallery_value, CONSTRAINT FK_CAT_PRD_ENTT_MDA_GLR_VAL_VAL_ID_CAT_PRD_ENTT_MDA_GLR_VAL_ID FOREIGN KEY (value_id) REFERENCES `catalog_prod)’
To remove all images from a product gallery:
$product = Mage::getModel('catalog/product')->load($id);
$mediaGalleryAttribute = Mage::getModel('catalog/resource_eav_attribute')->loadByCode($entityTypeId, 'media_gallery');
$gallery = $product->getMediaGalleryImages();
foreach ($gallery as $image)
$mediaGalleryAttribute->getBackend()->removeImage($product, $image->getFile());
$product->save();
During deleting of images I found one interesting thing. When you try this code:
$galleryData = $product->getMediaGallery(); //this returns NULL
Media gallery object depends on how your product was created, if:
$product = Mage::getModel('catalog/product')->loadByAttr('sku', $sku);
then media gallery will be empty, if:
$product = Mage::getModel('catalog/product')->load($id);
then media gallery is object and you can use this object to delete images from db.
To delete images from file system you have to add such code:
#unlink(Mage::getBaseDir('media') . '\catalog\product\' . $image['file']);
but if you want to change image and name it like previous image (image1.png replace with image1.png) in this case you will have browser caching issue.
Also you can try to load media gallery for product:
$product->getResource()->getAttribute('media_gallery')->getBackend()->afterLoad($product);
This is the code I finally decided to use for this task.
protected function _removeMediaGalleryImages(Mage_Catalog_Model_Product $product)
{
$mediaGalleryData = $product->getMediaGallery();
if (!isset($mediaGalleryData['images']) || !is_array($mediaGalleryData['images'])) {
return;
}
$toDelete = array();
foreach ($mediaGalleryData['images'] as $image) {
$toDelete[] = $image['value_id'];
}
Mage::getResourceModel('catalog/product_attribute_backend_media')->deleteGallery($toDelete);
}
Hopefully this answer isn't unwelcome, as it's technically not a solution achieved via Magento programming as you ask, but I have successfully purged all gallery images myself for the same purpose simply by truncating the relevant tables in Magento 1.4.2.0 (I believe it's the same table structure in 1.5 as well).
TRUNCATE TABLE `catalog_product_entity_media_gallery`
TRUNCATE TABLE `catalog_product_entity_media_gallery_value`
Then follow up by removing all the image files within the /media/catalog/product directory.
I did look for a way to do this programmatically myself, but found this much more efficient and have experienced no negative side effects.
Just use this code to create .php file and place it to root folder of magento.
<?php
require_once 'app/Mage.php';
Mage::app();
Mage::app()->getStore()->setId(Mage_Core_Model_App::ADMIN_STORE_ID);
$products = Mage::getModel('catalog/product')->getCollection();
//->addAttributeToFilter('entity_id', array('gt' => 14000));
$mediaApi = Mage::getModel("catalog/product_attribute_media_api");
foreach($products as $product) {
$prodID = $product->getId();
$_product = Mage::getModel('catalog/product')->load($prodID);
$items = $mediaApi->items($_product->getId());
foreach($items as $item) {
$mediaApi->remove($_product->getId(), $item['file']);
}
}
?>
What About this
Mage::app()->getStore()->setId(Mage_Core_Model_App::ADMIN_STORE_ID);
$mediaApi = Mage::getModel("catalog/product_attribute_media_api");
$items = $mediaApi->items($product->getId());
$attributes = $product->getTypeInstance()->getSetAttributes();
$gallery = $attributes['media_gallery'];
foreach($items as $item){
if ($gallery->getBackend()->getImage($product, $item['file'])) {
$gallery->getBackend()->removeImage($product, $item['file']);
}
}
$product->save();
Fastest way to remove image,then follow below steps:
delete all records from
catalog_product_entity_media_gallery
catalog_product_entity_media_gallery_value'
table because magento is save all product image data at those table.
Then index from Index management from admin for set image black.
Then remove image from dir then goto Your magento dir at media/catalog/product and from this folder delete all file.
Another Process:
Andy Simpson,you need a script which is delete all product from your system which will delete from DB and file system.
Step1: Create a php at root direct of magento system which include Mage.php at first code.
require_once "YOURMAGENTODIR/app/Mage.php";
umask(0);
Step2: set current store is admin and set Developer mode
Mage::app('admin');
Mage::setIsDeveloperMode(true);
Step3: Get Product Collection and create a loop for get one product by one by one
$productCollection=Mage::getResourceModel('catalog/product_collection');
Step4: fetch product image by one and remove image one using below code:
$remove=Mage::getModel('catalog/product_attribute_media_api')->remove($product->getId(),$eachImge['file']);
FULL CODE:
<?php
require_once "YOURMAGENTODIR/app/Mage.php";
umask(0);
Mage::app('admin');
Mage::setIsDeveloperMode(true);
$productCollection=Mage::getResourceModel('catalog/product_collection');
foreach($productCollection as $product){
echo $product->getId();
echo "<br/>";
$MediaDir=Mage::getConfig()->getOptions()->getMediaDir();
echo $MediaCatalogDir=$MediaDir .DS . 'catalog' . DS . 'product';
echo "<br/>";
$MediaGallery=Mage::getModel('catalog/product_attribute_media_api')->items($product->getId());
echo "<pre>";
print_r($MediaGallery);
echo "</pre>";
foreach($MediaGallery as $eachImge){
$MediaDir=Mage::getConfig()->getOptions()->getMediaDir();
$MediaCatalogDir=$MediaDir .DS . 'catalog' . DS . 'product';
$DirImagePath=str_replace("/",DS,$eachImge['file']);
$DirImagePath=$DirImagePath;
// remove file from Dir
$io = new Varien_Io_File();
$io->rm($MediaCatalogDir.$DirImagePath);
$remove=Mage::getModel('catalog/product_attribute_media_api')->remove($product->getId(),$eachImge['file']);
}
}
If you want to remove more products like 1000 or 5000 then use bottom one with direct query.
Before try this one take backup of your database
<?php
require_once 'app/Mage.php';
umask(0);
Mage::app();
set_time_limit(0);
ini_set('display_error','1');
$resource = Mage::getSingleton('core/resource');
$connection = $resource->getConnection('core_write');
$id = 101;
$product = Mage::getModel('catalog/product')->load($id);
$q = "DELETE FROM `catalog_product_entity_media_gallery` where entity_id = '".$product->getId()."'";
$connection->query($q);
?>
Accessing the Database for such things is a bad idea.
You can delete images ( or reorder them by changing the 'position' value ) using the following snippet in a custom module ( for the sake of simplicity i'm using ObjectManager, but you should place ProductFactory and ProductRepositoryInterface in the constructor )
$objectManager = ObjectManager::getInstance();
//Get ProductFactory in order to instatiate the Product Object
$productFactory = $objectManager->get('\Magento\Catalog\Model\ProductFactory');
//We have to use ProductRepositoryInterface in order to save the changes bellow to the product
$productRepository = $objectManager->get('\Magento\Catalog\Api\ProductRepositoryInterface');
//Load a Product by ID in this case 1
$product = $productFactory->create()->load(1);
//Gets an array containing arrays representing each image in the gallery
$mediaGalleryEntries = $product->getMediaGalleryEntries();
//Here we delete every image, you can use conditions in foreach
foreach ($mediaGalleryEntries as $key => $imageEntry) {
unset($mediaGalleryEntries[$key]);
}
//Finally set the altered entries and save using productRepository
$product->setMediaGalleryEntries($mediaGalleryEntries);
$productRepository->save($product);
The code above tested in Magento 2.3 and it also removes images from the filesystem. You can use it to either delete or alter an entry ( change position, image roles etc )
To view each imageEntry you can access its data using $imageEntry->getData()
I had to do something similar not too long ago - needed to replace all product images during an import.
This link helped a lot: http://www.sharpdotinc.com/mdost/2010/03/02/magento-import-multiple-images-or-remove-images-durring-batch-import/
Hopefully it will give you a nudge in the right direction.
DELETE FROM catalog_product_entity_media_gallery WHERE value_id NOT IN (SELECT * FROM (SELECT MIN(value_id) FROM `catalog_product_entity_media_gallery` GROUP BY LEFT(value,17), entity_id having count(*) > 1) x)
why 17 ?
The expamle you have duplicate like this:
/0/0/000116810609_1.jpg
/0/0/000116810609_2.jpg
/0/0/000116810609_3.jpg
/0/0/000116810609_4.jpg
LEFT(value,17)
/0/0/000116810609
/0/0/000116810609
/0/0/000116810609
/0/0/000116810609
No they are duplicates ;)
Place the below script in magento root and execute
<?php
require_once("app/Mage.php");
umask(0);
Mage::app();
$ob = new Clean();
$ob->removemedia();
Class Clean {
function removemedia() {
$read = Mage::getSingleton('core/resource')->getConnection('core_read');
$select = $read->select()
->from('catalog_product_entity_media_gallery', '*')
->group(array('value_id'));
$flushImages = $read->fetchAll($select);
echo count($flushImages);
$array = array();
foreach ($flushImages as $item1) {
$array[] = $item1['value'];
}
$valores = $array;
$pepe = 'media' . DS . 'catalog' . DS . 'product';
$leer = $this->listDirectories($pepe);
foreach ($leer as $item) {
try {
$item = strtr($item, '\\', '/');
if (!in_array($item, $valores)) {
$valdir[]['filename'] = $item;
unlink('media/catalog/product' . $item);
}
} catch (Zend_Db_Exception $e) {
} catch (Exception $e) {
//Mage::log($e->getMessage());
}
}
}
function listDirectories($path) {
if (is_dir($path)) {
if ($dir = opendir($path)) {
while (($entry = readdir($dir)) !== false) {
if (preg_match('/^\./', $entry) != 1) {
if (is_dir($path . DS . $entry) && !in_array($entry, array('cache', 'watermark'))) {
$this->listDirectories($path . DS . $entry);
} elseif (!in_array($entry, array('cache', 'watermark')) && (strpos($entry, '.') != 0)) {
$this->result[] = substr($path . DS . $entry, 21);
}
}
}
closedir($dir);
}
}
return $this->result;
}
}
I want to write a controller that finds the different options for a given product (eg. Large, Medium, Small, Red, Blue etc...).
Can anyone show me the code I would write into my controller?
Additional details
I'm getting closer, but I still can't figure it out. Here's the code I wrote in my controller
$db = Mage::getModel('catalog/product')->load($productId);
print_r($db->getOptions()); // returns an empty array
echo $db->getHasOptions(); // echos 1
But when I do the print_r() on the second line, the getOptions returns an empty array. The third line echo's the value 1, which means there SHOULD BE options.
Additional Details
I tried clockworkgeek's solution of $db->getProductOptions(), that returned nothing. I tried $db->getProductOptionsCollection(), and got this output
Array
(
[totalRecords] => 0
[items] => Array
(
)
)
What's wrong with my code such that it is not returning the allowable product options?
Instead of getOptions() please try getCustomOptions() or getProductOptionsCollection() or getProductOptionsCollection()->load().
Edit
I tried this on a product I knew had options.
<?php
require 'app/Mage.php';
Mage::app();
$product = Mage::getModel('catalog/product')->load($productId);
foreach ($product->getProductOptions() as $option) {
print_r($option->debug());
}
And got something like this:
Array
(
[option_id] => 37
[product_id] => 8
[type] => multidate
[is_require] => 1
[sku] =>
[image_size_x] => 0
[image_size_y] => 0
[sort_order] => 1
[default_title] => Dates
[title] => Dates
)
However, getOptions() also worked for me so I don't know what's going on.
Post-edit
The confusion was one of semantics. A simple product can have "custom options", they allow creation of a few form fields which are recorded as part of the order. A configurable product uses "associated products" to create a form with conditional fields.
For example you might be selling socks that are large-green, small-green or large-blue - but no small-blue ones. With a simple product you would have a field for large/small and a field for blue/green - which allows the customer to select small-blue and that is wrong.
So to find the component parts of a configurable you might do something like this:
if ($product->isConfigurable()) {
$configurable = $product->getTypeInstance();
$childProducts = $product->getUsedProducts($product);
foreach ($childProducts as $child) {
// You have a $child now
}
}
To find the equivalent of getOptions() you need this:
if ($product->isConfigurable()) {
$configurable = $product->getTypeInstance();
$attributes = $configurable->getConfigurableAttributes($product);
// $attributes is a Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Type_Configurable_Attribute_Collection
foreach ($attributes as $attribute) {
// $attribute is a Mage_Catalog_Model_Product_Type_Configurable_Attribute
print $attribute->getLabel();
}
}
Mage_Catalog_Model_Product_Type_Configurable_Attribute doesn't have much to reveal about itself.
The above solution is perfect and I solved my problem using it. I was
trying to display the colors on the list. Here is my solution
if ($_product->isConfigurable()) {
$configurable = $_product->getTypeInstance();
$childProducts = $configurable->getUsedProducts($_product);
foreach ($childProducts as $child) {
$sku = $child->getSku();
$skuarr = explode('-',$sku);
$col = trim($skuarr[1]);
?>
<span class="colorbar" style="background:<?php echo $col?>;" title="<?php echo $col?>"> </span>
}
}