Integrating Yii with Magento

Hi all,

I’m maintaining a Magento webshop. Since it’s very hard and time consuming to customize Magento, I thought of integrating Yii. Yii could supply many of the interface parts, it could handle Ajax requests, maintain cronjobs and all kinds of other tasks. Yii could sit in the background, taking care of all kind of non-core tasks that are hard to do in Magento.

It would be great to be able to develop in a quick, easy and elegant framework, and once everything is working ok, include it in Magento.

Offcourse integrating Yii would take up some resources, but extending Magento does too. And even if the performance loss is unacceptable, Yii could still be used to supply pages via ajax.

Has anyone ever tried this before? And what would be the best way to include views from within Magento?

Just a follow-up; I have tried including Yii into Magento, it works, but there are conflicts. I then tried to include the Magento API into Yii, but the Zend Autoloader and the Yii autoloader would start fighting: Magento tries to load Magento classes from the Yii base folder and the other way around. I’m not sure how to fix this.

Lastly I connected Yii to the Magento DB and created some models from Magento tables, I used that data to create some views and ajax-functions and included that within Magento, that worked great, the development is much easier and you speed Magento up by 1) using a faster framework (yii) and 2) loading data with ajax, so it doesn’t add to the initial loading time of the page.

When I got some spare time, I’ll try again to load the Magento api in Yii, if anyone has suggestions, please share…

Hi.

Autoloader conflicts can be circumvented by disabling Yii autoloader while doing Magentoo stuff. Following works for me:




$autoloaders = spl_autoload_functions();


$yii = $autoloaders[0];

spl_autoload_unregister ($yii);


// Start magentoo stuff

include('app/Mage.php');


Mage::App('default');

$product_model = Mage::getModel('catalog/product');

$product = $product_model->load($id);


// Back to Yii


restore_error_handler();

restore_exception_handler();

spl_autoload_register($yii);




How did you get that working? I got this error

My directory structure is like this:

magento: /magento/

yii: /magento/yii/app/

So I included mage.php like this: include(’../../app/Mage.php’);

Try to change:




spl_autoload_register($yii);



To




spl_autoload_register($yii, true, true);



It looks like Magento autoloader tries to load Yii class (and it fails to do so)

Thanks man, looks like it’s working :D

Would any of you guys care to share your experience with this integration… maybe a tutorial or howto on the approach, if not even code examples and config and setup files…

Currently I’m using only 1 model+controller where I perform all kinds of Magento tasks

Here it is (I hope the names and comments are clear enough, I’m happy to provide explanation)

controller:


<?php


class CronController extends Controller

{

    //set 'last_added' attribute in magento in the order of last modified

    public function actionLastModified()

    {

        $mage = new MagentoActions;

        $mage->setLastModified();


        die("ok");

    }


    //put all products that have a reduced price in the category sale

    public function actionSetSale()

    {

        $mage = new MagentoActions;

        $mage->setSale();


        die("ok");

    }


    //loop blog posts, check amount of comments and update table

    public function actionUpdateBlogCommentCount()

    {

        $mage = new MagentoActions;

        $mage->updateBlogCommentCount();


        die("ok");

    }


    //clean up redundant Magento files

    public function actionCleanUp()

    {

        $mage = new MagentoActions;

        $mage->cleanUpFiles();

        $mage->cleanUpDB();


        die("ok");

    }


    //to a reindex

    public function actionReindexData()

    {

        $mage = new MagentoActions;

        $mage->reindexData();


       die("ok");

    }


    //subscribe users to mailing

    public function actionSyncNewsletterSubscribers()

    {

        $mage = new MagentoActions;

        $mage->syncNewsletterSubscribers();


        die("ok");

    }


}



Model:




<?php

class MagentoActions

{

    function magento_init()

    {

        $autoloaders = spl_autoload_functions();


        $yii = $autoloaders[0];

        spl_autoload_unregister($yii);


        // Start magentoo stuff

        require_once('../../app/Mage.php');


        Mage::App('default');


        Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);

    }


    public function setSale()

    {

        $this->magento_init();


        $sale_cat_id = 7;

        foreach (array(1) as $storeId) {

            $products = Mage::getResourceModel('reports/product_collection')

                    ->setStoreId($storeId)

                    ->addStoreFilter($storeId)

                    ->addAttributeToFilter('visibility', 4)

                    ->addAttributeToSelect('*');


            foreach ($products as $product) {

                $orig_product_cats = $product_cats = $product->getCategoryIds();

                if ($product->getFinalPrice() < $product->getPrice()) {

                    $product_cats[] = $sale_cat_id;

                    $product_cats = array_unique($product_cats);

                }

                else {

                    $product_cats = array_diff($product_cats, array($sale_cat_id));

                }


                if ($orig_product_cats != $product_cats) {

                    $product->setCategoryIds($product_cats);

                    $product->save();

                }

            }

        }

    }


    public function setLastModified()

    {

        $this->magento_init();


        foreach (array(1) as $storeId) {

            $products = Mage::getResourceModel('reports/product_collection')

                    ->setStoreId($storeId)

                    ->addStoreFilter($storeId)

                    ->addAttributeToFilter('visibility', 4)

                    ->addAttributeToSort('entity_id', 'desc')

                    ->setPageSize(10000000)

                    ->setCurPage(1)

                    ->addAttributeToSelect('*');


            $i = 1;

            foreach ($products as $product) {

                $nr = str_pad($i, 10, "0", STR_PAD_LEFT);

                $product->setLastAdded($nr);

                $product->save();

                $i++;

            }

        }

    }


    //checks the amount of comment

    public function updateBlogCommentCount()

    {

        $sql = "select post_id, count(comment_id) as comments from aw_blog_comment where status=2 group by post_id";

        $rows = Yii::app()->db->createCommand($sql)->query()->readAll();

        foreach ($rows as $row)

        {

            $sql = "update aw_blog set comments = " . $row['comments'] . " where post_id=" . $row['post_id'];

            Yii::app()->db->createCommand($sql)->query();

        }

    }


    //cleanup temp/cache files

    public function cleanUpFiles()

    {

        $dirs = array(

            '../../downloader/pearlib/cache/*',

            '../../downloader/pearlib/download/*',

            '../../var/cache/',

            '../../var/log/',

            '../../var/report/',

            '../../var/session/',

            '../../var/tmp/'

        );


        foreach ($dirs as $v => $k) {

            exec('rm -rf ' . $k);

        }

    }


    //cleanup log/tmp db tables

    public function cleanUpDB()

    {

        $tables = array(

            'dataflow_batch_export',

            'dataflow_batch_import',

            'log_customer',

            'log_quote',

            'log_summary',

            'log_summary_type',

            'log_url',

            'log_url_info',

            'log_visitor',

            'log_visitor_info',

            'log_visitor_online',

            'report_event'

        );


        foreach ($tables as $v => $k) {

            $sql = "TRUNCATE $k";

            Yii::app()->db->createCommand($sql)->query();

        }

    }


    public function reindexData($index_name = "all")

    {

        /* index names:

         catalog_product_attribute

         catalog_product_price

         catalog_url

         catalog_product_flat

         catalog_category_flat

         catalog_category_product

         catalogsearch_fulltext

         tag_summary

         cataloginventory_stock

        */


        $this->magento_init();

        echo system('php ../../shell/indexer.php --reindex all');

    }


    public function syncNewsletterSubscribers()

    {

        $this->magento_init();

        $collection = Mage::getResourceModel('newsletter/subscriber_collection')->showStoreInfo()->showCustomerInfo();


        foreach ($collection as $customer) {

            $first_name = $customer->customer_firstname;

            $last_name = $customer->customer_lastname;

            $email = $customer->subscriber_email;

            //submit

            $fields = array(

                'customers_email_address' => $email,

                'customers_email_format' => $email,

                'customers_firstname' => $first_name,

                'customers_lastname' => $last_name,

                'entry_street_address' => "unknown",

                'entry_suburb' => "-",

                'entry_city' => "onbekend",

                'entry_state' => "-",

                'entry_postcode' => "onbekend",

                'entry_country_id' => "NLD",

                'customers_telephone' => "onbekend",

                'customers_fax' => "onbekend",

                'customers_newsletter' => TRUE,

                'kcm_title' => "",

            );


            $subscriber = new InterspireApi;

            $subscriber->iemAddSubscriberToList($fields);

        }

    }


}

Another thing, if you use your Yii app only for Magento tasks, you can get the db login info of Magento this way:

(in config/main.php)


//get info from magento

$xml = simplexml_load_file('../../app/etc/local.xml');

$mysql_host = $xml->global->resources->default_setup->connection->host;

$mysql_user = $xml->global->resources->default_setup->connection->username;

$mysql_pass = $xml->global->resources->default_setup->connection->password;

$mysql_db = $xml->global->resources->default_setup->connection->dbname;



Thanks for the details, seems a very good approach, I’ll dive into it and report back if my progress will seem worth being seen :)

Hi, I am new here and I am fascinated about the possibilities with Yii.

In my current project, I am working on a integration for Magento in Yii. While the posts in this thread have not helped me, I have come up with my own solution, which I wanted to share:

index.php (Bootstrap)





<?php


...


$yiiIncPath = apache_getenv("YII_INCLUDE_PATH");

if ($yiiIncPath !== false) { define('YII_INCLUDE_PATH', $yiiIncPath);}

else {define('YII_INCLUDE_PATH', realpath(dirname(__FILE__).'/../yiiframework/yii.php'));}


$mageIncPath = apache_getenv("MAGE_INCLUDE_PATH");

if ($mageIncPath !== false) { define('MAGE_INCLUDE_PATH', $mageIncPath);}

else {define('MAGE_INCLUDE_PATH', realpath(dirname(__FILE__).'/../magento/app/Mage.php'));}


...


// AutoloaderControl for Magento enabling/disabling

class AutoloaderControl {

	

	private static $mageAutoloader;

	

	public static function disableMage() {

		$autoloaders = spl_autoload_functions();

		

		foreach ($autoloaders as $autoloader) {

			if (get_class($autoloader[0]) == 'Varien_Autoload') {

				self::$mageAutoloader = $autoloader;

				spl_autoload_unregister($autoloader);		

			}

		}

	}

	

	public static function enableMage() {

		restore_error_handler();

		restore_exception_handler();

		

		spl_autoload_register(self::$mageAutoloader, false, true);

	}

}


...


// Including Magento Library first, worked for me better

include(MAGE_INCLUDE_PATH);

Mage::App('default');


// Disabling Magento Autoloader after including

AutoloaderControl::disableMage();


// Now we include Yii Base

require_once(YII_INCLUDE_PATH);


// change the following paths if necessary

$configMain = include ROOT_PATH . '/protected/config/main.php';


// Create Yii Application

$app = Yii::createWebApplication($configMain );


// Enabling Magento Autoloader

AutoloaderControl::enableMage();


// Run Yii Application

$app->run();



Warning: Magento Library is loaded with every request. When this is needed, as in my project, you can use my solution.

Using Mage-Classes is no problem any more:

(In your Controller)





...


public function actionIndex()

{

    $collection = Mage::getModel('catalog/product')->getCollection();


    foreach ($collection as $product) {

        ...

    }

}


...



Kind regards

That’s also a way of doing it. I’ve built two Magento shops in which I use Yii to a large extend, for example to:

  • parse less files

  • manage translations

  • provide forms (different contact forms, use Yii to validate and mail)

  • guestbook views (all ajax)

  • twitter feed view

  • manage cronjobs

Working great…