一直使用 yii 来做网站,也和朋友合作做了几个成品。只是框架虽好,要自己做一个像 wordpress 那样完善且功能丰富的博客系统却是有些费力。本站上一个版本就是基于yii做的,虽然也是像模像样,自己却是知道里面有诸多不顺畅的地方,索性还是用了 wordpress,当然也是不愿抛了yii提供的各种便利,那么就让她们华丽合体吧~~~
google搜一下,会有几篇关于她俩整合的文章,都是在yii的官方wiki上的,一般有两种方法
1 在wordpress 里面运行 yii
2 在 yii 里面运行 wordpress (本站使用的方法)
Run an Yii Application inside an WordPress page
这篇大概是最早做这项尝试的,后面的几篇都有提到,属于第一种方法。
Integrating Yii with WordPress
这也是第一种方法。
Integrating WordPress and Yii: yet another approach
这篇就开始用第二种方法了,看到似乎要改挺多代码的,也没有细看。
Integrating WordPress and Yii: still another approach, using Yii as the router/controller
这篇引用了上一篇文章,也是本站所使用的方法,稍微有些细节的修改,从逻辑上看相对简洁,两边都不需要做什么核心的修改,正文中介绍的便是这种方法了,权当是翻译,也分享下使用原文方法遇到的问题和解决。
Integrating WordPress and Yii,Working Out The Details.
和上一种方法一样,有点小修改,提到了为 yii 页面使用 wordpress 主题 的问题
好了,言归正传,来看看 yii 和 wordpress 的合体大法吧。
Step 1 建立 yii application
这个根据 yii 的教程走就好了,总之这一步创建一个基于 yii 的基本站点并配置好数据库。假设目录为 /xxx/website
Step 2 安装 wordpress
将 wordpress 的整个目录放在 /xxx/website,本文假设目录名为 wordpress。 在wp-config.php中配置使用的数据库,可以和 yii 使用同一个数据库,这样我们就可以在 wordpress 中使用 yii 的 model 的功能了。
另外,还需要修改数据库的 wp_options 表数据.
找到 option_name 为 siteurl 的行,修改 option_value 为 http://你的域名/wordpress
找到 option_name 为 home 的行,修改 option_value 为 http://你的域名
Step 3 定位 yii 的 404 页面到 wordpress 的 404 页面
这里要写一个类 ExceptionHandler 的类给 yii, 创建文件 /xxx/website/protected/components/ExceptionHandler.php , 代码如下
<?php class ExceptionHandler { public function __construct() { define('YII_ENABLE_EXCEPTION_HANDLER',false); set_exception_handler(array($this,'handleException')); } public function handleException($exception) { // disable error capturing to avoid recursive errors restore_error_handler(); restore_exception_handler(); $event=new CExceptionEvent($this,$exception); if($exception instanceof CHttpException && $exception->statusCode == 404) { try { Yii::app()->runController("blog/index"); } catch(Exception $e) {} // if we throw an exception in WordPress on a 404, we can use // our main error handler to handle the error } if(!$event->handled) { Yii::app()->handleException($exception); } } } ?>
Step 4 修改 yii 的入口文件 /xxx/website/index.php
这一步使得 yii 程序启动时加载 wordpress 的程序
define('WP_USE_THEMES', true); $wp_did_header = true; require_once('wordpress/wp-load.php'); require_once(dirname(__FILE__) . '/protected/components/ExceptionHandler.php'); $router = new ExceptionHandler(); .... require_once($yii); Yii::createWebApplication($config)->run();
Step 5 在 yii 中运行 wordpress
经过以上4步,基本的准备工作就做好了,下面让 wordpress 在我们的 yii 框架里运行起来把。
原文在这一步是另外创建了一个 wordpress 的 controller,但是我希望首页就是 wordpress 的博客首页,所以就直接用现成的 SiteController 了。
打开 /xxx/website/protected/controllers/SiteController.php
修改里面的 actionIndex函数为
$this->layout = false; // note that we disable the layout try { //spl_autoload_unregister(array('YiiBase', 'autoload')); wp(); require_once( ABSPATH . WPINC . '/template-loader.php' ); //spl_autoload_register(array('YiiBase', 'autoload')); Yii::app()->end(); } // if we threw an exception in a WordPress functions.php // when we find a 404 header, we could use our main Yii // error handler to handle the error, log as desired // and then throw the exception on up the chain and // let Yii handle things from here // without the above, WordPress becomes our 404 error // handler for the entire Yii app catch (Exception $e) { throw $e; }
其实光运行上述代码是会遇到 yii autoload 的问题的,这也是原文没有提到的,让我好一顿折腾。
这里有两个办法,一个治标,一个治本。
治标的方法,就是解开上述代码中被我注释掉的 spl_autoload_unregister 相关的两句,这样,在运行 wp() 时就不会调用 yii 的 autoload 函数产生错误。但是这样在 wordpress 里面就有很多 yii 的功能不能使用了。 所以我后来使用了另一个治本的方法,将这两句注掉了。
治本的方法,需要修改wordpress的一小点代码。
在 wp-includes/post.php 中,找到下面代码
if ( is_a( $post, 'WP_Post' ) ) { $_post = $post; } elseif ( is_object( $post ) ) { if ( empty( $post->filter ) ) { $_post = sanitize_post( $post, 'raw' ); $_post = new WP_Post( $_post ); } elseif ( 'raw' == $post->filter ) { $_post = new WP_Post( $post ); } else { $_post = WP_Post::get_instance( $post->ID ); } } else { $_post = WP_Post::get_instance( $post ); }
错误的地方在于 is_a 会调用YIIBase::autoload, 由于$post可能是数字,从而include的时候,导致exception,
修改的方法就是先检查is_object,修改如下
if ( is_object( $post ) ){ if ( is_a( $post, 'WP_Post' ) ) { $_post = $post; } else { if ( empty( $post->filter ) ) { $_post = sanitize_post( $post, 'raw' ); $_post = new WP_Post( $_post ); } elseif ( 'raw' == $post->filter ) { $_post = new WP_Post( $post ); } else { $_post = WP_Post::get_instance( $post->ID ); } } }
好了,在浏览器中输入你的域名,一个整合在 yii 里的 wordpress 就呈现啦。
Step 6 让 yii 的页面使用 wordpress 的主题
如果希望你的网站统一用 wordpress 的主题,同时又想用 yii 来写页面(废话,不然整这么多干嘛),那么再做下面一个小修改就好了。
打开 /xxx/website/protected/views/layouts/main.php 将里面的内容替换为
<?php get_header(); ?> <div id="primary" class="site-content"> <div id="content" role="main"> <?php // echos Yii content echo $content; ?> </div> </div> <?php get_sidebar(); ?> <?php get_footer(); ?>
OK,大功告成。当然如果你对 yii 熟悉,这些 controller、layout 什么都可以随便搞。总之你现在已经是左手倚天右手屠龙啦,爱怎么折腾怎么折腾吧。
整合后具体能实现什么功能和效果,能简单说明一下吗
@buffer: 你好,你可以说下错误是什么。我自己这个网站就是这么做的,我遇到的出错的地方,在 Step 5 里面有说解决的办法
很不靠谱,严重错误,但是依然感谢你的翻译精神