0

I'm about to set my webshop live. Today I installed Ideal payment and suddenly when I order a product I get an error. The error only pops up when I use Ideal as payment.

Fatal error: Call to a member function getId() on a non-object in /usr/home/xxx/domains/xxx.nl/public_html/app/design/frontend/base/default/template/email/order/items/order/default.phtml on line 29

This is the code and my custom attributes: (Verpakking, EAN, Z-index)

<?php $_item = $this->getItem() ?>
<?php $_order = $this->getItem()->getOrder(); ?>
<?php $_product = Mage::getModel('catalog/product')->load($_item->getProduct()->getId()); ?> 
<tr>
    <td align="left" valign="top" style="padding:3px 9px; border-bottom:1px dotted #CCCCCC;">
        <strong><?php echo $this->htmlEscape($_item->getName()) ?></strong><br>

        Verpakking: <?php echo $_product->getVerpakking(); ?><br>
        EAN: <?php echo $_product->getEancodeeenheid(); ?><br>
        Z-index: <?php echo $_product->getZindexnummer(); ?>

It has to do with these custom attributes, without them there is no error.

1 Answer 1

1

When working with product attributes for order items it is not OK to get the product details by loading the product data for 2 reasons:

  1. the product might be missing (deleted at some point)
  2. it affects the performance because you have to load every attribute

In my opinion it's best to add the product attributes you need to the quote item and carry them for all the other item types (order item, invoice item, shipment item and credit memo item). In order to achieve this you will need (yes you guest it) an extension that adds a column for each attribute you need on the corresponding item table. After that you will not need this code:

$_product = Mage::getModel('catalog/product')->load($_item->getProduct()->getId())

You will be able to make a simple call like:

Verpakking: <?php echo $_item->getVerpakking(); ?><br>

The following is an example for one attribute, but you can just mimic the behavior for the rest of the attributes. I will take the attribute with code verpakking.
Let's call the extension Easylife_Sales. For the extension you need the following files:

app/etc/modules/Easylife_Sales.xml - declaration file: (I'm anxious to work with Magento 2.0 so I won't need this declaration file anymore).

<?xml version="1.0"?>
<config>
    <modules>
        <Easylife_Sales>
            <active>true</active>
            <codePool>local</codePool>
            <depends>
                <Mage_Sales /><!-- your extension should depend on Mage_Sales -->
            </depends>
        </Easylife_Sales>
    </modules>
</config>

app/code/local/Easylife/Sales/etc/config.xml - the configuration file:

<?xml version="1.0"?>
<config>
    <modules>
        <Easylife_Sales>
            <version>0.0.1</version>
        </Easylife_Sales>
    </modules>
    <global>
        <models>
            <easylife_sales><!-- model declaration -->
                <class>Easylife_Sales_Model</class>
            </easylife_sales>
        </models>
        <events>
            <sales_quote_item_save_before><!-- event to attach the custom attributes to the quote items -->
                <observers>
                    <easylife_sales>
                        <class>easylife_sales/observer</class>
                        <method>addCustomAttributes</method>
                    </easylife_sales>
                </observers>
            </sales_quote_item_save_before>
        </events>
        <fieldsets>
            <sales_convert_quote_item>
                <verpakking><!-- all attributes that need to be passed from the quote item to the order item-->
                    <to_order_item>*</to_order_item>
                </verpakking>
<!-- add here one tag for each attribute you want to pass to the order item -->
            </sales_convert_quote_item>
            <sales_convert_order_item><!-- This is not mandatory but useful for consistency-->
                <verpakking><!-- all attributes that need to be passed from the order item to quote item, invoice item, shipping item and cm item-->
                    <to_quote_item>*</to_quote_item>
                    <to_invoice_item>*</to_invoice_item>
                    <to_shipment_item>*</to_shipment_item>
                    <to_cm_item>*</to_cm_item>
                </verpakking>
<!-- add here one section for each attribute -->
            </sales_convert_order_item>
        </fieldsets>
        <sales>
            <quote>
                <item>
                    <product_attributes>
                        <verpakking /><!-- each product attribute code that needs to be loaded when using a quote item -->
<!-- add here one tag for each attribute with the attribute code-->
                    </product_attributes>
                </item>
            </quote>
        </sales>
        <resources>
            <easylife_sales_setup><!-- install scripts that will add the new columns to the sales tables-->
                <setup>
                    <module>Easylife_Sales</module>
                    <class>Mage_Sales_Model_Resource_Setup</class>
                </setup>
            </easylife_sales_setup>
        </resources>
    </global>
</config>

app/code/local/Easylife/Sales/Model/Observer.php - used for filling the additional columns of the quote item.

<?php
class Easylife_Sales_Model_Observer{
    public function addCustomAttributes($observer){
        $item = $observer->getEvent()->getItem();
        if ($product = $item->getProduct()){
            $item->setVerpakking($product->getVerpakking());
            //add here one line for each product attribute
        }
        return $this;
    }
}

app/code/local/Easylife/Sales/sql/easylife_sales_setup/install-0.0.1.php - the extension install script that adds the columns to the needed tables.

<?php
$this->startSetup();
//add a column to the quote item table
$this->getConnection()
    ->addColumn($this->getTable('sales/quote_item'), 'verpakking', array(
        'type'      => Varien_Db_Ddl_Table::TYPE_TEXT, //type should match the product type. see the class `Varien_Db_Ddl_Table` for other column types
        'length'    => 32,
        'nullable'  => true,
        'comment'   => 'Verpakking'
    ));
//add a column to the order item table
$this->getConnection()
    ->addColumn($this->getTable('sales/order_item'), 'verpakking', array(
        'type'      => Varien_Db_Ddl_Table::TYPE_TEXT,//type should match the product type. see the class `Varien_Db_Ddl_Table` for other column types
        'length'    => 32,
        'nullable'  => true,
        'comment'   => 'Verpakking'
    ));
//add a column to the shipment item table
$this->getConnection()
    ->addColumn($this->getTable('sales/shipment_item'), 'verpakking', array(
        'type'      => Varien_Db_Ddl_Table::TYPE_TEXT,//type should match the product type. see the class `Varien_Db_Ddl_Table` for other column types
        'length'    => 32,
        'nullable'  => true,
        'comment'   => 'Verpakking'
    ));
//add a column to the invoice item table
$this->getConnection()
    ->addColumn($this->getTable('sales/invoice_item'), 'verpakking', array(
        'type'      => Varien_Db_Ddl_Table::TYPE_TEXT,//type should match the product type. see the class `Varien_Db_Ddl_Table` for other column types
        'length'    => 32,
        'nullable'  => true,
        'comment'   => 'Verpakking'
    ));
//add a column to the credit memo item table
$this->getConnection()
    ->addColumn($this->getTable('sales/creditmemo_item'), 'verpakking', array(
        'type'      => Varien_Db_Ddl_Table::TYPE_TEXT,//type should match the product type. see the class `Varien_Db_Ddl_Table` for other column types
        'length'    => 32,
        'nullable'  => true,
        'comment'   => 'Verpakking'
    ));
//add here columns for additional attributes by cloning the statements above and changing the column names. 
//The column names must be the same as the product attribute code for an easier use
$this->endSetup();

That's it. Clear the cache and make a call to your website (backend or frontend) to install the extension. Just to make sure, check the tables sales_flat_*_item to see if your columns have been added. Now you can use in your e-mail (like I've said before):

Verpakking: <?php echo $_item->getVerpakking(); ?><br>
13
  • Hey Marius, thanks allot for this. When I see databases needed to be added I get very scary for some reason. Hoped and hope there was a easier way to do this. Because I'm not really a coder I don't think I have balls enouf to implement this. If it doesn't work then I don't know how to fix it. If someone knows a easier way to do this.
    – magmarc
    Jul 10, 2013 at 15:05
  • You can try it. It should work if you just copy/paste the code I wrote and add the rest of the attributes where my comments are. You have nothing to lose. If it does't work, just remove the files and the column tables.
    – Marius
    Jul 10, 2013 at 20:52
  • Does the install run itself after going to the frontend website and do I need to remove it after its installed? Do you know in which table the columns will be add?
    – magmarc
    Jul 11, 2013 at 8:02
  • The install runs by itself when you do your first call to your website after clearing the cache. You don't need to remove anything after that. The columns should be added to the tables that look like this sales_flat_*_item (* can be quote, order, invoice, shipment, creditmemo)
    – Marius
    Jul 11, 2013 at 8:10
  • Hey thanks allot again, I have just did it and there is no error. I still might have some questions after inspection. The emailtemplate is blank where "Verpakking: xxx" needs to be but need to check it.
    – magmarc
    Jul 11, 2013 at 9:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.