Magento link in backend redirect to dashboard

You are working on Magento backoffice and make a link to a new page but when you click on your anchor, you are redirected to the dashboard ?

Here how to make a proper link :

   echo "<a href='".Mage::helper('adminhtml')->getUrl('*/*/displaydetail', array('id' => $cour['id']))."' >".$cour['name']."</a>";

Something like

 Mage::getUrl('*/*/displaydetail/id/'.$cour['id'])

doesn’t work, even if I had the FormKey. But you can use it for ajax request

 jQuery.ajax({
        url: "<?php echo Mage::getUrl('*/*/classroomfromplaceAjax') ?>",
        type: "POST",
        dataType: 'json',
        data: 'place_id=' + place_id + '&index=' + index + '&form_key=' + window.FORM_KEY,
        success: function (data) {
            jQuery('#classroom_' + index).html(data.html);
        },
    });

Magento – add a new action in grid

Here, how to add new action in grid like ‘Edit’ link at admin grid.
On this example, we will add a “schedule” action in product admin grid.

We will overrite this class /app/code/core/Mage/Adminhtml/Block/Catalog/Product/Grid.php.

Declare the rewrite class on the /app/code/local/Adin/Catalog/etc/config.xml
and add

<global>
      <blocks>
            <adminhtml>
                <rewrite>
                    <catalog_product_grid>Adin_Catalog_Block_Adminhtml_Catalog_Product_Grid</catalog_product_grid>
                </rewrite>
            </adminhtml>
        </blocks>
</global>

Then create your rewritted class /app/code/local/Adin/Catalog/Block/Adminhtml/Catalog/Product/Grid.php.

<?php
class Adin_Catalog_Block_Adminhtml_Catalog_Product_Grid extends Mage_Adminhtml_Block_Catalog_Product_Grid {
}
?>

Now, rewrite the _prepareColumns() function, find the ‘action’ column an add an entry in the actions array

  $this->addColumn('action',
            array(
                'header'    => Mage::helper('catalog')->__('Action'),
                'width'     => '50px',
                'type'      => 'action',
                'getter'     => 'getId',
                'actions'   => array(
                    array(
                        'caption' => Mage::helper('catalog')->__('Edit'),
                        'url'     => array(
                            'base'=>'*/*/edit',
                            'params'=>array('store'=>$this->getRequest()->getParam('store'))
                        ),
                        'field'   => 'id'
                    ),
                    array(
                        'caption' => Mage::helper('catalog')->__('Schedule'),
                        'url'     => array(
                            'base'=>'*/*/schedule',
                            'params'=>array('store'=>$this->getRequest()->getParam('store'))
                        ),
                        'field'   => 'id'
                    ),
                ),
                'filter'    => false,
                'sortable'  => false,
                'index'     => 'stores',
            ));

In our example, we just add this part

array(
                        'caption' => Mage::helper('catalog')->__('Schedule'),
                        'url'     => array(
                            'base'=>'*/*/schedule',
                            'params'=>array('store'=>$this->getRequest()->getParam('store'))
                        ),
                        'field'   => 'id'
                    ),

One last thing, at the end of the _prepareColumns function, change

return parent::_prepareColumns();

by

return Mage_Adminhtml_Block_Widget_Grid::_prepareColumns();

Magento custom sort on grid – sort increment_id by numeric not alpha

You can easily filter column in a magento grid (see my previous post) but customize a sort is a little bit more hand made.

In this example in the order grid, I want to sort by increment_id, but this is a text fields and I want to sort it by numeric.

default sort : 1, 10, 100, 2, 3 …
numeric sort : 1, 2, 3, 10, 100 …

If you look the SQL request, you got this

SELECT `main_table`.* FROM `sales_flat_order_grid` AS `main_table` ORDER BY increment_id DESC LIMIT 20

To tell MySQL to sort this text column by numeric, you can add “+ 0″ to the ORDER BY clause, this will transform the text field into numeric field

SELECT `main_table`.* FROM `sales_flat_order_grid` AS `main_table` ORDER BY increment_id + 0 DESC LIMIT 20

Now, how to tell Magento to add “+ 0″ to this sort ?

Override your grid class and modify the “_setCollectionOrder($column)” function.

class Adin_Sales_Block_Adminhtml_Sales_Order_Grid extends Mage_Adminhtml_Block_Sales_Order_Grid {
    protected function _setCollectionOrder($column)
    {
        $collection = $this->getCollection();
        if ($collection) {
            $columnIndex = $column->getFilterIndex() ? $column->getFilterIndex() : $column->getIndex();
            if($columnIndex == 'increment_id')
            {
                $columnIndex = 'increment_id + 0';
            }
            $collection->setOrder($columnIndex, strtoupper($column->getDir()));
        }
        return $this;
    }
}

Magento custom filter on grid

Sometimes, you need a special column on your grid from another table or with some calculation.
It works well, column is displayed but filter doesn’t work.
Here a small example how to customize your filter :

On your grid class (Adin_Sponsorship_Block_Adminhtml_Sponsorship_Grid.class.php), override your _prepareColumns() function

protected function _prepareColumns()
{
        $this->addColumn('sponsor_email', array(
                'header'    => Mage::helper('evian_customer')->__('Sponsor Email'),
                'index'     => 'sponsor_email',
                'align'     => 'center',
                'filter_condition_callback' => array($this, '_filterSponsortEmail'),
            )
        );
}

The ‘filter_condition_callback’ option indicates to use as filter a specific method, on the current class ($this) the method _filterSponsortEmail().

So next step, create this method.

    protected function _filterSponsortEmail($collection, $column)
    {
        if (!$value = trim($column->getFilter()->getValue())) {
            return;
        }
        $this->getCollection()->addFieldToFilter('customer.email', array('like' => '%'.$value.'%'));
    }

Yes, this is this simple.

If you use a datetime column, it’s just a bit more complicated, see below

        $this->addColumn('created_at', array(
            'header'    => Mage::helper('evian_customer')->__('Date of sponsorship'),
            'index'     => 'created_at',
            'align'     => 'center',
            'type' => 'datetime',
            'filter_condition_callback' => array($this, '_filterDate'),
            )
        );

and the filter method

    protected function _filterDate($collection, $column)
    {
        $filters = $column->getFilter()->getValue();

            $from = $filters['from'];
            $to = $filters['to'];


       $this->getCollection()->addFieldToFilter('main_table.created_at', array('gteq' => $from->toString('yyyy-MM-dd')));
        $this->getCollection()->addFieldToFilter('main_table.created_at', array('lteq' => $to->toString('yyyy-MM-dd')));
    }

Magento filter products collection get only visible

You want to retrieve all your products but only the one visible in catalog or filter ?

You may use this

 $collection = Mage::getModel('catalog/product')->getCollection()->addAttributeToSelect('*');
 Mage::getSingleton('catalog/product_status')->addVisibleFilterToCollection($collection);
 Mage::getSingleton('catalog/product_visibility')->addVisibleInCatalogFilterToCollection($collection);

But it’s depreacated and doesn’t work.
You may instead use this :

 $collection = Mage::getModel('catalog/product')->getCollection()->addAttributeToSelect('*');
 $collection->addFieldToFilter('visibility', Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH);

Magento multi fields validator for RIB

Magento come with a great form validator : VarienForm. These is a lot of existing validator, for every usage and you can easyly add some. This is how you can do it with a commun example, how to check RIB bank account.

First, our html code

<ul class="inlineblockli">
	<li>
		<label for="code_bank_pb"><?php echo $this->__('bank code') ?></label>
                <input type="text" class="inputText inputTextB validate-digits required-entry validate-length minimum-length-5 maximum-length-5" id="code_bank_pb" maxlength="5" name="prelevement[code_bank_pb]">
	</li>
	<li>
		<label for="code_guichet_pb"><?php echo $this->__('branch code') ?></label>
                <input type="text" class="inputText inputTextB validate-digits required-entry validate-length minimum-length-5 maximum-length-5" id="code_guichet_pb" maxlength="5" name="prelevement[code_guichet_pb]">
	</li>
	<li>
		<label for="num_compte"><?php echo $this->__('Account number to be debited') ?></label>
                <input type="text" class="inputText inputTextBig3 validate-digits required-entry validate-length minimum-length-11 maximum-length-11" id="num_compte" maxlength="11" name="prelevement[num_compte]">
	</li>
	<li>
		<label for="key_rib"><?php echo $this->__('RIB key') ?></label>
                <input type="text" class="inputText inputTextSm3 validate-digits required-entry validate-compte validate-length minimum-length-2 maximum-length-2" id="key_rib" maxlength="2" name="prelevement[key_rib]">
	</li>
</ul>

We first do a lenght validation with these 3 class : validate-length minimum-length-11 maximum-length-11

Then we validate the rib with this class : validate-compte
You will tell me this validator doesn’t exeist. That’s right, let’s create it.

<script type="text/javascript">
    //<![CDATA[
    Validation.addAllThese(
        [
            ['validate-compte', '<?php echo Mage::helper('rating')->__('Please check your RIB account') ?>', function(v) {
                var code_banque = jQuery('#code_bank_pb').val();
                var code_guichet = jQuery('#code_guichet_pb').val();
                var numero_compte = jQuery('#num_compte').val();
                var cle           = jQuery('#key_rib').val();

                var CompteTmp = code_banque + code_guichet + numero_compte + cle;

                while(CompteTmp.length > 9)
                {
                    var CompteTmp2 = CompteTmp.substr(0,9) % 97;
                    CompteTmp = CompteTmp2 + CompteTmp.substr(9,CompteTmp.length);
                }
                var CompteTmp2 = CompteTmp.substr(0,9) % 97;

                if(CompteTmp2 % 97 == 0)
                {
                    return true;
                }
                return false;
            }]
        ]
    );
    //]]>
</script>

Some explainations :

jQuery('#code_bank_pb').val();

Magento use prototype, tu use jQuery, use jQuery instead of $

For the multi field validation, I grab the different fields from this

var code_banque   = jQuery('#code_bank_pb').val();
var code_guichet  = jQuery('#code_guichet_pb').val();
var numero_compte = jQuery('#num_compte').val();
var cle           = jQuery('#key_rib').val();

I don’t know if this is the cleaner way to do (not really usable for another code) but it works.
If you always use the same input id, you can reuse this code on another site.

Magento import product image

How to import product image with the magento import tools ?
It’s quite easy, when you know how to fill your import file and put your file in the right directory.

The directory : create if needed a /media/import/ direcory in your magento root file, in my case it’s /home/www/eshop/media/import/
Paths in the import tool are always relative to you media/import directory.

The imported file : on you image or small_image columns, you need to put your file name prefixed by a “/”.

Some examples:
picture file ==> string in the import file
/home/www/eshop/media/import/product1.jpg ==> /product1.jpg
/home/www/eshop/media/import/ProductPage/product1.jpg ==> /ProductPage/product1.jpg

Hope this will help you.

Développement d’un module magento avec Git et Modman

Ca fait donc un moment que j’utilise Git dans mes développements quotidiens et jusqu’à présent j’utilisais le fichier .gitignore pour sortir l’ensemble des fichiers de magento de mon repo.

Ensuite il me suffisait d’ajouter les fichiers de mon modules en utilisant le paramètre de forçage ce qui me donnait des trucs du style :

git add -f app/code/community/MonNamespace/MonModule/

Ca fonctionne .. c’est pas optimal et il faut pas oublier d’inclure à la main l’ensemble des fichiers…
Aujourd’hui j’ai décidé d’essayer un outil qui à priori est fait pour faire ce type de développement j’ai nommé modman

En résumé c’est un gros bash qui va s’occuper pour nous :

  • de gérer les interactions avec votre repository git en le clonant dans son répertoire .modman
  • de faire les liens symboliques du repository placé dans .modman et notre instance de Magento

Etape 1 – Création d’un repository git qui va contenir le code de notre module

Donc la première chose à faire est de créer votre nouveau bare repository git avec par exemple le fichier de configuration modman à l’intérieur.

Sur le serveur contenant git

mkdir <monrepot>.git
cd !$
git --bare init

Puis en local chez vous vous préparer à faire votre premier commit

cd /tmp
mkdir temporaire
cd temporaire
git init
git remote add origin <monserveur>/<monrepot>.git
touch modman
git add modman
git commit -f "Initial commit"
git push origin master

et voilà .. fin de la première étape .. votre repo git qui va contenir le module est prêt

Etape 2 – Initialisation de modman et clone

Bon maintenant il vous faut une version toute fraichement installé de magento pour commencer .. je vais pas vous expliquer comment faire .. c’est assez bien décrit ici ou ici

Vous êtes donc désormais dans le DocumentRoot de votre magento et on va commencer par :

  • Initialiser modman
    modman init
  • Cloner notre dépôt git
    modman clone '<monserveur>/<monrepot>.git'

Arrivé ici vous devriez avoir votre repo cloné dans .modman/

Etape 3 – Le fichier de configuration de modman

Le fichier de configuration de modman est relativement simple en gros on a par ligne

 <cible> <source>

Du coup on va commencer avec une configuration basique pour un module à savoir

app/etc/modules/Namespace_Module.xml       app/etc/modules/Namespace_Module.xml
app/code/community/Namespace/Module/       app/code/community/Namespace/Module/

On peut lancer ensuite la commande modman, à la racine de votre documentroot, qui va créer les liens symboliques

modman update <monrepot>

Vous devriez voir apparaître dans les répertoires concernés les liens symboliques mappés sur le repot (dans .modman/xxxx)

Voilà .. pour finir il ne faut pas oublier d’activer la gestion de la prise en compte des liens symboliques dans magento. Ca se passe dans le backend et plus particulièrement dans le menu Système>Configuration>Développeur>Paramètres de gabarit

Magento using core_config_data table

Core_config_data is a magento table used to save configuration and setting. It’s really helpfull and easy to use :

save or update a new entry :

$data = new Mage_Core_Model_Config();
$data->saveConfig('adin/ssid', 'value', 'default', 0);

and retrieve saved value :

$value = Mage::getConfig()->getNode('default/adin/ssid');

You may need to specify scope and scope code to retrieve the value

$value = Mage::getConfig()->getNode('default/sogen/file_number', 'default', 0 );

Update or create a value inside the installer (data, no sql)

  $installer->setConfigData('customer/address/prefix_show', 0);

In a setup file

 $installer->setConfigData('your/path', 'value', 'stores', 1);
 $installer->deleteConfigData('your/path', 'stores');