Copying Product Attributes to Quote & Order Items

Add this to your XML;

<global>
    <sales>
        <quote>
            <item>
                <product_attributes>
                    <location/>
                </product_attributes>
            </item>
        </quote>
    </sales>
</global>

  • This makes the product attributes accessible to the Mage_Sales_Model_Quote_Config class’ getProductAttributes() method. This reads in the sales/quote/item/product_attributes node.

  • This is called by the _assignProducts method of the Mage_Sales_Model_Resource_Quote_Item_Collection‘s _assignProducts() method, where it adds all of the attributes to the product collection of the quote item collection.

Add the columns to the quote and order item tables

  • Create an installer with the following:

    $installer = new Mage_Sales_Model_Resource_Setup('core_setup');
    
    $entities = array(
        'quote_item',
        'order_item'
    );
    
    $options = array(
        // For some reason, VARCHAR works here, whereas elsewhere it must be TYPE_TEXT with a length of 255.
        'type'     => Varien_Db_Ddl_Table::TYPE_VARCHAR,
        'visible'  => true,
        'required' => false
    );
    
    foreach ($entities as $entity) {
        $installer->addAttribute($entity, 'location', $options);
    }
    

  • The addAttribute() method of the Mage_Sales_Model_Resource_Setup creates the columns on the quote_item and order_item tables.

Copy the attributes to the quote item

Unlike copying from quote items to order items, there isn’t an XML method to do this – it has to be accomplished through an observer. Add the following to the config (with the observer / method substituted):

<frontend>
    <events>
        <sales_quote_item_set_product>
            <observers>
                <observer_name>
                    <class>model/observer</class>
                    <method>addAttributesToQuoteItem</method>
                </observer_name>
            </observers>
        </sales_quote_item_set_product>
    </events>
</frontend>

Then create the following method for the observer above:

    public function addAttributesToQuoteItem($observer){
        $quoteItem = $observer->getQuoteItem();
        $product = $observer->getProduct();
        $quoteItem->setLocation($product->getLocation());
    }

Note: Values Don’t have to come from the product item

Any arbitrary information could be set on the quote or quote item; it does not have to come from the product itself. E.g. A different type of ship note could be set by a different observer. The associated columns just need to exist on the quote or quote item tables.

Copying quote item attributes to the order item

  • This can be achieved with a small amount of XML:
  <global>
    <fieldsets>
        <sales_convert_quote_item>
            <location>
                <to_order_item>*</to_order_item>
            </location>
        </sales_convert_quote_item>
    </fieldsets>
</global>

Note: This will not copy the data to the sales_flat_shipment_item table.

Converting from an order item to other types of item

The following will copy the object’s attributes when converting the quote item back to a quote item, an invoice item, and a credit memo item

<global>
    <fieldsets>
        <sales_convert_order_item>
            <location>
                <to_quote_item>*</to_quote_item>
                <to_invoice_item>*</to_invoice_item>
                <to_cm_item>*</to_cm_item>
            </location>
        </sales_convert_order_item>
    </fieldsets>
</global>

These are used in the Mage_Sales_Model_Convert_Order class’ itemToQuoteItem, itemToInvoiceItem, and itemToCreditmemoItem methods. Note: In default Magento, it does not appear that the itemToQuoteItem is used, so this should be included for third party extensions which may rely on this method.

Magento 2.0: Fixing a failed install

Seemingly due to some issues with my MySQL Server, Magento 2’s installer failed before it could complete. It left me with the following error in my browser:

Unable to proceed: the maintenance mode is enabled. 

Aha! I can turn maintenance mode off – that’s easy! Just watch as this error falls like that gummy bear tower you tried to build in junior school! Let’s hop over to Magento’s bin folder…

./magento maintenance:disable

Woohoo, and all is… erm.. yup. Still broken:

SQLSTATE[42S02]: Base table or view not found: 1146 Table &#039;magentorc.store_website&#039; doesn&#039;t exist, query was: SELECT `main_table`.* FROM `store_website` AS `main_table` WHERE (`is_default` = &#039;1&#039;) AND (main_table.website_id &gt; 0) ORDER BY main_table.sort_order ASC, main_table.name ASC

Hmm, a quick look at the magentorc table I'd previously created shows it's completely empty – looks like the MySQL issue was the dastardly culprit! After trying to get it to perform the setup again using a variety of cli commands (and a lot of swearing), I instead opted to remove the following file:

app/etc/env.php

This is where Magento keeps its database details. Removing this started the install process once more – voilà!

Debugging MySQL installed through Homebrew on Yosemite

I recently came across an annoying issue where MySQL would not start on Mac OS X Yosemite, exiting with the following:

ERROR 2002 (HY000): Can&#039;t connect to local MySQL server through socket &#039;/tmp/mysql.sock&#039; (2)

Join me on a journey which makes putting a greased ape on a waltzer and getting him to rate the experience seem like an easy task.

Finding the log files

To fix what’s going wrong, we need to know what’s going wrong. Unfortunately, finding log files (for me at least) can often be a bigger job than fixing the issue at hand. My version of MySQL is installed through Brew. After six days of Googling, I eventually found MySQL’s error log here:

tail -f /usr/local/var/mysql/Daves-MacBook-Pro.local.err

Four and a half days trawling through something which makes War and Peace look like a children’s book, I stumbled on a possible cause for the error:

2015-11-12T15:35:05.354808Z 0 [Warning] InnoDB: Ignoring tablespace `defender/wishlist_item_option` because it could not be opened.

Aha! It looks like one of the databases has become corrupted, MySQL can't open it, and it's failing! Great. Let's try moving the database elsewhere and see how we get on.

ERROR 2002 (HY000): Can&#039;t connect to local MySQL server through socket &#039;/tmp/mysql.sock&#039; (2)

No dice. Right, looking through the log shows up another error:

2015-11-12T15:48:13.051616Z 0 [ERROR] unknown variable &#039;key_buffer=32M&#039;

Variable variables

So, it looks like the variable key_buffer has been replaced with key_buffer_size in a newer version of MySQL. This exists in my MySQL config file:

/usr/local/etc/my.cnf

Changing this sorted my headache, and allowed me to get back to those yummy scrummy databases once more.