Pull to refresh

Интеграция WordPress и Zend FrameWork

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

Если вам интересно как выкручиваться в подобной ситуации, приглашаю под кат


Концепт такой. Весь нестандартный функционал выполняет ZF, а WP только выводит результат, так же, как например содержимое отдельной страницы или поста. Т.о. дизайнер может как угодно изменять рамку (хедер, футер, и т.п) для любых страниц, новая рамка применится и к страницам от ZF. Саппорт будет как ни в чём ни бывало, редактировать статические странички и новости, вставляя где надо ссылки на функционал ZF,

Первым делом требуется заставить WP спрашивать содержимое у ZF для запросов определённого вида, например /do/account/signup/
Конечно, используем систему плагинов. Только вот нету хука, который даст возможность не тянуть пост из wordPressa, а вызвать содержимое через какую либо функцию. Если кто то найдёт, то расскажите мне, будьте добры :) Поэтому будем вероломно использовать хук, который есть и вызывается до подготовки контента.

На наше счастье, http запросы парсятся классом WP_Query и этим же классом готовится содержимое страницы. WP использует один глобальный объект этого класса. Без всяких угрызений совести, заменяем этот объект на наш подставной экземпляр наследника класса WP_Query. Чувствуете к чему я веду? Правильно, функция get_posts() будет переопределена.
Лично я сперва вызываю стандартный метод, он заполнит все глобальные объекты стандартными данными, вытянет из базы дефолтную страницу для отображения, вобщем он молодец, мне без него было бы трудно.
Затем я заменяю контент дефолтной страницы, результатом пришедшим от ZF.

define('ZF_MARKER', 'do');

add_action('parse_request', 'zf_query_controller');

function zf_query_controller() {
parse_str($_SERVER['QUERY_STRING'], $params);

if(isset($params[ZF_MARKER])) {

global $wp_the_query;
$q = new ZF_Query();
$q->copyFrom($wp_the_query);
$zf_uri = trim($params[ ZF_MARKER ], "/ ");
$q->req_uri_zf = empty($zf_uri)? '/' : '/' . $zf_uri . '/';
$wp_the_query = $q;
}
}

class ZF_Query extends WP_Query
{
public $req_uri_original = '';
public $req_uri_zf = '';

function copyFrom(WP_Query $wp_query) {
$vars = get_object_vars($wp_query);
foreach($vars as $name => $value) {
$this->$name = $value;
}
}

function &get_posts() {
parent::get_posts();

$post_zf = array(
"ID" => 1,
"post_author" => 1,
"post_date" => '',
"post_date_gmt" => '',
"post_content" => '',
"post_title" => '',
"post_excerpt" => "",
"post_status" => "publish",
"comment_status"=> "open",
"ping_status" => "open",
"post_password" => "",
"post_name" => "",
"to_ping" => "",
"pinged" => "",
"post_modified" => "",
"post_modified_gmt"=> "",
"post_content_filtered"=> "",
"post_parent" => 0,
"guid" => "",
"menu_order" => 1,
"post_type" => ZF_MARKER,
"post_mime_type"=> "",
"comment_count" => "0",
"ancestors" => array(),
"filter" => "",
);

$tmp = $_SERVER['REQUEST_URI'];
$_SERVER['REQUEST_URI'] = $this->req_uri_zf;
$post_zf['post_content'] = require_once ABSPATH . 'zf-app/public/index.php';
$_SERVER['REQUEST_URI'] = $tmp;

global $post;
$post = (object)$post_zf;
$this->posts = array($post);
$this->post = $post;
$this->post_count = count($this->posts);
$this->current_post = 0;

$this->is_single = 1;
$this->is_page = 0;
$this->is_404 = 0;
$this->is_archive = 0;
$this->is_home = 0;

// эти 2 строки нужны, чтобы wordPress (особеннно в версии 3.x) не думал, что у него запросили нечто некорректное.
global $wp_filter;
unset($wp_filter['template_redirect']);

return $this->posts;
}
}


И конечно правило для .haccess:
RewriteRule /?do/(.*) /index.php?do=$1 [L]

Можно и без него, тогда урлы для функционала ZF будут вида /?do=account/signup/


Также, необходимо изменить ZF, он должен не выводить свой респонс, а возвращать его.

$controller->returnResponse(true);
$resp = $application->bootstrap()->getBootstrap()->run();
return $resp->getBody();


Возвращаемый HTML нужен без тегов <html> и <body> Так что отключите лэйаут или сделайте его примитивным, типа
<?php echo $this->layout()->content ?>


Вот вобщем-то и всё.




PS: Ещё один момент. если Вам нужно научить WP как-то особенно обращаться с содержимым от ZF, то можно зайти в шаблон Single.php используемой темы и прописать в нужном месте
<?php the_post(); if (ZF_MARKER == $post->post_type) : ?>
<?php echo $post->post_content;?>
<?php else:?>
...
<?php endif; ?>


Для этого и были нужны строчки:
$this->is_single = 1;
$this->is_page = 0;
$this->is_404 = 0;
$this->is_archive = 0;
$this->is_home = 0;
Tags:wordpresszend frameworkинтеграция
Hubs: Website development
Total votes 13: ↑9 and ↓4 +5
Views1.8K

Popular right now

Top of the last 24 hours