Tag Archives: Magento

Magento and .git directory hiding

If you’re deploying a Magento website using git you surely do not want the .git directory to be visible from the browser, so just put this line in your .htaccess:

RewriteRule .*\.git/.* - [F]

right after:

RewriteEngine on

let’s have a nice day now :)

Magento reindexer issue and very bad fix

On a big website, while Magento (this was a Professional 1.10.something) is reindexing (work done by a cron job) every page (viewed from the browser) seems to try to reindex the products it shows, that ends in a duplicate key error on an index temporary table (catalog_product_index_price_tmp), I needed a rough and quickfix I openedĀ app\code\core\Mage\Index\Model\Resource\Helper\Abstract.php and added a try/catch to theĀ insertFromSelect method, making it become:

public function insertFromSelect($select, $destTable, array $columns, $readToIndex = true)
    {
		try {
        if ($readToIndex) {
            $from   = $this->_getWriteAdapter();
            $to     = $this->_getIndexAdapter();
        } else {
            $from   = $this->_getIndexAdapter();
            $to     = $this->_getWriteAdapter();
        }

        if ($this->useDisableKeys()) {
            $to->disableTableKeys($destTable);
        }
        if ($from === $to) {
            $query = $select->insertFromSelect($destTable, $columns);
            $to->query($query);
        } else {
            $stmt = $from->query($select);
            $data = array();
            $counter = 0;
            while ($row = $stmt->fetch(PDO::FETCH_NUM)) {
                $data[] = $row;
                $counter++;
                if ($counter>2000) {
                    $to->insertArray($destTable, $columns, $data);
                    $data = array();
                    $counter = 0;
                }
            }
            if (!empty($data)) {
                $to->insertArray($destTable, $columns, $data);
            }
        }
        if ($this->useDisableKeys()) {
            $to->enableTableKeys($destTable);
        }
		} catch (Exception $e) {}
        return $this;
    }

It is bad but now it’s working, oh god.

Programmatically delete all Magento attribute sets

You’re developing a Magento importer and you want to clean your DB after some tests? Here you have:

require_once dirname(__FILE__) . '/app/Mage.php';
Mage::app()->setCurrentStore(Mage::getModel('core/store')->load(Mage_Core_Model_App::ADMIN_STORE_ID));

$resource = Mage::getSingleton('core/resource');
$db_read = $resource->getConnection('core_read');

$attribute_sets = $db_read->fetchCol("SELECT attribute_set_id FROM " . $resource->getTableName("eav_attribute_set") . " WHERE attribute_set_id<> 4 AND entity_type_id=4");
foreach ($attribute_sets as $attribute_set_id) {
	try {
		Mage::getModel("eav/entity_attribute_set")->load($attribute_set_id)->delete();
	} catch (Exception $e) {
		echo $e->getMessage() . "\n";
	}
}

Note that only products’ attribute sets are deleted, those are often generated automatically during imports.

Programmatically delete all Magento categories

You’re developing a Magento importer and you want to clean your DB after some tests? Here you have:

require_once dirname(__FILE__) . '/app/Mage.php';
Mage::app()->setCurrentStore(Mage::getModel('core/store')->load(Mage_Core_Model_App::ADMIN_STORE_ID));

$resource = Mage::getSingleton('core/resource');
$db_read = $resource->getConnection('core_read');

$categories = $db_read->fetchCol("SELECT entity_id FROM " . $resource->getTableName("catalog_category_entity") . " WHERE entity_id>1 ORDER BY entity_id DESC");
foreach ($categories as $category_id) {
	try {
		Mage::getModel("catalog/category")->load($category_id)->delete();
	} catch (Exception $e) {
		echo $e->getMessage() . "\n";
	}
}

Create a custom category attribute in Magento

I’ve run into a few posts about this thing but none of them was working out of the box so I took all the info and glued them together so…

if you’ve to create a custom attribute for a Magento category but you don’t have a module (and its installer script) simply create a php file in the project’s root with this code:

require_once('app/Mage.php');
Mage::app()->setCurrentStore(Mage::getModel('core/store')->load(Mage_Core_Model_App::ADMIN_STORE_ID));
$installer = new Mage_Sales_Model_Mysql4_Setup;
$attribute  = array(
	'type' => 'int',
	'label'=> 'Your attribute label',
	'input' => 'text',
	'global' => Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_GLOBAL,
	'visible' => true,
	'required' => false,
	'user_defined' => true,
	'default' => "",
	'group' => "General Information"
);
$installer->addAttribute('catalog_category', 'your_attribute_code', $attribute);
$installer->endSetup();

This attribute is a “text”, more info may come in comments if you need.

Magento Professional customer’s password hashing

So you want to import customer accounts but you’ve to generate the password hash? here you’ve the algorithm used by Magento Professional (which is different from Magento Community, but you can easily find that one in the net):

$passhash = hash("sha256", $salt . $password) . ":$salt";

By the way, for the community it’s

$passhash = md5($salt . $password) . ":$salt";

Create a custom order attribute in Magento

I’ve run into a few posts about this thing but none of them was working out of the box so I took all the info and glued them together so…

if you’ve to create a custom attribute for a Magento order but you don’t have a module (and its installer script) simply create a php file in the project’s root with this code:

require_once('app/Mage.php');
Mage::app()->setCurrentStore(Mage::getModel('core/store')->load(Mage_Core_Model_App::ADMIN_STORE_ID));
$installer = new Mage_Sales_Model_Mysql4_Setup;
$attribute  = array(
        'type'          => 'text',
        'backend_type'  => 'text',
        'frontend_input' => 'text',
        'is_user_defined' => true,
        'label'         => 'Your attribute label',
        'visible'       => true,
        'required'      => false,
        'user_defined'  => false,   
        'searchable'    => false,
        'filterable'    => false,
        'comparable'    => false,
        'default'       => ''
);
$installer->addAttribute('order', 'your_attribute_code', $attribute);
$installer->endSetup();

This attribute is a “text” and it’s made not to be visible but just to use it as a container for some data you may need in your custom development, more info may come in comments if you need.

“Magento 1.4 Themes Design Cookbook” review

As I wrote a few days ago, I was asked to review the Magento 1.4 Development Cookbook by Packt so I took the right time to read it deeply and with great attention to point out every pro and con of this mid-length book (249 pages).

First of all the book is available at a price of ~40 USD (~31 EUR) if you want the paper book, or ~32 USD (~25 EUR) for the digital copy (in PDF format), the price is right (maybe just a little high) for a highly technical book like this. You’ll also receive a comprehensive archive of all the code that’s used in the book, really useful for a quick cut&paste to try out things!

Now, I’ve to say that Magento 1.6 is near to be released and still we’ve no book about 1.5, and also if 1.4 documentation is still valid I think that it would be the time to update all the books on the new releases.

Chapter 1: I think it’s completely useless unless for the section about the differences between 1.3 and 1.4, in this moment every designer about to design and/or code a Magento themes already know what can be done and surely has seen enough themes in the wild so I think that we don’t need an introduction or a showcase.

Chapter 2: this is one of my preferred chapters, ok it’s not so difficult but it explains all the basic concept and it’s really needed for the first timers. I think this chapter should have been the first one but anyway it’s great.

Chapter 3: probably it could be merged with the 2nd ’cause it keeps talking about the basic things you need to know when you’re about to start working on a Magento themes, useful but anyway I think none needs a “where do I get inspiration for a favicon” section. The “display products on the homepage” section is instead really useful and raises the level of this chapter.

Chapter 4: first real steps into customizing a default Magento theme to fit your design, with some more basic hits (like enabling template path hints and block names hints) and some detailed info about CMS pages (which actually area managed pretty bad in Magento).

Chapter 5: creating a theme from scratch, pretty advanced things are going on here :) and that’s the kind of things I like the most.

Chapter 6: starts with a useless section about integrating font-face into a Magento theme, actually I don’t understand why this kind of info should be in a Magento book, it should have been in a HTML/CSS one… but finishes with some pretty handy documentation about “navigation” and the “product view” template.

Chapter 7: the part I liked the most about this chapter is about creating a custom block and using it in a layout xml file, other things (adding javascripts or stylesheets) are a little too basic at this point.

Chapter 8: talks about mail templates, pretty basic stuff in the beginning, getting interesting later with variables in emails and a good section about how to integrate external newsletter systems and another one on upgrade-proof email templates.

Chapter 9: integrating social stuff, absolutely basic notions about copying facebook’s html widgets and paste it in your templates…

Chapter 10: print styles, once again I think that this topic should be covered in a HTML/CSS guide.

Conclusions: if you never wrote a Magento theme buy this book, it will help you in a lot of ways. The second time you’ll have to do the same work again… you won’t need it.

Magmi, the best Magento importer

I found out Magmi while writing my Esprinet importer for Magento.

I think that using Magento API is the cleanest way to do every import operation but importing something like 70.000 products was absolutely TOO SLOW so I had to look for something else…

Magmi (which is released under the MIT license) does everything using SQL queries and it’s blazing fast! It also features a few really useful plugins, the one I like the most are:

  • Category importer: you can type category names in CSV instead of category ids, really nice. It also creates parent categories if you use the “parent/child” syntax.
  • Optimizer: runs some MySQL tables optimization before importing.
  • Magento reindexer: updates all (or just some) Magento indexes, couldn’t live without it!

What I didn’t like?

  • Using “/” for the category importer separator, I’ve a lot of categories with the “/” char in the name, so I hat to patch the plugin to use “->” instead of “/”. I think it could be better in any case but for the maximum flexibility it should be a part of the configuration options
  • I couldn’t find any documentation about the CLI usage
  • Using Magmi CLI it seems to me that the import progress file isn’t updated the right way

Anyway the Magmi team did a great job, hope it will continue to be maintained for future Magento releases.

Esprinet Importer for Magento

For everyone interested I just published my Esprinet importer for Magento.

It reads Esprinet’s dispoP.txt export file and convert it to CSV, passing it to a patched version of the great Magmi importer.

I also features a category choser/renamer/remapper to add some flexibility.