Vanilla完美整合wordpress中文手册

btn_vanilla.gif     版权申明:本文为龙吟疯参照英语原文撰写(代码当然不是咯),任何机构或个人如需转载请先征得我的同意:ufoian@gmail.com,违反者将受到最大限度的追究。同时欢迎添加本文链接,永久链接地址:http://zhouyou.org/a/vanilla-wordpress/

        最近看到很多朋友在论坛上wordpressvanilla怎么整合的问题,虽然有一篇官方教程,但一则是英文,二则写这篇文章的时间已经是几个世纪前的事情了,现在两者的版本都有所变化,给中文用户带来不少麻烦。龙吟疯通过对照英语原文,结合新版本特点写出了这个中文教程,希望对大家有所帮助。演示:http://zhouyou.org/  and   http://zhouyou.org/bbs

首先来介绍一下Vanilla,在英语中是”香草”的意思。这个程序兴起时间较wordpress短,特别是国内认知度还不高。但是并不影响她的强大。不是龙吟疯对国内的程序有意见,几年来DZ、PW在激烈的竞争中越来越强大,但令人遗憾的是他们并没有朝着我们希望的方向发展:功能越来越多也越来越华而不实,比如什么银行、QQ头像;风格越来越华丽却越发让人感觉浮躁;安装包越来越庞大而我也越怀念DZ4.0、PW2.23了… …也许这就是商业化的必然结局吧。

反观Vanilla,真是物如其名,她的安装包仅有386Kb,和WP一样,她的许多功能,都需要通过插件来实现,甚至包括编辑器(汗一个先!)。不过不用担心,几乎你想要的功能,都可以在官方网站下载,而且安装方式亦如Wp简单,有时我甚至在想:她就是为WP而生。Vanilla最大的特点当然就是简单了:她的首页显示的是近期发表的最新帖子而不是版块列表,这就非常适用于帖数不多但是质量较高的论坛(这句不是我的原话,谁说的我忘啦),特别适合个人网站和单纯的技术网站使用。曾经有人说:她是所有论坛中最具有2.0像的论坛。还有她默认的色彩配制,让人感到朴素和恬美,就像一位未施粉黛的水摆夷少女,看惯了国内论坛的浓妆艳抹,你也许会感叹:美,原来是可以这样的。

好啦,再说就肉麻啦,还以为我是Vanilla请的网特呢,言归正传:

你可以通过一下7步来整合Vanilla和Wordpress,虽然步骤较多但是并不复杂:

一、下载Vanilla和Wordpress,我下载的时候Wordpress是点点游2.2.3汉化版(最新的2.3我还没有弄过,哪位朋友如果照这个方法成功了麻烦在下面说一下),大家可以通过这里下载。至于Vanilla,这里给大家特别推荐一个版本(虽然我没有用这个安装包,但是看了一下,一样滴!),不仅包括简体中文语言包,而且还有各种常用插件,煎蛋真是个好同志,我们一起来喊:煎蛋好,好煎蛋。

二、当然是安装Vanilla和Wordpress了,怎么安装可以参考相关文章,这已经超出了本文的范围咯,有一点要注意的是二者必须安装在同一个数据库中

三、修改Vanilla的配制文件,整合两者的用户数据。

大家打开Vanilla目录下的conf/database.php文件,这里要注意啦,在我们刚刚下载的安装包里面,是没有这个文件的,它是安装了Vanilla后自动生成的,所以我们要用FTP软件下载下来。在这个文件的最后(也就是在$DatabaseTables['User'] = ‘LUM_User’;这句话的下面)加上这样的语句[由于我的BLog没有使用PHP代码高亮插件,大家小心些看着,红色的就是代码]:

// Wordpress Integration
// =====================
 
// Map to the wordpress user table
$DatabaseTables['User'] = 'wp_users';
 
// Map existing wordpress columns to Vanilla
$DatabaseColumns['User']['UserID'] = 'ID';
$DatabaseColumns['User']['Name'] = 'user_login';
$DatabaseColumns['User']['Password'] = 'user_pass';
$DatabaseColumns['User']['Email'] = 'user_email';
$DatabaseColumns['User']['DateFirstVisit'] = 'user_registered';
 
// Also map the Wordpress columns into Vanilla
$DatabaseColumns['User']['user_nicename'] = 'user_nicename';
$DatabaseColumns['User']['user_url'] = 'user_url';
$DatabaseColumns['User']['user_activation_key'] = 'user_activation_key';
$DatabaseColumns['User']['user_status'] = 'user_status';
$DatabaseColumns['User']['display_name'] = 'display_name';

记得保存,上传。这代码的意思呢就是两者现在统一使用使用Wordpress的用户表来注册了。

四、升级数据库。大家进入数据库管理页面,运行如下两段SQL代码,将Vanilla的已有的用户添加到Wordpress:

CREATE TABLE `LUM_User` (

  `UserID` int(10) NOT NULL AUTO_INCREMENT,

  `RoleID` int(2) NOT NULL DEFAULT ‘0′,

  `StyleID` int(3) NOT NULL DEFAULT ‘1′,

  `CustomStyle` varchar(255) DEFAULT NULL,

  `FirstName` varchar(50) NOT NULL DEFAULT ”,

  `LastName` varchar(50) NOT NULL DEFAULT ”,

  `Name` varchar(20) NOT NULL DEFAULT ”,

  `Password` varchar(32) DEFAULT NULL,

  `VerificationKey` varchar(50) NOT NULL DEFAULT ”,

  `EmailVerificationKey` varchar(50) DEFAULT NULL,

  `Email` varchar(200) NOT NULL DEFAULT ”,

  `UtilizeEmail` enum(’1′,’0′) NOT NULL DEFAULT ‘0′,

  `ShowName` enum(’1′,’0′) NOT NULL DEFAULT ‘1′,

  `Icon` varchar(255) DEFAULT NULL,

  `Picture` varchar(255) DEFAULT NULL,

  `Attributes` text NULL,

  `CountVisit` int(8) NOT NULL DEFAULT ‘0′,

  `CountDiscussions` int(8) NOT NULL DEFAULT ‘0′,

  `CountComments` int(8) NOT NULL DEFAULT ‘0′,

  `DateFirstVisit` datetime NOT NULL DEFAULT ‘0000-00-00 00:00:00′,

  `DateLastActive` datetime NOT NULL DEFAULT ‘0000-00-00 00:00:00′,

  `RemoteIp` varchar(100) NOT NULL DEFAULT ”,

  `LastDiscussionPost` datetime DEFAULT NULL,

  `DiscussionSpamCheck` int(11) NOT NULL DEFAULT ‘0′,

  `LastCommentPost` datetime DEFAULT NULL,

  `CommentSpamCheck` int(11) NOT NULL DEFAULT ‘0′,

  `UserBlocksCategories` enum(’1′,’0′) NOT NULL DEFAULT ‘0′,

  `DefaultFormatType` varchar(20) DEFAULT NULL,

  `Discovery` text,

  `Preferences` text,

  `SendNewApplicantNotifications` enum(’1′,’0′) NOT NULL DEFAULT ‘0′,

  PRIMARY KEY  (`UserID`),

  KEY `user_role` (`RoleID`),

  KEY `user_style` (`StyleID`),

  KEY `user_name` (`Name`)

第二段

ALTER TABLE wp_users
  ADD `RoleID` int(2) NOT NULL DEFAULT '3',
  ADD `StyleID` int(3) NOT NULL DEFAULT '1',
  ADD `CustomStyle` varchar(255) DEFAULT NULL,
  ADD `FirstName` varchar(50) NOT NULL DEFAULT '',
  ADD `LastName` varchar(50) NOT NULL DEFAULT '',
  ADD `VerificationKey` varchar(50) NOT NULL DEFAULT '',
  ADD `EmailVerificationKey` varchar(50) DEFAULT NULL,
  ADD `Email` varchar(200) NOT NULL DEFAULT '',
  ADD `UtilizeEmail` enum('1','0') NOT NULL DEFAULT '0',
  ADD `ShowName` enum('1','0') NOT NULL DEFAULT '1',
  ADD `Icon` varchar(255) DEFAULT NULL,
  ADD `Picture` varchar(255) DEFAULT NULL,
  ADD `Attributes` text NULL,
  ADD `CountVisit` int(8) NOT NULL DEFAULT '0',
  ADD `CountDiscussions` int(8) NOT NULL DEFAULT '0',
  ADD `CountComments` int(8) NOT NULL DEFAULT '0',
  ADD `DateLastActive` datetime NOT NULL DEFAULT '2006-06-06 00:00:00',
  ADD `RemoteIp` varchar(100) NOT NULL DEFAULT '',
  ADD `LastDiscussionPost` datetime DEFAULT NULL,
  ADD `DiscussionSpamCheck` int(11) NOT NULL DEFAULT '0',
  ADD `LastCommentPost` datetime DEFAULT NULL,
  ADD `CommentSpamCheck` int(11) NOT NULL DEFAULT '0',
  ADD `UserBlocksCategories` enum('1','0') NOT NULL DEFAULT '0',
  ADD `DefaultFormatType` varchar(20) DEFAULT NULL,
  ADD `Discovery` text,
  ADD `Preferences` text,
  ADD `SendNewApplicantNotifications` enum('1','0') NOT NULL DEFAULT '0';

五、统一登录和注销。不能统一登录和退出那还叫整合吗?下面的设置可以帮助我们实现:

  • 1, 新建一个文件并命名为People.Class.WordpressAuthenticator.php。

文件内容如下:

<?php

/*

* Copyright 2003 Mark O’Sullivan

* This file is part of People: The Lussumo User Management System.

* Lussumo’s Software Library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

* Lussumo’s Software Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.

* You should have received a copy of the GNU General Public License along with Vanilla; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

* The latest source code is available at www.lussumo.com

* Contact Mark O’Sullivan at mark [at] lussumo [dot] com

*

* Description: Default interface for user authentication. This class may be

* replaced with another using the “AUTHENTICATION_MODULE” configuration setting.

* Applications utilizing this file: Vanilla;

*/

class Authenticator {

   var $Context;

        var $WordpressSettingsRetrieved;

        var $CookiePath;

        var $SiteCookiePath;

        var $CookieHash;

        var $UserCookieName;

        var $PassCookieName;

       

        function AssignSessionData($user_login, $user_pass, $PersistentSession = ‘0′) {

               $this->GetWordpressSettings();

     

               $Expire = $PersistentSession ? time() + 31536000 : 0;

               $user_pass = md5($user_pass); // Double hash the password in the cookie.

              

               // Set the cookies

               setcookie($this->UserCookieName, $user_login, $Expire, $this->CookiePath, false);

               setcookie($this->PassCookieName, $user_pass, $Expire, $this->CookiePath, false);

       

               if ($this->CookiePath != $this->SiteCookiePath ) {

                       setcookie($this->UserCookieName, $user_login, $Expire, $this->SiteCookiePath, false);

                       setcookie($this->PassCookieName, $user_pass, $Expire, $this->SiteCookiePath, false);

               }             

        }

       

        // This method is used in various places in Vanilla to sign someone into a session

        function AssignSessionUserID($UserID) {

               // Get the login_name and password for session assignment

      $s = $this->Context->ObjectFactory->NewContextObject($this->Context, ‘SqlBuilder’);

      $s->SetMainTable(’User’, ‘u’);

      $s->AddSelect(array(’Name’, ‘Password’), ‘u’);

      $s->AddWhere(’u', ‘UserID’, ”, $UserID, ‘=’);

      $Result = $this->Context->Database->Select($s,

         ‘WordpressAuthenticator’,

         ‘AssignSessionUserID’,

         ‘An error occurred while attempting to assign session data’);

             

      if ($Result) {

                       $user_login = ”;

                       $user_pass = ”;

         while ($rows = $this->Context->Database->GetRow($Result)) {

            $user_login = ForceString($rows['Name'], ”);

            $user_pass = ForceString($rows['Password'], ”);

         }

                       $this->AssignSessionData($user_login, $user_pass);

               }

        }

       

   // Returning ‘0′ indicates that the username and password combination weren’t found.

   // Returning ‘-1′ indicates that the user does not have permission to sign in.

   // Returning ‘-2′ indicates that a fatal error has occurred while querying the database.

   function Authenticate($Username, $Password, $PersistentSession) {

      // Validate the username and password that have been set

      $Username = FormatStringForDatabaseInput($Username);

      $Password = FormatStringForDatabaseInput($Password);

      $UserID = 0;

               $user_login = ”;

               $user_pass = ”;

              

      // Retrieve matching username/password values

      $s = $this->Context->ObjectFactory->NewContextObject($this->Context, ‘SqlBuilder’);

      $s->SetMainTable(’User’, ‘u’);

      $s->AddJoin(’Role’, ‘r’, ‘RoleID’, ‘u’, ‘RoleID’, ‘inner join’);

      $s->AddSelect(array(’UserID’, ‘Name’, ‘Password’), ‘u’);

      $s->AddSelect(’PERMISSION_SIGN_IN’, ‘r’);

      $s->AddWhere(’u', ‘Name’, ”, $Username, ‘=’);

      $s->AddWhere(’u', ‘Password’, ”, md5($Password), ‘=’, ‘and’, ”, 1, 1);

      $s->AddWhere(’u', ‘Password’, ”, $Password, ‘=’, ‘or’);

      $s->EndWhereGroup();

 

      $UserResult = $this->Context->Database->Select($s,

         ‘WordpressAuthenticator’,

         ‘Authenticate’,

         ‘An error occurred while attempting to validate your credentials’);

             

      if (!$UserResult) {

         $UserID = -2;

      } elseif ($this->Context->Database->RowCount($UserResult) > 0) {

         $CanSignIn = 0;

         $VerificationKey = ”;

         while ($rows = $this->Context->Database->GetRow($UserResult)) {

                               $UserID = ForceInt($rows['UserID'], 0);

            $user_login = ForceString($rows['Name'], ”);

            $user_pass = ForceString($rows['Password'], ”);

            $CanSignIn = ForceBool($rows['PERMISSION_SIGN_IN'], 0);

         }

         if (!$CanSignIn) {

            $UserID = -1;

         } else {

            // Update the user’s information

            $this->UpdateLastVisit($UserID);

 

            // Assign the session value

            $this->AssignSessionData($user_login, $user_pass, $PersistentSession);

                              

                               // Log the person’s ip

            $this->LogIp($UserID);

         }

      }

      return $UserID;

   }

  

   function Authenticator(&$Context) {

      $this->Context = &$Context;

               $this->WordpressSettingsRetrieved = ‘0′;

               $this->CookiePath = ”;

               $this->SiteCookiePath = ”;

               $this->CookieHash = ”;

   }

  

   function DeAuthenticate() {

               if (session_id()) session_destroy();

               $this->GetWordpressSettings();

               setcookie($this->UserCookieName, ‘ ‘, time() - 31536000, $this->CookiePath, false);

               setcookie($this->PassCookieName, ‘ ‘, time() - 31536000, $this->CookiePath, false);

               setcookie($this->UserCookieName, ‘ ‘, time() - 31536000, $this->SiteCookiePath, false);

               setcookie($this->PassCookieName, ‘ ‘, time() - 31536000, $this->SiteCookiePath, false);

      return true;     

   }

  

   function GetIdentity() {

               $this->GetWordpressSettings();

              

               // Examine the cookie values for session info

      $login = ForceIncomingCookieString($this->UserCookieName, ”);

               $pass = ForceIncomingCookieString($this->PassCookieName, ”);

               $dbpass = ”;

               $UserID = 0;

 

      if ($login != ” && $pass != ”) {

                       $s = “select id, user_pass from wp_users where user_login = ‘”.FormatStringForDatabaseInput($login).”‘”;

 

                       $Result = $this->Context->Database->Execute($s,

                               ‘WordpressAuthenticator’,

                               ‘GetIdentity’,

            ‘An error occurred while attempting to retrieve session data.’);

 

                       if ($Result) {

                               while ($rows = $this->Context->Database->GetRow($Result)) {

                                      $UserID = ForceInt($rows['id'], 0);

                                      $dbpass = ForceString($rows['user_pass'], ”);

                               }

                               // If the double-md5d password doesn’t match the one in the cookie - don’t authenticate

                               if (md5($dbpass) != $pass) {

                                      $UserID = 0;

                               }

         }

      }

      else {

         if (session_id()) session_destroy();

      }

 

      if (!session_id()) {

         session_set_cookie_params(0, $this->CookiePath);

         session_start();

      }

 

      return $UserID;

   }

       

        function GetWordpressSettings() {

               if ($this->WordpressSettingsRetrieved == ‘0′) {

                       $siteurl = ”;

                       $home = ”;

                       $s = “select option_name, option_value from wp_options where option_name = ’siteurl’ or option_name = ‘home’”;

                       $DataSet = $this->Context->Database->Execute($s,

                               ‘WordpressAuthenticator’,

                               ‘GetCookieName’,

                               ‘An error occurred while retrieving cookie names.’);

                       if ($DataSet) {

                               while ($rows = $this->Context->Database->GetRow($DataSet)) {

                                       if ($rows['option_name'] == ’siteurl’) {

                                              $siteurl = ForceString($rows['option_value'], ”);

                                      } else if ($rows['option_name'] == ‘home’) {

                                              $home = ForceString($rows['option_value'], ”);

                                      }

                               }

                       }             

                       $this->CookiePath = preg_replace(’|https?://[^/]+|i’, ”, $home . ‘/’ );

                       $this->SiteCookiePath = preg_replace(’|https?://[^/]+|i’, ”, $siteurl . ‘/’ );

                       $this->CookieHash = md5($siteurl);

                       $this->UserCookieName = ‘wordpressuser_’.$this->CookieHash;

                       $this->PassCookieName = ‘wordpresspass_’.$this->CookieHash;

                       $this->WordpressSettingsRetrieved = ‘1′;

               }

        }

       

   function LogIp($UserID) {

      if ($this->Context->Configuration['LOG_ALL_IPS']) {

         $s = $this->Context->ObjectFactory->NewContextObject($this->Context, ‘SqlBuilder’);

         $s->SetMainTable(’IpHistory’, ‘i’);

         $s->AddFieldNameValue(’UserID’, $UserID);

         $s->AddFieldNameValue(’RemoteIp’, GetRemoteIp(1));

         $s->AddFieldNameValue(’DateLogged’, MysqlDateTime());

 

         $this->Context->Database->Insert($s,

            ‘WordpressAuthenticator’,

            ‘LogIp’,

            ’An error occurred while logging your IP address.’,

            false); // fail silently

      }

   }

              

   function UpdateLastVisit($UserID) {

      $s = $this->Context->ObjectFactory->NewContextObject($this->Context, ‘SqlBuilder’);

      $s->SetMainTable(’User’, ‘u’);

      $s->AddFieldNameValue(’DateLastActive’, MysqlDateTime());

      $s->AddFieldNameValue(’CountVisit’, ‘CountVisit + 1′, 0);

      $s->AddWhere(’u', ‘UserID’, ”, $UserID, ‘=’);

 

      $this->Context->Database->Update($s,

         ’WordpressAuthenticator’,

         ‘UpdateLastVisit’,

         ‘An error occurred while updating your profile.’,

         false); // fail silently

   }

 

保存好,上传到你的Vanilla安装目录下的library/People/下面。

2、找到Vanilla安装目录的conf/settings.php下载下来,这个文件也和上面的/database.php一样:安装包里没有,是安装时自动生成的。打开它,在任何一个可以的地方加上下面这段话:

// Wordpress Authenticator

$Configuration['AUTHENTICATION_MODULE'] = ‘People/People.Class.WordpressAuthenticator.php’;

 

3、管理员用户的统一。进入数据库管理页面,运行SQl语句:

UPDATE wp_users SET RoleID = 4 WHERE id = 1

就此,同步登录退出及管理员都统一了。不管是Wordpress还是vaniila的老用户都可以畅游你的网站无阻了,但是还有一个小问题,那就是新用户注册的问题:Wordpress的用户表wp_users,不允许有空字段,因此如果在vaniila注册的新用户与Wordpress不兼容,那么怎么处理这个问题呢?在Vaniila官方的英文帮助文档上给出了两种方案,一是禁止在Vaniila注册:直接删除Vanilla的注册文件people.php,虽然简单,但是用起来不爽。下面就给大家介绍第二种方法:

六、新注册用户文件配置。

1、新建一个PHP文件,内容如下:

 

<?php

/*

Extension Name: Wordpress Integration

Extension Url: http://lussumo.com/docs/

Description: Makes it so that new users can be added via the Vanilla registration form and it won’t mess up the wordpress user table.

Version: 1.0

Author: Mark O’Sullivan

Author Url: http://markosullivan.ca/

*/

 

if ($Context->SelfUrl == ‘people.php’) {

   function UserManager_AddWordpressFieldsToCreateUser(&$UserManager) {

      $User = &$UserManager->DelegateParameters['User'];

      $SafeUser = clone ($User);

               $SafeUser->FormatPropertiesForDatabaseInput();

      $s = &$UserManager->DelegateParameters['SqlBuilder'];

     

      // Since Vanilla and Wordpress encode their passwords differently, I need

      // to make Vanilla’s CreateUser method save it’s password in the same way.

      // So, I’ll have to rebuild this sql object with the proper password.

      $s->Clear();

      $s->SetMainTable(’User’, ‘u’);

      $s->AddFieldNameValue(’FirstName’, $SafeUser->FirstName);

      $s->AddFieldNameValue(’LastName’, $SafeUser->LastName);

      $s->AddFieldNameValue(’Name’, $SafeUser->Name);

      $s->AddFieldNameValue(’Email’, $SafeUser->Email);

      $s->AddFieldNameValue(’Password’, md5($SafeUser->NewPassword));

      $s->AddFieldNameValue(’DateFirstVisit’, MysqlDateTime());

      $s->AddFieldNameValue(’DateLastActive’, MysqlDateTime());

      $s->AddFieldNameValue(’CountVisit’, 0);

      $s->AddFieldNameValue(’CountDiscussions’, 0);

      $s->AddFieldNameValue(’CountComments’, 0);

      $s->AddFieldNameValue(’RoleID’, $UserManager->Context->Configuration['DEFAULT_ROLE']);

      $s->AddFieldNameValue(’StyleID’, 0);

      $s->AddFieldNameValue(’UtilizeEmail’, $UserManager->Context->Configuration['DEFAULT_EMAIL_VISIBLE']);

      $s->AddFieldNameValue(’Attributes’, ”);

      $s->AddFieldNameValue(’RemoteIp’, GetRemoteIp(1));     

      $s->AddFieldNameValue(’user_nicename’, $SafeUser->Name);

      $s->AddFieldNameValue(’user_url’, ‘http://’);

      $s->AddFieldNameValue(’user_activation_key’, ”);

      $s->AddFieldNameValue(’user_status’, ‘0′);

      $s->AddFieldNameValue(’display_name’, $SafeUser->Name);

   }

   $Context->AddToDelegate(’UserManager’,

      ‘PreDataInsert’,

      ‘UserManager_AddWordpressFieldsToCreateUser’);

}

 

将其命名为default.php,并放在一个名为WordpressIntegration的文件夹里,上传到你的Vanilla安装目录下的extensions/目录里。(extensions是Vanilla的插件目录,所有的插件都要放在里面——龙吟疯注)

2、到Vanilla后台设置里开启这个插件(这个时候你就要用Wordpress的管理账号登录了哦,因为刚才已经整合了嘛)。解决了新用户注册的问题。

 

七、还想要?没有啦。你的Vanilla已经和Wordpress完美整合了。哈哈,怎么样?是不是很有成功感?别忘了到下面回复一下哦,没事的时候来我的周游记(zhouyou.org)赠个IP,谢谢啦。

本文共有 12 条评论Vanilla完美整合wordpress中文手册


  1. 1 十哈

    写的好。我以前也弄过,以后有什么问题就来你这里探讨探讨。呵呵。

  2. 2 龙吟疯

    好的,谢谢了。

  3. 3 neekey

    我也是最近在网上转的时候发现VANILLA的.下了一下,感觉确实清爽.但我下的版本有个BUG,如果密码为空(一般是本机测试),那就会出现错误.

    还没有真正玩.

  4. 4 龙吟疯

    如果密码为空(一般是本机测试),那就会出现错误.
    是吗?那我倒还没有发现的。没有试过。

  5. 5 cooolala

    学习了!讲得很详细!

  6. 6 zhang

    修改源代码太不友好了。

    可以考虑用bbpress

  7. 7 龙吟疯

    修改源代码太不友好了。

    可以考虑用bbpress。
    其实只是涉及到增加代码,没有修改。

  8. 8 nwo

    用过香草,正在用WP,但是因为买的虚拟主机是win2003+PHP的,所以觉得wp在这个环境下很多功能有问题,比如注册用户的邮件问题,但是香草对外部SMTP支持很完美!!我用的163的邮箱设置的,效果很好。
    我现在的问题是,如果WP+香草,那么邮件系统和注册用户的管理,整合以后是香草的?还是WP的?谢谢。请邮件回复我。感激!

  9. 9 完美世界私服

    wp类型的真是太多了,弄的都有不足了

  10. 10 dog

    文章中错误百出。按照这个装法很难成功

  11. 11 龙吟疯

    不对啊,我都装成功了啊。你看看zhouyou.org/bbs

  1. 1 Integrating Vanilla Forum and WordPress Themes - Ppin’s blog
    Pingback2008-5-25 12:15 am

请留下您的评论: