geektimes

Процесс подключения Yii 1.1.15 к CMS в качестве приложения на примере Shop-Script 5

  • суббота, 8 ноября 2014 г. в 02:10:54
http://habrahabr.ru/post/242577/

Давно стояла задача собрать два проекта в один. Был магазин на платформе ShopScript 5 и небольшое приложение на Yii. Требовалось сделать общую авторизацию, личный кабинет и, вообще, совместить эти два проекта в один.
Наконец, дошли руки и было решено подцепить Yii к ShopScript в качестве отдельного приложения. Приложение будет называться Tracker.

О том, что было сделано — по порядку:

1. Создание пустого приложения для ShopScript


Создание болванки приложения довольно хорошо описано в мануале на сайте ShopScript.

В принципе, ничего сверхъестественного. Приложение будет представлять из себя всего два экшена:
  • BackendAction — в котором опишем DefaultAction. Его мы пока оставим пустым;
  • FrontendAction — в котором опишем метод execute, реализующий всю логику фронтенда. Его мы пока также оставим пустым.


Для приложения так-же необходимо создать файл конфига, несколько иконок и вьюх. Это все подробно описано в мануале на сайте ShopScript, так что описывать этого здесь не имеет смысла.

2. Создадим приложение на Yii


Так-же ничего нового.
Положим приложение на Yii в папку apptrackers, которая будет находиться в корне сайта.
Либо закинем в папку уже готовое приложение, либо создадим прямо там новое. Без разницы. Суть заключается в том, чтоб в папке apptrackers оказалось наше приложение на Yii.
Как установить приложение тоже можно найти на официальном сайте.

Это была подготовка. Дальше начинается самое интересное.

3. Запускаем приложение Yii через ShopScript


Для того, чтоб полностью передать управление Yii в приложении ShopScript, настроим в административной панели на вкладке «Структура» вызов нашего приложения по адресу trackers/*, а в самом приложении оставим один FrontendAction, который будет вызываться всегда при вызове адреса типа ваш_сайт/trackers/*.
В самом FrontendAction, в методе execute, который реализует логику проекта пропишем одну строчку:

        require_once($_SERVER["DOCUMENT_ROOT"]."/apptrackers/index.php");

Это значит, что если мы в адресной строке введем адрес вида ваш_сайт/trackers/*, ShopScript отправит его на выполнение нашему приложению. А т.к. в приложении описан всего один экшен по умолчанию, то всегда будет вызываться именно он.

В итоге, мы получили вызов нашего Yii приложения. Осталось настроить наше Yii приложение.

4. Настройка Yii


Теперь, зная, что наше приложение уже запускается, осталось прописать необходимые конфиги.

  1. Настроим наш UrlManager так, чтоб он отображал адрес в виде path, и не показывал выполняемый скрипт. Нам же надо, чтоб урлы были красивые и однотипные
  2. Далее — укажем, что url у нас в приложении будет начинаться с trackers:

            'request' => array(
                'baseUrl' => '/trackers',
            ),
    

  3. Т.к. наше приложение Yii лежит в папке, о которой никто не должен знать, вынесем стили и assets в отдельную папку в корне сайта. Назовем ее tracks. Внутри создадим сразу папку assets. Туда будем складывать все наши файлы стилей, js-скриптов и прочую нечисть.
  4. Теперь настроим AssetsManager, указав ему, где будут лежать наши файлы:

            'assetManager' => array(
                'basePath' => dirname(__FILE__).DIRECTORY_SEPARATOR.'..'.DIRECTORY_SEPARATOR.'..'.DIRECTORY_SEPARATOR.'..'.DIRECTORY_SEPARATOR.'tracks'.DIRECTORY_SEPARATOR.'assets',
                'baseUrl' => '../../tracks/assets',
            ),
    

  5. Также немного подправим основной layout, указав в подключаемых скриптах пока просто нашу папку:

    	<link rel="stylesheet" type="text/css" href="/tracks/css/screen.css" media="screen, projection" />
    	<link rel="stylesheet" type="text/css" href="/tracks/css/print.css" media="print" />
    	<!--[if lt IE 8]>
    	<link rel="stylesheet" type="text/css" href="tracks/css/ie.css" media="screen, projection" />
    	<![endif]-->
    
    	<link rel="stylesheet" type="text/css" href="/tracks/css/main.css" />
    	<link rel="stylesheet" type="text/css" href="/tracks/css/form.css" />
    



Теперь, при вызове нашего приложения по адресу ваш_сайт/trackers — мы увидим наше приложение Yii.
Отлично! У нас получилось! Но зайдя в gii нашелся один нюанс.
Gii публикует все свои ресурсы в assets по умолчанию в папке приложения. Нам-же необходимо переопределить этот путь.
Для этого укажем в конфиге gii путь к ресурсам:

		'gii'=>array(
			'class'=>'system.gii.GiiModule',
			'password'=>'******',
                        'assetsUrl'=>'/tracks/assets/gii',
			// If removed, Gii defaults to localhost only. Edit carefully to taste.
			'ipFilters'=>array('xxx.xxx.xxx.xxx','::1'),
		),


Скопируем все файлы для gii из каталога модуля /apptrackers/framework/gii/assets/* в папку для наших файлов /tracks/assets/gii/* и получим уже полнофункциональный проект.

Можно конечно было все сделать проще. Просто поместить приложение yii в отдельный каталог, по которому будет вызываться yii. Без всяких дополнительных настроек. Но неоспоримый плюс вышеописанного решения в том, что в приложении Yii мы имеем весь функционал ShopScript с уже готовой авторизацией, управлением пользователями, корзиной и прочее-прочее-прочее…

Продемонстрирую это на примере модуля пользователей.

5. Добавление модуля пользователей в Yii


По сути, у нас в ShopScript уже есть пользователи, есть их корзина и часть функционала, который хочется оставить.
Поступим следующим образом:

Создадим в Yii папку modules и в ней каталог для нашего модуля user.
Добавим файл модуля UserModule.php, в котором оставим стандартный функционал для инициализации и добавим статический метод isAdmin:

	public static function isAdmin() {
		wa()->getUser()->isAdmin();
	}


Из кода видно, что мы обращаемся к уже существующему приложению ShopScript, получаем из него пользователя и статус администратора.

Так-же добавим в папку components класс, который будет отвечать за работу пользователей SSUser.php, в котором опишем несколько стандартных методов:

class SSUser extends CWebUser
{    
    public function getId()
    {
        return wa()->getUser()->getId();
    }

    public function isAdmin() {
        return wa()->getUser()->isAdmin();
    }
    
    public function getIsGuest() {

        if(wa()->getUser()->getId())
        {
            return false;
        }
        return true;
    }
    
    public function getName() {

        return wa()->getUser()->get('name');
    }
}


Из кода видно, что все данные для пользователя мы берем из уже запущенного приложения ShopScript.

Подправим в конфиге класс, который отвечает за пользователей:

		'user'=>array(
			'class' => 'SSUser',
		),


Теперь, стандартный код в layouts/main.php, где стоит проверка на пользователя:

$this->widget('zii.widgets.CMenu',array(
			'items'=>array(
				array('label'=>'Home', 'url'=>array('/site/index')),
				array('label'=>'About', 'url'=>array('/site/page', 'view'=>'about')),
				array('label'=>'Contact', 'url'=>array('/site/contact')),
				array('label'=>'Login', 'url'=>array('/site/login'), 'visible'=>Yii::app()->user->isGuest),
				array('label'=>'Logout ('.Yii::app()->user->name.')', 'url'=>array('/site/logout'), 'visible'=>!Yii::app()->user->isGuest)
			),

в последних двух пунктах будет отображать ссылку в зависимости от того, авторизован пользователь в приложении ShopScript или нет, и если авторизован — будет выводить имя пользователя из того-же приложения.

В дальнейшем модуль можно расширять до необходимого функционала.

Такой способ симбиоза двух приложений, конечно, не претендует на идеальный, но для решения многих задач, я думаю должен подойти.