Tuesday, June 7, 2011

Add category names to the product list

In order to add category names to the product list (grid)
you have 2 options. For both of them you have to edit app/design/frontend/{interface}/{theme}/template/catalog/product/list.phtml
1. Add the category (categories) link(s) for all the products in any list (search results included). Keep in mind that any product can be in one or more categories (or none).
At the top of the file add this:
<?php $_category = Mage::regsitry('current_category');?>
<?php if ($_category) : ?>
<a href="<?php echo $_category->getUrl();?>"><?php echo $_category->getName();?></a>
<?php endif;?>
2.
At the top of the file add this:
<?php $_categories = array();?>
This will work as some kind of cache.
Now below the $_product item (inside the foreach) add this
<?php foreach ($_product->getCategoryIds() as $categoryId) : ?>
 <?php if (isset($_categories[$categoryId])) : ?>
  <?php $_category = $_categories[$categoryId];?>
 <?php else:?>
  <?php $_category = Mage::getModel('catalog/category')->setStoreId(Mage::app()->getStore()->getId())->load($categoryId);?>
  <?php $_categories[$categoryId] = $_category;?>
 <?php endif;?>
 <a href="<?php echo $_category->getUrl()?>"><?php echo $_category->getName();?></a>
 <?php //if you want only the first category link add a break here; ?>
<?php endforeach;?>
This second method covers all the cases but it's a little bit slower than the first one.

Thursday, June 2, 2011

How to change 'My account' menu link in the customer name for logged in users

Hello.
Here is how you can change the 'My account' menu link into the customer name (John Doe) for logged in users.
I'm going to use the same system that the checkout module uses to add the cart and the checkout link.
First of all create a new module that will extend the Mage_Customer module. We will call it Custom_Customer.
In app/code/local folder create a folder named 'Custom'.
[UPDATE]
Inside the Custom folder create a folder 'Customer'.
/* Thanks for the comment 'Anonymous' - see first comment*/
[/UPTATE]
In this folder create a subfolder called 'Block' (because we need a new block).
Inside 'Block' folder create a php file named 'Links.php' with this content
<?php 
class Custom_Customer_Block_Links extends Mage_Core_Block_Template
{
/**
ads my account link to some block
*/
    public function addAccountLink()
    {
        $parentBlock = $this->getParentBlock();//this block will have a parent
        if ($parentBlock && Mage::helper('core')->isModuleOutputEnabled('Mage_Customer')) {//check if the customer module is not disabled
            $customerSession = Mage::getSingleton('customer/session');//the customer session

            if( $customerSession->isLoggedIn() ) {//if the customer is logged in get the name
                $text = $customerSession->getCustomer()->getName();
            } else {//if the customer is not logged in print 'My account'
                $text = Mage::helper('customer')->__('My Account');
            }
//add the block to the set of links.
            $parentBlock->addLink($text, Mage::helper('customer')->getAccountUrl(), $text, false, array(), 10, null, '');
        }
        return $this;
    }
}

Now create the config.xml file for the module.

In folder 'Custom' create a subfolder 'etc' and inside it the config.xml with this content.
[UPDATE]
inside the Customer folder create a subfolder 'etc' and inside it the config.xml with this content.
/* Thanks for the comment 'Anonymous' - see first comment*/
[/UPTATE]
<?xml version="1.0"?>
<config>
    <modules>
        <!-- the  version of the module-->
        <Custom_Customer>
            <version>0.0.1</version>
        </Custom_Customer>
    </modules>
    <!-- Hack to tell magento that our block overrides a core block (that does not exits) -->
    <global>
     <blocks>
      <customer>
       <rewrite>
        <links>Custom_Customer_Block_Links</links>
       </rewrite>
      </customer>
     </blocks>
    </global>
</config>
Now we have to use out block in the design.
in app/design/frontend/{interface}/{theme}/layout/customer.xml replace this:
<default>
        <!-- Mage_Customer -->
        <reference name="top.links">
            <action method="addLink" translate="label title" module="customer"><label>My Account</label><url helper="customer/getAccountUrl"/><title>My Account</title><prepare/><urlParams/><position>10</position></action>
            
        </reference>
    </default>
with this
<default>
        <!-- Mage_Customer -->
        <reference name="top.links">
            <!-- THe block we've just created and the method to add the link -->
            <block type="customer/links" name="customer_links">
             <action method="addAccountLink" />
            </block>
        </reference>
    </default>

Now all we have to do is to tell Magento that we have a new module.
in app/etc/modules create a new file called Custom_Customer.xml (the name is not important) with this content:
<?xml version="1.0"?>
<config>
    <modules>
        <Custom_Customer>
            <active>true</active>
            <codePool>local</codePool>
            <depends><Mage_Customer /></depends>
        </Custom_Customer>
    </modules>
</config>

Clear the contents of 'var/cache' and enjoy.

Tested on Magento CE 1.5.1.0

Tuesday, May 31, 2011

Disabling customer logging

All the tables that start with 'log_' become pretty big after some uptime.
If you don't need these here is a solution to disable them.
[UPDATE]
It seams that the product compare feature is based on this logging. If you disable all the logging you won't be able to compare products. This is a big no-no Magento Team. (see the logging methods marked in the xml below)
[/UPDATE] Create your own Magento extension. Let's call it 'Custom_Log'.
For this you need to create in app/code/local the folder 'Custom' and inside it the folder 'Log'.
Each module needs a config file.
Create inside the 'Log' folder a folder named 'etc' and inside it a file called config.xml with this content:
<?xml version="1.0"?>
<config>
    <modules>
         <Custom_Log>
            <version>0.0.1</version>
        </Custom_Log>
    </modules>
    <frontend>
 <!-- [+] Disable logging -->
   <events>
            <controller_action_predispatch><!--disabling this will 'kill' the product compare-->
                <observers>
                    <log>
                        <type>disabled</type>
                    </log>
                </observers>
            </controller_action_predispatch>
            <controller_action_postdispatch><!--disabling this will 'kill' the product compare-->
                <observers>
                    <log>
                        <type>disabled</type>
                    </log>
                </observers>
            </controller_action_postdispatch>
            <customer_login>
                <observers>
                    <log>
                        <type>disabled</type>
                    </log>
                </observers>
            </customer_login>
            <customer_logout>
                <observers>
                    <log>
                        <type>disabled</type>
                    </log>
                </observers>
            </customer_logout>
            <sales_quote_save_after>
                <observers>
                    <log>
                        <type>disabled</type>
                    </log>
                </observers>
            </sales_quote_save_after>
            <checkout_quote_destroy>
                <observers>
                    <log>
                        <type>disabled</type>
                    </log>
                </observers>
            </checkout_quote_destroy>
        </events>
   <!-- [-] Disable logging -->
    </frontend>
</config>

now you need to tell Magento to use your module.
In app/etc/modules create the file 'Custom_Log.xml' with this content:
<?xml version="1.0"?>
<config>
    <modules>
        <Custom_Log>
            <active>true</active>
            <codePool>local</codePool>
        </Custom_Log>
    </modules>
</config>

now just clear the cache (contents of folder var/cache) and you are done.
The downside of doing this is that you won't get any details of the customers visits. But you can live with that. There's Google Analytics for this.

New design

Based on the visitor suggestions (if they were needed) I decided to change the design of this 'so called blog' to a 'less ugly one'.
I hope this is more readable.

Magento extensions you would like to see or to improuve

Hello everyone.
I decided to make a list and a poll (I hope it's still active when you read this) of extensions that people would like to see or to have perfected.

Here is the the short list I came up with.
Save a product as pdf
Tree like sitemap
Live chat
Yahoo weather widget
Multilanguage FAQ (with categories)
Product accessories
Price based on dimensions (WxHxD)
Multi-language e-mail templates

If you have any other ideas please put them here and maybe you will get that extension.

Please do not suggest online payment extensions.

Marius.

Tuesday, April 12, 2011

Adding 'on the fly' form validation

Here is how you can add 'on the fly' validation for forms in Magento. I mean to validate the forms not only on submit but after editing a field.
Put the following line in a js file included in all the pages or in the <head> tag
Validation.defaultOptions.immediate = true; 

If you also want the classes of the validation to be added not only for the input but fur it's parent also add the following line in the same place as the one above.
Validation.defaultOptions.addClassNameToContainer = true;

Hope it helps

Wednesday, November 24, 2010

How to add tier prices in the product list

Inside the app/design/frontend/{interface}/{theme}/template/catalog/product/list.phtml add this inside the foreach loops for grid and/or list
<?php $this->setProduct(Mage::getModel('catalog/product')->setStoreId(Mage::app()->getStore()->getId())->load($_product->getId()))?>
<?php echo $this->getTierPriceHtml() ?> 

It does not look nice for grid but it can be fixed by css.

Tuesday, August 3, 2010

How to delete orders from Magento

This is a response for http://www.magentocommerce.com/boards/viewthread/197549/
Problem: How to delete (test) orders from Magento.
Possible solution:

Here is a free but 'quick and dirty' way to do it.
Create a file on the same level as index.php. Let's call it orders.php
<?php
$mageFilename = 'app/Mage.php';
require_once $mageFilename;
Varien_Profiler::enable();
Mage::setIsDeveloperMode(true);
ini_set('display_errors', 1);
umask(0);
Mage::app('default');
Mage::register('isSecureArea', 1);
//until here you gained access to the Magento models. The rest is custom code

$orderId = 156;//put here the id of the order you want to delete. THE ONE FROM THE DATABASE NOT THE INCREMENT_ID

$order = Mage::getModel('sales/order')->load($orderId);
$invoices = $order->getInvoiceCollection();
foreach ($invoices as $invoice){
$invoice->delete();
}
$creditnotes = $order->getCreditmemosCollection();
foreach ($creditnotes as $creditnote){
$creditnote->delete();
}
$shipments = $order->getShipmentsCollection();
foreach ($shipments as $shipment){
$shipment->delete();
}
$order->delete();
?>
Save and call it in your browser (http://my-magento.root/orders.php)
This will delete an order with the id you specify.
If you want to delete more of them just create a for (foreach) loop that will execute this code for each order you want to delete.

For example, if all your test orders are consecutive up to a number you can do this:
//let's say that the orders with ids less than 200 are test orders
$collection = Mage::getModel('sales/order')->getCollection()->addAttributeToFilter(array(array('attribute'=>'entity_id', 'lt'=>200)));
foreach ($collection as $o){
$orderId = $o->getId();
//here goes the code above starting below $orderId = 156.
}

I've used it in several occasions and it worked, but please back-up before using it. I will not be responsible if something goes wrong :)

Wednesday, June 9, 2010

Adding related products, up-sells and cross-sells programmaticly

Problem:
Adding related products, up-sells and cross-sells programmaticly.
http://www.magentocommerce.com/boards/viewthread/195440/

Possible solution:

In order to set related, up-sells and crosssells you need to do the following
Let's assume that the current product is $_product (that you got by doing Mage::getModel('catalog/product')->load(SOME ID))
//for related
$_product->setRelatedLinkData($param);
//for up-sells
$_product->setUpSellLinkData($param);
//for crosssells
$_product->setCrossSellLinkData($param);
$param is an array with the following structure
$param = array(
$associatedProductId=>array(
'position'=>$associatedProductPosition
)
)

Here is an example. Let's say you want to add products with ids 101 and 102 as related products to $_product on positions 3 and 5.
You should do something like this:

$param = array(
101=>array(
'position'=>3
),
102=>array(
'position'=>5
)
);
$_product->setRelatedLinkData($param);
//here ... some other product operations and in the end
$_product->save();

It works the same for up-sells and crosssels.

Thursday, May 20, 2010

how to find methods in Magento

Problem: http://www.magentocommerce.com/boards/viewthread/193422/
Here is how I've learned.
Let's say you have in a phtml file this line of code.
$object->method();
($object can be anything including $this).
And you don't know what type is $object.
put this line above the method call.
echo get_class($object);
Clear the cache (contents of var/cache) and reload the page. You should see the name of the class. For example Mage_Catalog_Model_Category. now all you have to do is to find the class.
Because Magento is based on Zend Framework it uses the the same convention for class naming.
So class Abc_Def_Ghi will be in the file Abc/Def/Ghi.php (for the example above the file is Mage/Catalog/Model/Category.php)
All the classes are placed in app/code/core or app/code/local/ or app/code/community or lib/ and after that follow the path like explained above.

If you don't find a method in that specific class look in one of the parents. Check the class that the current class extends.

You will not find all the methods in Magento. For example some of the methods that start with get, set, has, uns is possible that the methods are missing.
For this take a look in Varien_Object class (that is the base class for most of the objects) lib/Varien/Object.php file (remember the convention above?) and look in the 'magic' method __call().