Yii + WordPress = <3, или Увлекательный эксперимент получения Франкенштейна

  • Tutorial
Всем привет. Я — Денис Мельский. Работаю PHP Developer в DataArt. Область моих профессиональных интересов — Web Development и Linux. Сегодня я хотел бы поговорить с вами о «скрещивании ежа с ужом».

image

Intro


На первый взгляд может показаться, что это безумство и, в некотором роде, архитектурный костыль. Но, если посмотреть с другой стороны, это один из вариантов выхода из часто встречающейся тупиковой ситуации: заказчик хочет WordPress и ничего другого не признает. Скорее всего, что-то он такое услышал, нагуглил, увидел, посоветовал сосед гуру кодер Джон (ну, или Вася).
А программисты наотрез отказываются натягивать на движок блога, с, мягко говоря, не самой лучшей архитектурой, функционал, допустим, интернет-магазина, форума, и вдобавок — REST API для партнёров этого магазина, и сверху — еще пачку кронов с бизнес-логикой.

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

Один из вариантов, который я нашел проводя исследование, на эту тему— скрещивание WordPress и Yii.

Let the party begin


Что же, давайте попробуем осилить что-то из этого в коде.

Начнем со скачивания Yii framework. Думаю, composer для таких экспериментов — перебор — из-за кастомизации путей и архитектуры всей сборки у нас без композера будет больше возможностей для экспериментов, т. ч. спокойно качаем с родного сайта.

Ту же нехитрую манипуляцию производим с WP.

Далее вооружаемся вспомогательными мануалами:
Раз
Два

Идем по первому мануалу, к которому хочу добавить несколько замечаний и комментариев.

Устанавливаем WP размещаем всё в такую архитектуру:
image

Для начала рассмотрим ключевые строки нашего index.php.

define(‘WP_USE_THEMES’, true);
$wp_did_header = true;
require_once(‘wordpress/wp-load.php’);


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

Создаем класс Exception Handler, суть которого на 404 exception yii framework — передавать власть WP.

Делаем дефолтный .htaccess для Yii, который дает возможность делать красивые URL.

RewriteEngine on
# if a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# otherwise forward it to index.php
RewriteRule . index.php


Прописываем в конфиге Yii ‘showScriptName’ => false и раскоментируем дефолтные правила стоковой поставки.

Далее по вышеуказанному мануалу создаем WpController и View к нему.

Еще интересный момент, который нельзя обойти стороной: в wordpress конфигах на уровне DB есть настройка в табличке `wp_options`— “siteurl”, ее нужно поменять на yourdomain/wordpress. Также это можно поменять в админке WP
Settings -> General -> WordPress Address (URL).

Не могу не упомянуть интересный момент: в main layout Yii размещаем структуру внутренности нашей темы из WP.



Мы уже близки к победе: подключаем gii (кто не в курсе почитать можно тут).

В gii мы можем и создать модель CRUD, и получить на выходе собственно то, что хотели — скрещенный код Yii и WP.



It's alive!

На этом скрине мы можем наблюдать красивый CRUD из Yii с использованием CGridView.

Для авторизации везде попробуем вот такой метод.

В корне создаем папку wordpress и переносим туда внутренности самого WP.

По итогу моего ресеча на тему получаем такие выводы:

  • Frontend WP пропускать через Yii очень даже можно с подстройкой темы и в итоге у нас могут получаться кастомные модули на Yii, которые гармонично будут жить вместе с WP. К тому же, есть возможность синхронизации юзеров из WP в Yii.
  • Backend WP соединить с Yii гармонично у меня не получилось, т. е. общая админка для стандартных модулей WP и кастомных модулей Yii — не самый лучший вариант реализации. Обусловлено это тем, что в backend-e WP очень нестандартная архитектура не сильно подходящая для интеграции. Но это — результаты моего ресёрча, не претендующие на истинность в последней инстанции.
  • По итогу мы можем разработать приложение где будет гармонично сочетаться frontend WP с кастомными модулями Yii. В backend WP мы можем разрабатывать кастомные плагины и как один из вариантов реализации подгружать Yii. И даже, не побоюсь этого варианта, рендерерить некоторые модули Yii через iframe внутри WP плагина.


P.S. Хочу пожелать всем правильного выбора инструментов для решения определённого спектра задач, для которого они созданы, но и не терять азарта эксперементаторства

P.P.S. Немного линков на тему:

Примеры схожих подходов для реализации задумки в некоторых так же используются немного другие кастомизации yii.

www.yiiframework.com/wiki/382/integrating-wordpress-and-yii-working-out-the-details

www.yiiframework.com/wiki/322/integrating-wordpress-and-yii-still-another-approach-using-yii-as-the-router-controller

www.yiiframework.com/wiki/213/integrating-wordpress-and-yii-yet-another-approach

www.yiiframework.com/wiki/202/integrating-yii-with-wordpress

www.yiiframework.com/wiki/144/run-an-yii-application-inside-an-wordpress-page
DataArt
Технологический консалтинг и разработка ПО

Comments 14

    +6
    У WP вполне сносное API. Зачем собаке пятая нога?
      +1
      Тут, исходя из формулировки задачи, скорее «YII вполне неплохо работает как CMS, зачем, ну зачем заказчик хочет видеть WP...»
        0
        Затем что единственное в чем WP нету равных — это админка. За годы ее очень неплохо вылизали. То что там внутри боль и слезы, никого не волнует.
        +2
        Да там и с плагинами полный порядок, не могу представить для чего такое может пригодиться :)
        +14
        Жуть. Зря я на ночь это прочитал.

        Мое имхо, если заказчик хочет WP и его ну никак не отговорить то уж лучше:
        1) Нанять Wordpress гуру, который бы вел остальных разработчиков.
        или
        2) нанять 2-х wordpress гуру которые бы просто сделали отлично проект.

        И еще, я думаю у Вас проблема с менеджером, если он хороший менеджер, то он бы убедил что Yii лучше подходит для решения его задачи и что вы по Yii супер профессионалы, а вместо этого он Вас заставил заниматься анонизмом.

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

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

        Ну и напоследок. Когда Вы будете сдавать проект, скорее всего заказчик будет ожидать Wordpress админку, под все задачи, он очень удивится.

        Получается Вы заказчика просто обманули)
          0
          Я немного сгоряча написал коммент, а может и нет. Но надеюсь Вы серьезно так делать не будете.
          Я просто забыл что пятница и время развлекаться
            0
            Тут скорее пятнично-теоритическая задачка =) Таких заказчиков, к счастью, встретишь не часто.
              0
              я прям таки рад что не попал вам на wp.
          +1
          Вообще не понимаю суть задачи.
          Да, повторю вопрос — а нахера такое вообще делать?
          Если кастомер хочет только Вордпресс — тогда нужно реализовывать логику в рамках вордпресса.
          Многие считают что правило — «Клиент всегда прав, так как платит деньги».
          Вот от такого и появляются вот такие мысли докручивать непонятно что непонятно куда.

          Я уже в ожидании новой статьи как к этому всему можно прикрутить бандлы от Симфони.
            +4
            Заказчик хочет вордпресс, потому что потом придут программисты работающие с вордпрессом (и не знающие yii) и будут ставить плагины работающие с вордпрессом (кэширующие допустим) или пытаться работать через его апи (неплохое кстати), или не дай бог напрямую с БД или xml-rpc (что тоже иногда бывает)

            Как думаете, что заказчик скажет, когда в разработанной Вами под него части «вордпресса» и в помине не окажется?

            С тем же успехом можно было ограничить «скрещивание» размещением логотипа вордпресса:)
              +5
              image
                –1
                Недавно любопытства ради интересовался вопросом возможности интеграции Wordpress с Symfony2 (благо что на основной работе собаку уже съел на интеграции legacy-кода с Symfony2). Нагуглил такую штуку: github.com/ekino/EkinoWordpressBundle — вроде бы большинство задач решает вполне грамотно. Впрочем, сам я никогда с Wordpress серьезно не работал.
                  0
                  Простите, но это какая-то попа-боль.
                  У меня тоже был проект сделать корп сайт с конкурсом на WP.
                  Да, я люблю писать на Yii и WP вызывает аллергию по всему телу.
                  Я тоже нашел эти статьи по скрещиванию.
                  Но не смотря на всю мою ненависть к WP, проще было изучить API WP.
                  Ибо как уже выше писали, если заказчик прыгнет куда-то в сторону, голова болеть будет у вас, а не у заказчика :)
                    0
                    У меня аналогичный опыт, но полностью скрещивать Wordpress и Yii я отказался.

                    Нужный функционал сделали довольно быстро как независимый проект на фреймворке Yii в виде клиента на javascript и RESTfull API (кэширование, сфинкс, куча крон-задач, утилиты по конвертированию и сжатию изображений), а не в виде плагина к Wordpress. Запустить хотели на том же домене, где раньше был блог на Wordpress ( проект icons8 — иконки в стиле windows8, iOS7, Android ).

                    Но на Wordpress было огромное количество статей, хорошо проиндексированных в гугле и яндексе. Нужно было сохранить весь контент с его прежними URL. Переносить большой функционал CMS в небольшое приложение на Yii было неразумным решением с точки зрения трудоёмкости. Делать общую авторизацию пользователей не предполагалось.

                    В итоге сайт на wordpress оставили «в тени», а доступ к нему обеспечен средствами nginx.
                    Позаботились о сохранении всех прежних ссылок для гугля и о других специальных ссылках: файлы тем, загруженные картинки, RSS, sitemap.

                    Кусок конфига для проксирования через nginx выглядит так:
                    # конфиг верхнего уровня для перенаправления запросов на приложение Yii или блог wordpress
                    server {
                        listen   80;
                        #server_name icons8.com;
                    
                        location / {
                            proxy_intercept_errors on; # чтобы перехватить ошибки
                            error_page 404 = @wordpress_fallback; # при ошибке Page Not Found запросить wordpress
                            proxy_pass http://127.0.0.1:8889; # запросить приложение на Yii
                        }
                    
                        location @wordpress_fallback {
                            proxy_intercept_errors off; # пусть теперь wordpress отрисовывает страницы ошибок
                            proxy_pass http://wordpress_upstream; # запросить wordpress
                        }
                    
                        # несколько фиксированных URL, которые надо сразу передать в wordpress мимо Yii
                        #   страницы блога http://icons8.com/2014/01/21/???
                        location ~ /\d\d\d\d/\d\d/ {
                            proxy_pass http://wordpress_upstream;
                        }
                        # стили и оформление блога http://icons8.com/wp-content/themes/icons8/style.css
                        location ^~ /wp-(.+) {
                            proxy_pass http://wordpress_upstream;
                        }
                        # новостные ленты http://icons8.com/feed/rss/
                        location ^~ /feed/ {
                            proxy_pass http://wordpress_upstream;
                        }
                    }
                    
                    # Приложение wordpress
                    upstream wordpress_upstream {
                        server blog; # тут либо IP либо адрес сервера
                    }
                    
                    # приложение на Yii - конфиг стандартный кроме порта 8889
                    server {
                        listen 8889;
                        set $yii_bootstrap "index.php";
                        root /var/www/icons8.com/www;
                    
                        location / {
                            index index.html $yii_bootstrap;
                            try_files $uri $uri/ /$yii_bootstrap?$args;
                        }
                    
                        # pass the PHP scripts to FastCGI server listening
                        location ~ \.php {
                            # ...
                        }
                    }
                    


                    Полный вариант на gist.github.com

                    Обсуждали это решение неделю. Задача по созданию конфига заняла часа два.

                    Есть проблема в том, что если сайт заваливать запросами, гарантированно возвращающими 404, то их последовательно будут обрабатывать и Yii, и Wordpress, но это частично разруливается кэшем страниц в nginx, а в Yii оптимизирована работа с роутингом запросов, чтобы как можно меньше ресурсов потреблять на «нерасшифровываемые» URL.

                    Only users with full accounts can post comments. Log in, please.