سؤال

Today, I am running into the following problem: A module I developed works very well in a Magento 1.7 version store. Now, I need to adapt it to also work with a Magento 1.5 store.

One point at which the compatibility runs apart is in my collection where I am exending the class Mage_Core_Model_Resource_Db_Collection_Abstract. This class does not exist in Magento 1.5, but it has some nice functionality like getMainTable(). One thing I could do is to instead use the class Varien_Data_Collection_Db which is inherited from in Mage_Core_Model_Resource_Db_Collection_Abstract. This works, but then I cannot use the getMainTable() method anymore - even not in the 1.7 store where it actually exists.

How do you handle such version specific quirks? It seems absurd to write a custom class which implements the stuff version 1.7 already has and thereby duplicate code in that version. On the other hand, it is bad not to have the function and use worse coding habits like hard-coding instead. So, is there any good approach in writing Magento modules which are backwards-compatible?

هل كانت مفيدة؟

المحلول

You could create an intermediary class that implements all the functions that you require and depending on the version of magento call parent's implementation or use your own implementation:

model/Int.php

<?php
  if (!version_compare(Mage::getVersion(), '1.7', '>=')) {
    class N_M_Model_Int extends Mage_Core_Model_Resource_Db_Collection_Abstract
    {
    }
  } else {
    class N_M_Model_Int extends Varien_Data_Collection_Db
    {
      public function getMainTable()
      {
        // my implementation
      }
    }
  }
?>

model/Final.php

<?php
  class N_M_Model_Final extends N_M_Model_Int
  {
    // common code between all the versions
  }
?>

نصائح أخرى

This is perhaps not the exact answer you are looking for, but I can't imagine many people are developing extensions for older versions.

Just upgrade, its inevitable anyway

The obvious solution is for the 1.5 customer to upgrade to 1.7 (1.5 is a horribly broken release anyway).

But if you must

If we had to tackle it, it would just be a case of backing up the module with a secondary foundation module to back-port the core functionality that you require. Then when the time comes to upgrade, the dependency module could merely be deleted/removed.

The downsides being that you could potentially end up overriding abstract classes merely to add/modify a single function. The time invested in this could well be on par with just upgrading the store to begin with.

In terms of making extensions backwards compatible - it seems an odd practice - as you be making compromises for newer releases. Extensions tend to age naturally, so that rather being back-wards compatible; you develop upon it to make it forwards compatible.

If you've ever looked at the source code of 3rd party modules; they tend to be filled with Mage::getVersion() calls and conditional statements - all to be multi-version compatible. Its messy and should be avoided. In all reality - you should have different versions of extensions, for different versions of Magento. Otherwise you'll be faced supporting an extension that has deviations in class methods and an increasing number of conditional statements.

Although here's a good example of why not

I understand your logic. But what happens in cases such as the 1.4.1 > 1.4.2 upgrade and the EAV sales tables were dropped. Any newer functions operated on the basis of this table now being flat - so trying to back-port this is far more hassle than its worth. This may be an extreme and you'll clearly make a judgement call on how much time to invest.

The latest version of Magento is forever going to be a moving target and given the choice between making new modules work with older stores - or older modules work with newer stores. I know what we'd rather do. Deprecation of functions is slow and graceful and you have plenty of time to make them newer.

What you are facing is pretty easy to fix. Starting 1.6 some Mysql4 classes were moved on to Resource classes but backward compatibility is still supported as Magento developers have done the necessary.

For Mage_Core_Model_Resource_Db_Collection_Abstract classes use Mage_Core_Model_Mysql4_Collection_Abstract instead

For Mage_Core_Model_Resource_Db_Abstract classes use Mage_Core_Model_Mysql4_Abstract instead

If you go to those Mysql4 classes you will find that they are blank and are just extending the Resource classes properly

Hope this helps you out

In addition to Domen Vrankar's answer, you can also do something like:

<?php

if (!version_compare(Mage::getVersion(), '1.7', '>=')) {
    $code = "\nclass N_M_Model_Int extends Mage_Core_Model_Resource_Db_Collection_Abstract\n";
} else {
    $code = "\nclass N_M_Model_Int extends Varien_Data_Collection_Db\n";
}

$code .= <<<FEED
{
    //class implementation

} // END OF CLASS
FEED;

eval ( $code );

Not sure someone would prefer this method, but I've seen SweetTooth Rewards do this.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى magento.stackexchange
scroll top