Integrate Opencart and Yii – part II

In previous post we have discussed the modification required in yii to work with opencart.

In this post, we will discuss how we can modify the opencart to make it work with yii.

This section is faily easy and the most complex one

The easy side is, install opencart

install vqmod.

downlaod the following files (vqmod scripts) and copy to vqmod/xml

opencart-yii-integration-by-webcare.pk-v1.0

open webroot/index.php and add following lines to it.

 

global $server;
// yii code
// check the server, i.e. either development | production
$server = ($_SERVER['HTTP_HOST'] == 'localhost' || $_SERVER['HTTP_HOST'] == 'localhost:8080' || preg_match('/^192.168.15.d{1,3}$/', $_SERVER['HTTP_HOST']) ? 'development' : (($_SERVER['HTTP_HOST'] == 'yourdomain.com') || ($_SERVER['HTTP_HOST'] == 'www.yourdomain.com') ? 'production' : 'unknown'));
// change the following paths if necessary
$yii = dirname(__FILE__) . '/../yii/framework/yii.php';
$yii_open_config = dirname(__FILE__) . '/protected/config/opencart.php'; //remembder this file from our previous post

if ($server == 'development') {
    // remove the following lines when in production mode
    defined('YII_DEBUG') or define('YII_DEBUG', true);
    // specify how many levels of call stack should be shown in each log message
    defined('YII_TRACE_LEVEL') or define('YII_TRACE_LEVEL', 3);
}
require_once($yii);
Yii::createWebApplication($yii_open_config);

Note that we have

  • included the config/opencart.php
  • have special line to check whether it’s development or production and enable/disable debug accordingly.
  • The reason to mark
    $server

    as global is that, it goes all the way to db selection in config/db.php and assets url selection so we have to decide it one and use it everywhere.

  • removed the ->run() part from the last line,

We are going to do something similar with the admin/index.php

global $server;
// yii code
$server = ($_SERVER['HTTP_HOST'] == 'localhost' || $_SERVER['HTTP_HOST'] == 'localhost:8080' || preg_match('/^192.168.15.d{1,3}$/', $_SERVER['HTTP_HOST']) ? 'development' : (($_SERVER['HTTP_HOST'] == 'yourdomain.com') || ($_SERVER['HTTP_HOST'] == 'www.yourdomain.com') ? 'production' : 'unknown'));

// change the following paths if necessary
$yii = dirname(__FILE__) . '/../../yii/framework/yii.php';
//$yii_config = dirname(__FILE__) . '/../protected/config/main.php';
$yii_open_config = dirname(__FILE__) . '/../protected/config/opencart.php';

// remove the following lines when in production mode
if ($server == 'development') {
    defined('YII_DEBUG') or define('YII_DEBUG', true);
    // specify how many levels of call stack should be shown in each log message
    defined('YII_TRACE_LEVEL') or define('YII_TRACE_LEVEL', 3);
}

require_once($yii);
Yii::createWebApplication($yii_open_config);

It’s very much alike, but the path reference is different.

That’s it.

The fairly complex part starts when I have to explain each step.

starts with wMod_header.xml

First of all we have added a few lines in

admin/controller/common/header.php

before the call for template.
the lines are

        // http://www.tipstank.com/2011/03/20/yii-how-to-register-jquery-ui-javascript-and-css/
        $output = '';
        // if you need jquery-ui
        $scripts = Yii::app()->clientScript->registerCoreScript('jquery.ui');
        $scripts->registerCssFile(Yii::app()->clientScript->getCoreScriptUrl().'/jui/css/base/jquery-ui.css');
        $scripts->renderCoreScripts($output);
        $scripts->renderHead($output);
        $this->data['yii_scripts'] = $output;
        // end addition by rehan@webcare.pk

Remember that we have stopped yii from including the jquery.js so jquery will be loaded by opencart itself.

However for any further scripts used in yii by us, we have to use the above lines and store them in a variable

$this->data['yii_scripts'];

Now to display this variable, along with other requirement

open admin/view/template/common/header.tpl

and just before the jquery inclusion, add

<?php // added by rehan@webcare.pk ?>
<!--[if lt IE 8]>
<link rel="stylesheet" type="text/css" href="../css/ie.css" media="screen, projection" />
<![endif]-->
<?php echo $yii_scripts; ?>
<?php // end addition by rehan@webcare.pk ?>

Like the way I have included the ie.css, we can add any css or javascript you need.

Same Way open admin/controller/common/footer.php and add before the template call

        //addition by rehan@webcare.pk
        $output = '';
        Yii::app()->clientScript->renderBodyEnd($output);
        $this->data['yii_scripts'] = $output;
        // end addition by rehan@webcare.pk

And again in admin/view/template/common/footer.tpl just in the header section

<?php // added by rehan@webcare.pk ?>
<?php echo $yii_scripts; ?>
<?php // end addition by rehan@webcare.pk ?>

Till this point, we are able to use Yii::app() thing anywhere within the opencart’s controllers models and views.

Now for the redirection part.

open up catalog/controller/error/not_found.php

Replace the whole file with the following content.

<?php                            
class ControllerErrorNotFound extends Controller {

    public function index() {

        try {
            // YII code begins
            // this call is directed from opencart / admin
            $adminString = 'admin/';
            $adminPosition = strpos($_GET['_route_'], $adminString);
            $route = (($adminPosition !== false) ? substr($_GET['_route_'], strlen($adminString)) : $_GET['_route_']) ;

            $indexString = 'index.php';
            $indexPosition = strpos($route, $indexString);
            $route = (($adminPosition !== false) ? substr($route, strlen($indexPosition)) : $route) ;

            Yii::app()->runController($route);
            // YII code ends
        } catch (Exception $e) {
            if(Yii::app()->request->isAjaxRequest){
                echo $e->getMessage() . '<br />'
                    . $e->getTraceAsString() . '<br />';
                 Yii::app()->end();
            }else{
                $this->language->load('error/not_found');

                $this->document->setTitle($this->language->get('heading_title'));

                $this->data['breadcrumbs'] = array();

                $this->data['breadcrumbs'][] = array(
                    'text' => $this->language->get('text_home'),
                    'href' => $this->url->link('common/home'),
                    'separator' => false
                );

                if (isset($this->request->get['route'])) {
                    $this->data['breadcrumbs'][] = array(
                        'text' => $this->language->get('text_error'),
                        'href' => $this->url->link($this->request->get['route']),
                        'separator' => $this->language->get('text_separator')
                    );
                }

                $this->data['heading_title'] = $this->language->get('heading_title');

                $this->data['text_error'] = $this->language->get('text_error') . '<br />'
                                 . $e->getMessage() . '<br />'
                                 . $e->getTraceAsString() . '<br />';;

                $this->data['button_continue'] = $this->language->get('button_continue');

                $this->response->addHeader($this->request->server['SERVER_PROTOCOL'] . '/1.1 404 Not Found');

                $this->data['continue'] = $this->url->link('common/home');

                if (file_exists(DIR_TEMPLATE . $this->config->get('config_template') . '/template/error/not_found.tpl')) {
                    $this->template = $this->config->get('config_template') . '/template/error/not_found.tpl';
                } else {
                    $this->template = 'default/template/error/not_found.tpl';
                }

                $this->children = array(
                    'common/column_left',
                    'common/column_right',
                    'common/content_top',
                    'common/content_bottom',
                    'common/footer',
                    'common/header'
                );

                $this->response->setOutput($this->render());
            }
        }
    }

}
?>

This will let yii handle the request when opencart cannot find it, and if even yii cannot find it, it will display the error generated by yii.

Same file has to be copied to admin/controller/error/not_found.php

And not to be outdone here, we have another  xml file here which will enable us to cross login from opencart to yii with a single click.

open system/library/user.php and just after

$permissions = unserialize($user_group_query->row['permission']);

add

//addition by rehan@webcare.pk
try {
$yii_user = new LoginForm;
$yii_user->username = $username;
$yii_user->password = $password;
$yii_user->validate();
$yii_user->login();
} catch (Exception $e) {
echo $e->getMessage();
}
// end addition by rehan@webcare.pk

Also Before the following line

unset($this->session->data['user_id']);

add

// addition by rehan@webcare.pk
Yii::app()->user->logout();
// end addition by rehan@webcare.pk

And Hope fully we are done.

Enjoy using the yii’s models within opencart, I love to use the following lines within opencart’s product models

    $product = new Product::model();

    if(isset($_POST['Product'])){

        $product->attribute = $_POST['Product'];

        $product->save();

    }

Love it? I cannot live without it.

Open for comments/suggestions/improments

 

7 thoughts on “Integrate Opencart and Yii – part II

  • Hi, I have succesfully integrate the apps with a slightly modification. I am no expert in Open Cart, so I dunno if the modification I made is the best solution or not. The error is caused by the warning, when I call Yii::app()->user->login(), Yii CHttpSession started the session again when the session is already started by Open Cart, so it displays warning. Then I also modify function logout of vq2-system_library_user.php to be as below :

    if(isset(Yii::app()->user->id)) {
    Yii::app()->user->logout();
    } else {
    session_destroy();
    }

    Because every time I call Yii::app()->user->logout(), it will destroy the session. If I call session_destroy() again then it will display warning.

    Thanks a lot for your tutorial, appreciate it so much! =)

    • Hello, I found a way to resolve this problem,
      for this, we have to create a WHttpSession.php under components and inherit the CHttpSession.
      Override the open() function. Copy and paste from CHttpSession and just before @session_start() add the session check like follows
      if(!isset($_SESSION)){
      @session_start()
      }

      Now change your session Class name under config->main.php like

      'components' => array(
      ......
      //session management
      'session' => array(
      'class' => 'WHttpSession',
      ),
      ........
      ),

      For logout, we have to modify the opencart logout script (because we are logging out yii first).
      add this vqmod xml for library/user.php

      operation
      search position="replace"
      session_destroy();
      /search
      add
      if(session_id() != ''){
      session_destroy();
      }
      /add
      /operation

      just add the opening < and closing > symbols.

      I hope this will resolve the matter swiftly.

      Thanks for pointing out the bug and appreciating by using the script

  • I think it is somewhat related with the session. When I access localhost/shop/admin using other browser ( which I never use to login to my app ) it does not display :

    “Notice: Undefined variable: username in D:xampphtdocsopencartvqmodvqcachevq2-system_library_user.php on line 28Notice: Undefined variable: password in D:xampphtdocsopencartvqmodvqcachevq2-system_library_user.php on line 29″

    Then I log in and it success. But after I login, it displays notice :

    ““Notice: Undefined variable: username in D:xampphtdocsopencartvqmodvqcachevq2-system_library_user.php on line 28Notice: Undefined variable: password in D:xampphtdocsopencartvqmodvqcachevq2-system_library_user.php on line 29″

    And when I logout it displays error :

    ““Warning: Cannot modify header information – headers already sent by (output started at D:xampphtdocsopencartadminindex.php:106) in D:xampphtdocsopencartvqmodvqcachevq2-system_engine_controller.php on line 28Warning: Cannot modify header information – headers already sent by (output started at D:xampphtdocsopencartadminindex.php:106) in D:xampphtdocsopencartvqmodvqcachevq2-system_engine_controller.php on line 29″

    • Hello,
      Actually you are enabled the E_All & E_NOTICE in php.ini, which is showing the warnings also.
      In production server, only E_ERROR is enabled to so these warnings will not be shown, to make sure, try changing the settings.
      If is does not resolve the problem, let me know

  • Hi, thank you for the tutorial. I am using Open Cart version v1.5.5.1

    I have followed all the tutorial and when I access localhost/shop/admin then it displays notice :

    “Notice: Undefined variable: username in D:xampphtdocsopencartvqmodvqcachevq2-system_library_user.php on line 28Notice: Undefined variable: password in D:xampphtdocsopencartvqmodvqcachevq2-system_library_user.php on line 29”

    And when I enter the username and password it displays error :

    “Warning: Cannot modify header information – headers already sent by (output started at D:xampphtdocsopencartadminindex.php:106) in D:xampphtdocsopencartvqmodvqcachevq2-system_engine_controller.php on line 28Warning: Cannot modify header information – headers already sent by (output started at D:xampphtdocsopencartadminindex.php:106) in D:xampphtdocsopencartvqmodvqcachevq2-system_engine_controller.php on line 29”

    Please help.. Thanks

Comments are closed.