Magento Common problems and solutions for images disappear from website

April 11, 2010 · Leave a Comment
Filed under: Featured, Magento Cart, PHP, Shopping Carts 

If images disappear from the  Magento site check the below

logo_magento

  1. Cache refresh
  2. image path being CASE SENSITIVE
  3. incorrect image path in catalog_product_entity_media_gallery while porting
  4. Make sure you have GD installed fine on your server.,.. if not re-install it ..and also disable open_basedir function for this account.
  5. php_value memory_limit : supports only values in M and not in G you can’t give 1G instead give it as 1024M.



Hope this save lot of time for other Magento users.

Magento Customer Password is encrypted with the below code

April 4, 2010 · 3 Comments
Filed under: eCommerce, Featured, Magento Cart, Shopping Carts 

Magento Customer Password is encrypted with the below code

It does use Md5. Here is the code:

public function getHash($password, $salt=false)
{
if (is_integer($salt)) {
$salt = $this->getRandomString($salt);
}
return $salt===false ? md5($password) : md5($salt.$password).':'.$salt;
}

So, in the database it is stored as this: [md5]:[salt]

Magento Adding New Order RSS to Google Reader without Authentication

April 2, 2010 · Leave a Comment
Filed under: eCommerce, Featured, Magento Cart, Shopping Carts 

If you wish, Magento will automatically notify you via RSS Feed of the creation of all new Orders, whether created in front-end the or the admin. In order to use this RSS feed, navigate to Sales > Orders, and click the New Order RSS link at the top of the page. You will be prompted to enter your User Name and Password. These are the same that you use to access the Magento admin panel. You will be redirected to the RSS page, where you can select which reader you would like to use for receiving this feed.

logo_magento

Google does not support password protected feeds.  So we need to register our feed with
http://freemyfeed.com/ . This will convert RSS feed into a normal feed so that we can add this feed to Google reader.

freemyfeed_com

For SSL you have another link on the site where you can generate normal feed

Magento database script to delete all test data from database

April 1, 2010 · 1 Comment
Filed under: Featured, Magento Cart, MySql, Shopping Carts 

After you import the data.  execute the following queries to delete all the customers, orders, wishlist info, logs, reports, stored carts.

This script will start you over, remember to backup first!

SET FOREIGN_KEY_CHECKS=0;

TRUNCATE `sales_order`;
TRUNCATE `sales_order_datetime`;
TRUNCATE `sales_order_decimal`;
TRUNCATE `sales_order_entity`;
TRUNCATE `sales_order_entity_datetime`;
TRUNCATE `sales_order_entity_decimal`;
TRUNCATE `sales_order_entity_int`;
TRUNCATE `sales_order_entity_text`;
TRUNCATE `sales_order_entity_varchar`;
TRUNCATE `sales_order_int`;
TRUNCATE `sales_order_text`;
TRUNCATE `sales_order_varchar`;
TRUNCATE `sales_flat_quote`;
TRUNCATE `sales_flat_quote_address`;
TRUNCATE `sales_flat_quote_address_item`;
TRUNCATE `sales_flat_quote_item`;
TRUNCATE `sales_flat_quote_item_option`;
TRUNCATE `sales_flat_order_item`;
TRUNCATE `sendfriend_log`;
TRUNCATE `tag`;
TRUNCATE `tag_relation`;
TRUNCATE `tag_summary`;
TRUNCATE `wishlist`;
TRUNCATE `log_quote`;
TRUNCATE `report_event`;

ALTER TABLE `sales_order` AUTO_INCREMENT=1;
ALTER TABLE `sales_order_datetime` AUTO_INCREMENT=1;
ALTER TABLE `sales_order_decimal` AUTO_INCREMENT=1;
ALTER TABLE `sales_order_entity` AUTO_INCREMENT=1;
ALTER TABLE `sales_order_entity_datetime` AUTO_INCREMENT=1;
ALTER TABLE `sales_order_entity_decimal` AUTO_INCREMENT=1;
ALTER TABLE `sales_order_entity_int` AUTO_INCREMENT=1;
ALTER TABLE `sales_order_entity_text` AUTO_INCREMENT=1;
ALTER TABLE `sales_order_entity_varchar` AUTO_INCREMENT=1;
ALTER TABLE `sales_order_int` AUTO_INCREMENT=1;
ALTER TABLE `sales_order_text` AUTO_INCREMENT=1;
ALTER TABLE `sales_order_varchar` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_quote` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_quote_address` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_quote_address_item` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_quote_item` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_quote_item_option` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_order_item` AUTO_INCREMENT=1;
ALTER TABLE `sendfriend_log` AUTO_INCREMENT=1;
ALTER TABLE `tag` AUTO_INCREMENT=1;
ALTER TABLE `tag_relation` AUTO_INCREMENT=1;
ALTER TABLE `tag_summary` AUTO_INCREMENT=1;
ALTER TABLE `wishlist` AUTO_INCREMENT=1;
ALTER TABLE `log_quote` AUTO_INCREMENT=1;
ALTER TABLE `report_event` AUTO_INCREMENT=1;

--

reset customers
TRUNCATE `customer_address_entity`;
TRUNCATE `customer_address_entity_datetime`;
TRUNCATE `customer_address_entity_decimal`;
TRUNCATE `customer_address_entity_int`;
TRUNCATE `customer_address_entity_text`;
TRUNCATE `customer_address_entity_varchar`;
TRUNCATE `customer_entity`;
TRUNCATE `customer_entity_datetime`;
TRUNCATE `customer_entity_decimal`;
TRUNCATE `customer_entity_int`;
TRUNCATE `customer_entity_text`;
TRUNCATE `customer_entity_varchar`;
TRUNCATE `log_customer`;
TRUNCATE `log_visitor`;
TRUNCATE `log_visitor_info`;

ALTER TABLE `customer_address_entity` AUTO_INCREMENT=1;
ALTER TABLE `customer_address_entity_datetime` AUTO_INCREMENT=1;
ALTER TABLE `customer_address_entity_decimal` AUTO_INCREMENT=1;
ALTER TABLE `customer_address_entity_int` AUTO_INCREMENT=1;
ALTER TABLE `customer_address_entity_text` AUTO_INCREMENT=1;
ALTER TABLE `customer_address_entity_varchar` AUTO_INCREMENT=1;
ALTER TABLE `customer_entity` AUTO_INCREMENT=1;
ALTER TABLE `customer_entity_datetime` AUTO_INCREMENT=1;
ALTER TABLE `customer_entity_decimal` AUTO_INCREMENT=1;
ALTER TABLE `customer_entity_int` AUTO_INCREMENT=1;
ALTER TABLE `customer_entity_text` AUTO_INCREMENT=1;
ALTER TABLE `customer_entity_varchar` AUTO_INCREMENT=1;
ALTER TABLE `log_customer` AUTO_INCREMENT=1;
ALTER TABLE `log_visitor` AUTO_INCREMENT=1;
ALTER TABLE `log_visitor_info` AUTO_INCREMENT=1;

TRUNCATE `sales_payment_transaction`;
ALTER TABLE `sales_payment_transaction` AUTO_INCREMENT=1;

TRUNCATE sales_invoiced_aggregated;

TRUNCATE  sales_refunded_aggregated;

TRUNCATE  sales_shipping_aggregated;

--

Reset all ID counters
TRUNCATE `eav_entity_store`;
ALTER TABLE `eav_entity_store` AUTO_INCREMENT=1;

SET FOREIGN_KEY_CHECKS=1;

If I miss anything please point out.

This scripts works perfectly when I do test on magento

How to set different port no for MySql database in Magento

March 28, 2010 · 2 Comments
Filed under: Databases, eCommerce, Featured, Magento Cart, MySql, Shopping Carts 

How to set different port no for mysql database in Magento

Open the Configuration file where you setup database properties, i.e app/etc/local.xml

Just Replace the PORTNO in below xml with your port number.

<default_setup>

<connection>

<host><![CDATA[HOSTADDRESS]]></host>

<username><![CDATA[USERNAME]]></username>

<password><![CDATA[PASSWORD]]></password>

<dbname><![CDATA[DBNAME]]></dbname>

<port><![CDATA[PORTNO]]></port>

<active>1</active>

</connection>

</default_setup>

How to set E-Commerce Magento – Tier Pricing

February 1, 2010 · Leave a Comment
Filed under: Featured, Magento Cart 

Tier pricing is an essential part of in-depth pricing strategies in ecommerce, particularly for shops that sell high volumes of a particular product and would like to encourage customers to buy in bulk. The idea is that the product comes with an normal price, however as you start to add more of them to your basket, the price per item comes down.

The best thing about it is that it is extremely simple to integrate into a Magento store.

Tier Pricing

When creating a product, locate the ‘Prices’ tab on the left side of the screen. Click this and select ‘Add Tier’. Enter the qty (quantity) that you’d like to start the tier pricing at, then add the new price per item based on the number added to the basket. And that’s pretty much all there is to it! To add more tiers, just press the ‘Add Tier’ button again –  you can have as many as you like.  If you want to remove one of the tiers, press ‘Delete Tier’.

Here’s the official Magento video for a more detailed demonstration:

Increase Memory PHP, Magento, WordPress by just changing in .htaccess

If you are on a virtual hosting then its a big problem to increase server php memory usage. Then we can simply modify the .htaccess file in root directory and increase memory.

if .htaccess file is not there then create one and add below code.

Then  simply modify the variable “php_value memory_limit 120M”

by default we will have 32M allocated we can increase it according to our requirement.

We can do this in any php apache technology or in Zend, Prado, Symfony, Joomla, CakePHP, CodeIgniter etc.

<IfModule mod_php5.c>

############################################

## adjust memory limit

#    php_value memory_limit 64M

php_value memory_limit 120M

php_value max_execution_time 18000

############################################

## disable magic quotes for php request vars

php_flag magic_quotes_gpc off

############################################

## disable automatic session start

## before autoload was initialized

php_flag session.auto_start off

############################################

## enable resulting html compression

#php_flag zlib.output_compression on

###########################################

# disable user agent verification to not break multiple image upload

php_flag suhosin.session.cryptua off

###########################################

# turn off compatibility with PHP4 when dealing with objects

php_flag zend.ze1_compatibility_mode Off

</IfModule>

How to Add Magento JQuery/Ajax Add-To-Cart

December 26, 2009 · 18 Comments
Filed under: Featured, JavaScript, JQuery, Magento Cart 

So, Ajax being the thing and all, I was hunting for a way to add an item to the cart using an Ajax call in Magento.  Recently, I noticed there was a module that apparently does this, but either I hadn’t seen that or it didn’t exist yet when I wrote this, so I hacked my way through it.

PHP isn’t my primary language – I come from the ASP, ASP.Net, C# world, but Magento was compelling enough that I’ve taken the leap.  I’m sure there are lots of things I could be doing better/differently here so if you’ve got some suggestions, I’m all ears!

Add to Cart Page

So first I needed an “Add to Cart” page (called – addToCart.php) that could be called from the client.  This page returns a result in JSON format.  The actual page also returns related items so we can try to cross sell the user, but I’ve removed that in this sample to make it simpler.

<?php

include_once '../app/Mage.php';

Mage::app();

try{
// usage /scripts/addToCart.php?product_id=838&amp;amp;amp;amp;amp;amp;amp;amp;amp;qty=1
// product_id OR sku is required

// get query string
if (!isset($_GET['sku'])) { $sku = ''; } else { $sku = $_GET['sku']; }
if (!isset($_GET['product_id'])) { $product_id = ''; } else { $product_id = $_GET['product_id']; }
if (!isset($_GET['qty'])) { $qty = '1'; } else { $qty = $_GET['qty']; }

if ($sku != ""){
$product_id = Mage::getModel('catalog/product')->getIdBySku("$sku");
if ($product_id == '') {
$session->addError("Product Not Added
The SKU you entered ($sku) was not found.");
}
}

$request = Mage::app()->getRequest();

$product = Mage::getModel('catalog/product')->load($product_id);

$session = Mage::getSingleton('core/session', array('name'=>'frontend'));
$cart = Mage::helper('checkout/cart')->getCart();

$cart->addProduct($product, $qty);

$session->setLastAddedProductId($product->getId());
$session->setCartWasUpdated(true);

$cart->save();

$result = "{'result':'success'}";

echo $result;

} catch (Exception $e) {
$result = "{'result':'error'";
$result .= ", 'message': '".$e->getMessage()."'}";
echo $result;
}

Buy Now Button

Then I need a “Buy Now” button that doesn’t do a post to the server that I can attach my jQuery code to.  I’ve added the sku as an attribute to the anchor because I have this in a page that has more than one product on the page and I need to know which product has been selected.

<a href="#" sku="<?php echo $this->__($product->sku) ?>"><img src="/media/upload/image/product-details/buy-now.jpg" border=0 alt="<?php echo $this->__('Buy Now') ?>"></a>

Client Script

Finally, I need the client script that gets attached to the button and calls the server “addToCart.php” page.

/* Cart */
jQuery(document).ready(function($) {
$.ui.dialog.defaults.bgiframe = true;

$(".add-to-cart").click(function(e){
var buyNow = $(e.currentTarget);
var listingItem = $(buyNow).closest(".listing-item");
var colorSelector = $("#colorSelector", listingItem);
var product_id = colorSelector.val();

if (product_id == ""){
showDialog("Please select a color.", "Missing Information");
return false;
}

var stockStatus = $("option:selected", colorSelector).attr("stockstatus");
if (stockStatus == "out of stock"){
showDialog("Sorry, that colour is currently unavailable.", "Out of Stock")
return false;
}

var qty = $("#quantity", listingItem).val();

if (qty == ""){
qty = "1";
}

$(this).siblings(".ajax-loader").show();
var obj = this;

var params = "product_id=" + product_id + "&amp;amp;amp;amp;amp;qty=" + qty;

var result = $.getJSON("/scripts/addToCart.php", params, function(data, textStatus){
$(obj).siblings(".ajax-loader").hide();

if (textStatus == "error"){
showDialog("There was an error adding this item to your cart.  Please call customer service for assistance.", "Error");
return;
}

if (data.result == "error"){
showDialog("Sorry, an error occurred while adding the item to your cart.  The error was: '" + data.message + "'");
return;
}

// SHOW FEEDBACK, ERRORS AND RELATED ITEMS
} // end add to cart

function showDialog(msg, title){
$("#dialog").dialog( 'destroy' );
$("#dialog").html(msg);

$("#dialog").dialog({
buttons: {
"Ok": function() {
$(this).dialog("close");
}
}
// , closeOnEscape: true
// , show: 'slide'
});

$('#dialog').dialog('option', 'title', title);
$("#dialog").dialog('open');
}
});

Few things probably need some explanation:
1. I’ve attached the function to ALL add to cart buttons using the “add-to-cart” class.  (There are multiple products on the page.)
2. Each product has a color selector that has the product_id as the value in the drop down.  There’s also an additional attribute called “stockstatus” that will let me know if the color is out of stock.  My customer didn’t want to hide the out of stock colors, but I obviously can’t let anyone order them.
3. I put a little animated gif (the “ajax loader”) on the page and that gets displayed when the ajax call is being made.
4. If there is an error, I display it using the jQuery UI library and a little showdialog helper function.
5. There’s a feedback panel that shows related items, but I’ve removed that in this code just to make it easier to follow.
So there it is.  Hope this helps someone.  And if there are better ways to do this, I’d love to hear them!
[Update:  I removed the reference to common.php in the code above because it’s not needed.  It had some common user functions in it that aren’t necessary for this sample]

Magento how to create a Custom Plugin/ Module / example / tutorial Part II

December 25, 2009 · 7 Comments
Filed under: eCommerce, Featured, Magento Cart, PHP, Shopping Carts, Zend 

Controller

/app/code/local/<Namespace>/<Module>/controllers/Adminhtml/<Module>Controller.php

NOTE: you need to manually add line 16, which is currently missing in this file. As per suggestion from mkd at page http://www.magentocommerce.com/boards/viewthread/11228/

<?php
 class >Namespace<_<Module>_Adminhtml_<Module>Controller extends
        {
      protected function _initAction()

     {
        $this->loadLayout()
        ->_setActiveMenu('/items')
        ->_addBreadcrumb(Mage::helper('adminhtml')->__('Items Manager'), Mage::helper('adminhtml')->__('Item Manager'));
        return $this;
        }
        public function indexAction() {
        $this->_initAction();
        $this->_addContent($this->getLayout()->createBlock('/adminhtml_'));
        $this->renderLayout();
        }

      public function editAction()

     {
        $Id     = $this->getRequest()->getParam('id');
        $Model  =	Mage::getModel('/')->load($Id);
    if ($Model->getId() || $Id ==	0) {
  	  Mage::register('_data', $Model);
  	  $this->loadLayout();
          $this->_setActiveMenu('/items');

	  $this->_addBreadcrumb(Mage::helper('adminhtml')->__('Item	Manager'), Mage::helper('adminhtml')->__('Item Manager'));
 	  $this->_addBreadcrumb(Mage::helper('adminhtml')->__('Item News'), Mage::helper('adminhtml')->__('Item News'));

      $this->getLayout()->getBlock('head')->setCanLoadExtJs(true);

        $this->_addContent($this->getLayout()->createBlock('/adminhtml__edit'))
        ->_addLeft($this->getLayout()->createBlock('/adminhtml__edit_tabs'));

      $this->renderLayout();

      } else {

      Mage::getSingleton('adminhtml/session')->addError(Mage::helper('')->__('Item does not exist'));

      $this->_redirect('*/*/');

      }

      }

      public function newAction()
        {
        $this->_forward('edit');
        }

      public function saveAction()

      {

      if ( $this->getRequest()->getPost() ) {

      try {

      $postData = $this->getRequest()->getPost();

      $Model = Mage::getModel('/');

      $Model->setId($this->getRequest()->getParam('id'))

      ->setTitle($postData['title'])

      ->setContent($postData['content'])

      ->setStatus($postData['status'])

      ->save();

      Mage::getSingleton('adminhtml/session')->addSuccess(Mage::helper('adminhtml')->__('Item was successfully saved'));

      Mage::getSingleton('adminhtml/session')->setData(false);

      $this->_redirect('*/*/');

      return;

      } catch (Exception $e) {

      Mage::getSingleton('adminhtml/session')->addError($e->getMessage());

      Mage::getSingleton('adminhtml/session')->setData($this->getRequest()->getPost());

      $this->_redirect('*/*/edit', array('id' => $this->getRequest()->getParam('id')));

      return;

      }

      }

      $this->_redirect('*/*/');

      }

      public function deleteAction()

      {

      if( $this->getRequest()->getParam('id') > 0 ) {

      try {

      $Model = Mage::getModel('/');

      $Model->setId($this->getRequest()->getParam('id'))

      ->delete();

      Mage::getSingleton('adminhtml/session')->addSuccess(Mage::helper('adminhtml')->__('Item was successfully deleted'));

      $this->_redirect('*/*/');

      } catch (Exception $e) {

      Mage::getSingleton('adminhtml/session')->addError($e->getMessage());

      $this->_redirect('*/*/edit', array('id' => $this->getRequest()->getParam('id')));

      }

      }

      $this->_redirect('*/*/');

      }

      }

XML Configuration Changes

/app/code/local/<Namespace>/<Module>/etc/config.xml

<?xml version="1.0"?>

<config>

<modules>

<[Namespace]_[Module]>

<version>0.1.0</version>

</[Namespace]_[Module]>

</modules>

<frontend>

<routers>

<[module]>

<use>standard</use>

<args>

<module>[Namespace]_[Module]</module>

<frontName>[module]</frontName>

</args>

</[module]>
</routers>

<layout>

<updates>

<[module]>
<file>[module].xml</file>

</[module]>

</updates>

</layout>

</frontend>

<admin>

<routers>

<[module]>

<use>admin</use>

<args>

<module>[Namespace]_[Module]</module>

<frontName>[module]</frontName>

</args>

</[module]>

</routers>

</admin>

<adminhtml>

<menu>

<[module] module="[module]">

<title>[Module]</title>

<sort_order>71</sort_order>

<children>

<action>[module]/adminhtml_[module]</action>

</items>

</children>

</[module]>

</menu>

<acl>

<resources>

<all>

<title>Allow Everything</title>

</all>

<admin>

<children>
<[module]>
<title>[Module] Module</title>

<sort_order>200</sort_order>

</[module]>

</children>

</admin>

</resources>

</acl>

<layout>

<updates>

<[module]>

<file>[module].xml</file>

</[module]>

</updates>

</layout>

</adminhtml>

<global>

<models>

<[module]>

<class>[Namespace]_[Module]_Model</class>

<resourceModel>[module]_mysql4</resourceModel>

</[module]>

<[module]_mysql4>

<class>[Namespace]_[Module]_Model_Mysql4</class>

<entities>

<[module]>

<table>[module]</table>

</[module]>

</entities>

</[module]_mysql4>

</models>

<resources>

<[module]_setup>

<setup>

<module>[Namespace]_[Module]</module>

</setup>

<connection>

<use>core_setup</use>

</connection>

</[module]_setup>

<[module]_write>

<connection>

<use>core_write</use>

</connection>

</[module]_write>

<[module]_read>

<connection>

<use>core_read</use>

</connection>

</[module]_read>

</resources>

<blocks>

<[module]>

<class>[Namespace]_[Module]_Block</class>

</[module]>

</blocks>

<helpers>

<[module]>

<class>[Namespace]_[Module]_Helper</class>

</[module]>

</helpers>

</global>

</config>

XML Layout

/app/design/adminhtml/<interface>/<theme>/layout/<module>.xml

<?xml version="1.0"?>

<layout version="0.1.0">

<[module]_adminhtml_[module]_index>

<reference name="content">
Source : http://www.magentocommerce.com/wiki/custom_module_with_custom_database_table

Magento how to create a Custom Plugin/ Module / example / tutorial

December 25, 2009 · 12 Comments
Filed under: eCommerce, Featured, Magento Cart, PHP, Shopping Carts, Zend 

Module Creator

Thanks to member Danieln for creating this PHP script to automatically create a base module given a Namespace and Module.

Credits: Danieln (creator), Alistek (contributor), Damián Culotta (contributor), Somesid (contributor), Ahsan Shahzad (contributor)

Download Module Creator (v0.0.9.1) or Install it as an Extension (beta)

modcreator0.0.9.0_small.jpg

Updated: 25/08/2008 – 0.0.9.1 Release Notes

#NOTE: v0.0.9.1 holds a bug that do not allow to ACL to manage module’s user level access. I am currently working on it to fix.

#ADDED: The module is now created with an upload field for example.

#ADDED: Code in the frontend controller shows how to get an object by param and by custom query .

#FIXED: You can now use blocks to get data on the frontend (see http://www.magentocommerce.com/boards/viewreply/54110/ for more details) .

#NOTE: Wiki post has yet to be updated with new code and explanations.

Updated: 07/04/2008 – 04:00AM CST – 0.0.9.0 Release Notes

#NEW FEATURE: Now with module uninstaller and better look&feel.

#NEW FEATURE: Point to your Magento Install Directory to get you module copied to the right places right away.

#NOTE: Thanks to Barbanet the below problem should be alleviated with entering in your interface and theme at module creation time.

#NOTE: A common problem with the Module Creator has been the confusion over the use of ‘interface’ and ‘theme’.

The directories:

  1. /new/app/design/adminhtml/interface/theme/
  2. /new/app/design/frontend/interface/theme/

In a new Magento installation correspond to:

  1. /app/design/adminhtml/default/default/
  2. /app/design/frontend/default/default/

Please make sure to put your <module>.xml files in the correct ‘layout’ directories as these will determine whether your module is shown or not.

Installing the Module Creator

To install the Module Creator, you can use the Magento Connect Manager with the extension key, or install it manually as follows. Note that if you install via the Connect Manager the path it uses is /moduleCreator.

Copy the index.php file and the Blank folder to your webserver. You may want to put it in it’s own folder so that the index file does not conflict with other index files. Example: mysite.com/module_creator/

Go to the module creator index page in your web browser, and fill in the desired module information. If you enter your Magento directory, the module creator will attempt to install the module directly into Magento, though file permissions must be set correctly for this to happen. If your file permissions are incorrect, or you do not want the module installed right away, you can leave the Magento Directory blank, and the module creator will create the module in a folder called [i]new[/i], and place it in the module creator’s folder.

Please note that if you enter in your magento directory to install to you must have the correct path. Let’s say that you have Magento installed here:

  1. http://www.my_site.com/magento/

And you have the Module Creator installed here:

  1. http://www.my_site.com/module_creator/

This means that the path that you would need to enter in the Module Creator is this:

  1. ../magento

The ‘..’ signifies one directory up.

Document Conventions

I am going to use a few common conventions here that should make it easier to figure out what you need to replace as I am making this as generic as possible.

Anything in angled brackets (including the angled brackets): < >, needs to replaced with the appropriate text.

Anything in square brackets (including the square brackets): [ ], needs to replaced with the appropriate text.

The reason I am using two different conventions here are that XML files already use angled brackets so you will only see the square brackets in use in XML files.

NOTE: All directory, file, class names are Case Sensitive unless otherwise noted.

Create Directories

Magento Modules follow a common naming scheme, Namespace_Module. This is very important to remember as you need to be careful about how you name your classes. Every custom module will be created in the directory:

/app/code/local

The first step in creating your custom module is determining the namespace and module name. The namespace is simply an extra division that you can create you module in. This means that you can have two modules named the same thing if they are in two different namespaces. One way to use namespaces is to use your company name or initials for all of your modules. If my company name is Acme and I am creating a module called News the full module name would be Acme_News. Magento uses the namespace Mage. There is nothing stopping you from using that namespace under local, i.e. you could create Mage_News and that would work just fine.

Note : You can not use underscore within your module name

Note2: It seems that currently, if you use upper case characters in module names (expecting to show word starts since neither – nor _ is allowed)… the install will fail or rather the module will not work. Suggestion: use a single upper case character, at the beginning of the name.

Let’s setup our directory structure:

/app/code/local/<Namespace>/<Module>/

  1. Block/
  2. controllers/
  3. etc/
  4. Model/
  5. Mysql4/
  6. <Module>/
  7. sql/
  8. <module>_setup/

/app/design/frontend/<interface>/<theme>/

  1. template/
  2. <module>/

Activate Module

Magento requires there to be an XML file that tells Magento to look for and use your custom module.

/app/etc/modules/<Namespace>_<Module>.xml

<?xml version="1.0"?>

<config>

<modules>

<[Namespace]_[Module]>

<active>true</active>

<codePool>local</codePool>

</[Namespace]_[Module]>

</modules>

</config>

Also you can disable your module in the Configuration menu on the backend via the Advanced tab.

NOTE: Due to a bug in Magento, whitespace is not treated correctly. This means that if you leave space in the values between node names (anything in angled brackets <> is a node), Magento will break.

As an explanation of the above code you will see that all you are changing is the [Namespace]_[Module] text and leaving everything else the same. Please note the capital P in codePool. If this is lowercase this module will not be active.

Create Controller

/app/code/local/<Namespace>/<Module>/controllers/IndexController.php

<?php

class <Namespace>_<Module>_IndexController extends Mage_Core_Controller_Front_Action

{

public function indexAction()

{

$this->loadLayout();

$this->renderLayout();

}

}

NOTE: You may notice that there is no closing, ?>, PHP tag in the code. This is a common coding style that Magento core classes use. Magento Coding Standard is similar (with some exceptions) to Zend Framework PHP Coding Standard and you can find the detailed explanations of this rule in Zend Framework Documentation

Create Configuration XML

/app/code/local/<Namespace>/<Module>/etc/config.xml

    <?xml version="1.0"?>		

      <config>		

      <modules>		

      <[Namespace]_[Module]>		

      <version>0.1.0</version>		

      </[Namespace]_[Module]>		

      </modules>		

      <frontend>		

      <routers>		

      <[module]>		

      <use>standard</use>		

      <args>		

      <module>[Namespace]_[Module]</module>		

      <frontName>[module]</frontName>		

      </args>		

      </[module]>		

      </routers>		

      <layout>		

      <updates>		

      <[module]>		

      <file>[module].xml</file>		

      </[module]>		

      </updates>		

      </layout>		

      </frontend>		

      <global>		

      <models>		

      <[module]>		

      <class>[Namespace]_[Module]_Model</class>		

      <resourceModel>[module]_mysql4</resourceModel>		

      </[module]>		

      <[module]_mysql4>		

      <class>[Namespace]_[Module]_Model_Mysql4</class>		

      <entities>		

      <[module]>		

      <table>[module]</table>		

      </[module]>		

      </entities>		

      </[module]_mysql4>		

      </models>		

      <resources>		

      <[module]_setup>		  <items module="[module]">
		 <title>Manage Items</title>
      <setup>
		  <sort_order>0</sort_order>
      <module>[Namespace]_[Module]</module>		

      </setup>		

      <connection>		

      <use>core_setup</use>		

      </connection>		

      </[module]_setup>		

      <[module]_write>		

      <connection>		

      <use>core_write</use>		

      </connection>		

      </[module]_write>		

      <[module]_read>		

      <connection>		

      <use>core_read</use>		

      </connection>		

      </[module]_read>		

      </resources>		

      <blocks>		

      <[module]>		

      <class>[Namespace]_[Module]_Block</class>		

      </[module]>		

      </blocks>		

      <helpers>		

      <[module]>		

      <class>[Namespace]_[Module]_Helper</class>		

      </[module]>		

      </helpers>		

      </global>		

      </config>

Create Helper

/app/code/local/<Namespace>/<Module>/Helper/Data.php

<?php

class <Namespace>_<Module>_Helper_Data extends Mage_Core_Helper_Abstract

{

}


Create Models

/app/code/local/<Namespace>/<Module>/Model/<Module>.php

<?php

class <Namespace>_<Module>_Model_<Module> extends Mage_Core_Model_Abstract

{

public function _construct()

{

parent::_construct();

$this->_init('<module>/<module>');

}

}

/app/code/local/<Namespace>/<Module>/Model/Mysql4/<Module>.php

<?php

class <Namespace>_<Module>_Model_Mysql4_<Module> extends Mage_Core_Model_Mysql4_Abstract

{

public function _construct()

{

$this->_init('<module>/<module>', '<module>_id');

}

}

NOTE: The ‘<module>_id’ refers to the PRIMARY KEY in your database table.

/app/code/local/<Namespace>/<Module>/Model/Mysql4/<Module>/Collection.php

<?php

class <Namespace>_<Module>_Model_Mysql4_<Module>_Collection extends Mage_Core_Model_Mysql4_Collection_Abstract

{

public function _construct()

{

//parent::__construct();

$this->_init('<module>/<module>');

}

}


SQL Setup

/app/code/local/<Namespace>/<Module>/sql/<module>_setup/mysql4-install-0.1.0.php

<?php

$installer = $this;

$installer->startSetup();

$installer->run("

-- DROP TABLE IF EXISTS {$this->getTable('<module>')};

CREATE TABLE {$this->getTable('<module>')} (

`<module>_id` int(11) unsigned NOT NULL auto_increment,

`title` varchar(255) NOT NULL default '',

`content` text NOT NULL default '',

`status` smallint(6) NOT NULL default '0',

`created_time` datetime NULL,

`update_time` datetime NULL,

PRIMARY KEY (`<module>_id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

");

$installer->endSetup();

NOTE: Please note the <module> text that needs to be replaced. This SQL structure is up to you, this is merely a starting point.

Template Design

/app/design/frontend/<interface>/<theme>/layout/<module>.xml

<?xml version="1.0"?>

<layout version="0.1.0">

<[module]_index_index>

<reference name="content">

<block type="[module]/[module]" name="[module]" />

</reference>

</[module]_index_index>

</layout>

NOTE: The block type will automatically figure out what template file to use based on the second [module] declaration.

As an alternate way of declaring what template file to use you can use this: /app/design/frontend/<interface>/<theme>/layout/<module>.xml

<?xml version="1.0"?>

<layout version="0.1.0">

<[module]_index_index>

<reference name="content">

<block type="core/template" name="[module]" template="[module]/[module].phtml" />

</reference>

</[module]_index_index>

</layout>

/app/design/frontend/<interface>/<theme>/template/<Module>/<module>.phtml

<?php echo $this->__('Module List') ?>

<?php

/*

This will load one record from your database table.

load(<module>_id) will load whatever ID number you give it.

*/

/*

$news = Mage::getModel('<module>/<module>')->load(1);

echo $news->get<Module>Id();

echo $news->getTitle();

echo $news->getContent();

echo $news->getStatus();

*/

/*

This block of code loads all of the records in the database table.

It will iterate through the collection and the first thing it will do

is set the Title to the current value of $i which is incremented each

iteration and then echo that value back out.  At the very end it will

save the entire collection.

*/

/*

$i = 0;

$collection = Mage::getModel('<module>/<module>')->getCollection();

$collection->setPageSize(5);

$collection->setCurPage(2);

$size = $collection->getSize();

$cnt = count($collection);

foreach ($collection as $item) {

$i = $i+1;

$item->setTitle($i);

echo $item->getTitle();

}

$collection->walk('save');

*/

/*

This shows how to load one value, change something and save it.

*/

/*

$object = Mage::getModel('<module>/<module>')->load(1);

$object->setTitle('This is a changed title');

$object->save();

*/

?>

NOTE: Uncomment anything that you would like to use and this is just a starting point and some common methods for you to try and pull the data out.

In this section I am utilizing the built-in Grid Widgets and form capabilities to create a form to allow editing and creating new items for your custom database.

Directory Additions

Here is the revised directory setup due to the additions and changes we need for the backend module.

/app/code/local/<Namespace>/<Module>/

  1. Block/
  2. Adminhtml/
  3. <Module>/
  4. Edit/
  5. Tab/
  6. controllers/
  7. Adminhtml/
  8. etc/
  9. Helper/
  10. Model/
  11. Mysql4/
  12. <Module>/
  13. sql/
  14. <module>_setup/

Blocks

These control the setup and appearance of your grids and the options that they display.

NOTE: Please note the fact that Block comes before Adminhtml in the class declaration. In any of the Magento modules in Adminhtml it is the opposite. For your module to work it has to be Block_Adminhtml otherwise you will get a ‘Cannot redeclare module…’ error.

/app/code/local/<Namespace>/<Module>/Block/Adminhtml/<Module>.php

<?php

class <Namespace>_<Module>_Block_Adminhtml_<Module> extends Mage_Adminhtml_Block_Widget_Grid_Container

{

public function __construct()

{

$this->_controller = 'adminhtml_<module>';

$this->_blockGroup = '<module>';

$this->_headerText = Mage::helper('<module>')->__('Item Manager');

$this->_addButtonLabel = Mage::helper('<module>')->__('Add Item');

parent::__construct();

}

}

/app/code/local/<Namespace>/<Module>/Block/Adminhtml/<Module>/Edit.php

<?php

class <Namespace>_<Module>_Block_Adminhtml_<Module>_Edit extends Mage_Adminhtml_Block_Widget_Form_Container

{

public function __construct()

{

parent::__construct();

$this->_objectId = 'id';

$this->_blockGroup = '<module>';

$this->_controller = 'adminhtml_<module>';

$this->_updateButton('save', 'label', Mage::helper('<module>')->__('Save Item'));

$this->_updateButton('delete', 'label', Mage::helper('<module>')->__('Delete Item'));

}

public function getHeaderText()

{

if( Mage::registry('<module>_data') && Mage::registry('<module>_data')->getId() ) {

return Mage::helper('<module>')->__("Edit Item '%s'", $this->htmlEscape(Mage::registry('<module>_data')->getTitle()));

} else {

return Mage::helper('<module>')->__('Add Item');

}

}

}

/app/code/local/<Namespace>/<Module>/Block/Adminhtml/<Module>/Grid.php

<?php

class <Namespace>_<Module>_Block_Adminhtml_<Module>_Grid extends Mage_Adminhtml_Block_Widget_Grid

{

public function __construct()

{

parent::__construct();

$this->setId('<module>Grid');

// This is the primary key of the database

$this->setDefaultSort('<module>_id');

$this->setDefaultDir('ASC');

$this->setSaveParametersInSession(true);

}

protected function _prepareCollection()

{

$collection = Mage::getModel('<module>/<module>')->getCollection();

$this->setCollection($collection);

return parent::_prepareCollection();

}

protected function _prepareColumns()

{

$this->addColumn('<module>_id', array(

'header' => Mage::helper('<module>')->__('ID'),

'align' =>'right',

'width' => '50px',

'index' => '<module>_id',

));

$this->addColumn('title', array(

'header' => Mage::helper('<module>')->__('Title'),

'align' =>'left',

'index' => 'title',

));

/*

$this->addColumn('content', array(

'header'    => Mage::helper('<module>')->__('Item Content'),

'width'     => '150px',

'index'     => 'content',

));

*/

$this->addColumn('created_time', array(

'header' => Mage::helper('<module>')->__('Creation Time'),

'align' => 'left',

'width' => '120px',

'type' => 'date',

'default' => '--',

'index' => 'created_time',

));

$this->addColumn('update_time', array(

'header' => Mage::helper('<module>')->__('Update Time'),

'align' => 'left',

'width' => '120px',

'type' => 'date',

'default' => '--',

'index' => 'update_time',

));

$this->addColumn('status', array(

'header' => Mage::helper('<module>')->__('Status'),

'align' => 'left',

'width' => '80px',

'index' => 'status',

'type' => 'options',

'options' => array(

1 => 'Active',

0 => 'Inactive',

),

));

return parent::_prepareColumns();

}

public function getRowUrl($row)

{

return $this->getUrl('*/*/edit', array('id' => $row->getId()));

}

}

/app/code/local/<Namespace>/<Module>/Block/Adminhtml/<Module>/Edit/Form.php

<?php

class <Namespace>_<Module>_Block_Adminhtml_<Module>_Edit_Form extends Mage_Adminhtml_Block_Widget_Form

{

protected function _prepareForm()

{

$form = new Varien_Data_Form(array(

'id' => 'edit_form',

'action' => $this->getUrl('*/*/save', array('id' => $this->getRequest()->getParam('id'))),

'method' => 'post',

)

);

$form->setUseContainer(true);

$this->setForm($form);

return parent::_prepareForm();

}

}

/app/code/local/<Namespace>/<Module>/Block/Adminhtml/<Module>/Edit/Tabs.php

<?php

class <Namespace>_<Module>_Block_Adminhtml_<Module>_Edit_Tabs extends Mage_Adminhtml_Block_Widget_Tabs

{

public function __construct()

{

parent::__construct();

$this->setId('<module>_tabs');

$this->setDestElementId('edit_form');

$this->setTitle(Mage::helper('<module>')->__('News Information'));

}

protected function _beforeToHtml()

{

$this->addTab('form_section', array(

'label' => Mage::helper('<module>')->__('Item Information'),

'title' => Mage::helper('<module>')->__('Item Information'),

'content' => $this->getLayout()->createBlock('<module>/adminhtml_<module>_edit_tab_form')->toHtml(),

));

return parent::_beforeToHtml();

}

}

/app/code/local/<Namespace>/<Module>/Block/Adminhtml/<Module>/Edit/Tab/Form.php

<?php

class <Namespace>_<Module>_Block_Adminhtml_<Module>_Edit_Tab_Form extends Mage_Adminhtml_Block_Widget_Form

{

protected function _prepareForm()

{

$form = new Varien_Data_Form();

$this->setForm($form);

$fieldset = $form->addFieldset('<module>_form', array('legend'=>Mage::helper('<module>')->__('Item information')));

$fieldset->addField('title', 'text', array(

'label' => Mage::helper('<module>')->__('Title'),

'class' => 'required-entry',

'required' => true,

'name' => 'title',

));

$fieldset->addField('status', 'select', array(

'label' => Mage::helper('<module>')->__('Status'),

'name' => 'status',

'values' => array(

array(

'value' => 1,

'label' => Mage::helper('<module>')->__('Active'),

),

array(

'value' => 0,

'label' => Mage::helper('<module>')->__('Inactive'),

),

),

));

$fieldset->addField('content', 'editor', array(

'name' => 'content',

'label' => Mage::helper('<module>')->__('Content'),

'title' => Mage::helper('<module>')->__('Content'),

'style' => 'width:98%; height:400px;',

'wysiwyg' => false,

'required' => true,

));

if ( Mage::getSingleton('adminhtml/session')->get<Module>Data() )

{

$form->setValues(Mage::getSingleton('adminhtml/session')->get<Module>Data());

Mage::getSingleton('adminhtml/session')->set<Module>Data(null);

} elseif ( Mage::registry('<module>_data') ) {

$form->setValues(Mage::registry('<module>_data')->getData());

}

return parent::_prepareForm();

}

}

Part II : creating controllers

« Previous PageNext Page »