显示变更自修订 #1 至 #2:
添加 | 移除
英语原文:http://wiki.rubyonrails.com/rails/pages/PhpBB+Integration↘卍手机窃听器怎么买↘卍手机:15980268262
虽然 rForum 是个有前途的项目,但是至今还没有一个使用Ruby写的尽善尽美的论坛程序。所以,对于很多需要论坛模块的Rails项目来说,phpBb 多半是首选。本文讲述如何在Rails程序中整合phpBB2,以在你的网站中实现单一用户登录。实际的实现其实很简单。
首先,我假设你的phpBB2和你的Rails程序运行在同一个数据库上。并且你采用”phpbb_”数据表名前缀。
在phpBB数据表结构中有两个最需要注意的表:@phpbb_users@ 和 phpbb_sessions
首先,创建一个用户的数据模型
rails script/generate model User
然后,在 app/model/user.rb 中加入以下语句
class User < ActiveRecord::Base set_primary_key "user_id" set_table_name "phpbb_users" def is_online? tmp = User.find_by_sql( "SELECT session_user_id, session_logged_in FROM phpbb_sessions WHERE session_user_id=#{self.user_id}" )[0] if self.user_allow_viewonline == 1 && self.user_id != -1 && !tmp.nil? return true else return false end end end
这样一来,我们告诉 Active Record? 我们的数据模式是在 phpbb_users 表基础上,并且使用 user_id 作为关键字段。 我们定义了方法 is_online? 是一个用于验证用户是否已经登录的数据库查询。(只有当用户登录,并且不隐身的时候,才返回 true。 在phpBB中 id == -1 意味是一个匿名用户)。
现在, phpBB 在你登录以后,在你的电脑上保存 cookie。所以可以使用 Rails 提供的 “cookies” 哈希来读取 phpBB的cookie。
这样的话,我们就可以识别当前登录的用户了
在 @app/controllers/application.rb@,写入:
class ApplicationController < ActionController::Base def get_user_by_sid( ) sid = cookies["phpbb2mysql_sid"] return nil if sid.nil? User.find_by_sql( [ "SELECT phpbb_users.* FROM phpbb_sessions,phpbb_users WHERE session_id = ? AND phpbb_sessions.session_user_id = phpbb_users.user_id", sid ] )[0] end end
这个方法通过读取 phpbb 的 session 数据 而返回一个 User 对象。 如果这个用户退出登录 phpBB,那么他也退出 Rails 程序。
从而在所有控制器和页面视图中,当你需要检查一个用户是否登录的时候,只需要执行 get_user_by_sid(), 如果返回结果非空,那么就是这个用户的数据 User 对象。
有了这些以后,你就可以在你的程序中创建任何同 phpbb 用户之间的关联。这个用户只需要登录一次,然后你就可以访问他们所有的phpbb中的属性(email, AIM, 头像 等等),和其他所有你的 Rails User 对象指定的数据。
如果你希望用户登录 phpBb以后不是直接进入论坛,而是去你指定的页面,那么你可以以下的 php 脚本
<table border=0> <tr><td colspan=2 align=left> <B>Please Login</b> </td> </tr> <tr> <td> Username:<form action="/forums/login.php" method="post" name="login_form" target=_top> </td> <td valign=top> <input type="text" name="username"> </td> </tr> <tr> <td>Password:</td> <td> <input type="password" name="password"> </td> <tr> <td></td> <td align=center> <input type=hidden name="redirect" value=".."><input type="submit" value="Login" name="login"></form> </td> </tr> <tr> <td></td> <td align=center> <a href="http://www.yourdomain.com/forums/profile.php?mode=register" target=_top><span style="font-size: 0.8em">Register</span></a> </td> </tr> </table>
注意,以上脚本中的
<input type=hidden name="redirect" value="..">
中的值是你希望用户登录后访问的路径 (是相对你的论坛的路径)。
如果你希望让用户直接在你的程序中退出登录,那么你可以使用以下代码
<form action="/forums/login.php?logout=true" method="post" name="login_form" target=_top> <input type=hidden name="redirect" value="..">(<a href="#" onClick="javascript:document.login_form.submit()">logout</a> </form>
以下代码是我如何让用户在rails程序中向论坛发帖子。
首先,添加一些新数据模型:
# app/model/phpbb_forum.rb class PhpbbForum < ActiveRecord::Base set_primary_key :forum_id end # app/model/phpbb_post.rb class PhpbbPost< ActiveRecord::Base set_primary_key :post_id end # app/model/phpbb_posts_text.rb class PhpbbPostsText < ActiveRecord::Base set_primary_key :posts_text_id set_table_name :phpbb_posts_text end # app/model/phpbb_topic.rb class PhpbbTopic < ActiveRecord::Base set_primary_key :topic_id belongs_to :user, :foreign_key => 'topic_poster' end
然后在你的程序中加入以下代码(我放在 app/controllers/application.rb 从而所有的控制器都可以使用)
def post_topic( forum_id, user_id, subject="test subject", content="test content" ) forum = PhpbbForum.find( forum_id ) return if( forum.nil? || user_id.nil? || forum_id.nil? || subject.nil? || content.nil? ) return unless validate_admin_with_hidden_action() # Apply post # Update forums table with new posts count, new topic count, and forum_last_post_id forum.forum_posts += 1 forum.forum_topics += 1 # Update user post count user.user_posts += 1 user.save # Update posts with new topic_id, topic = PhpbbTopic.create post = PhpbbPost.create post.topic_id = topic.id post.forum_id = forum.id post.poster_id = user.id post.post_time = Time.now.to_f.to_i post.poster_id = user_id post.save # Create new topic topic.forum_id = forum.id topic.topic_title = subject topic.topic_poster = user_id topic.topic_time = Time.now.to_f.to_i topic.topic_first_post_id = post.id topic.topic_last_post_id = post.id topic.save forum.forum_last_post_id = post.id forum.save # Create new posts text post_text = PhpbbPostsText.new post_text.post_id = post.id post_text.bbcode_uid = "3edc9030fc" post_text.post_subject = subject post_text.post_text = content post_text.save return topic.id end end
以上代码没有被测试过,仅用来表达实现的想法。它们应该被更好地封装到数据模型中去,并且被完整测试。
还有一些可能有用的东西
首先,在数据模型中:
class PhpbbForum < ActiveRecord::Base set_primary_key :forum_id has_many :phpbb_topics, :foreign_key => 'forum_id' end class PhpbbPost< ActiveRecord::Base set_primary_key :post_id belongs_to :phpbb_topic, :foreign_key => 'topic_id' belongs_to :phpbb_forum, :foreign_key => 'forum_id' belongs_to :user, :foreign_key => 'poster_id' has_one :phpbb_posts_text, :foreign_key => 'post_id' def text self.phpbb_posts_text.text end end class PhpbbPostsText < ActiveRecord::Base set_primary_key :post_id set_table_name :phpbb_posts_text belongs_to :phpbb_posts, :foreign_key=>'post_id' def text self[:post_text] end end class PhpbbSession < ActiveRecord::Base set_primary_key :session_id belongs_to :user, :foreign_key => 'session_user_id' end class PhpbbTopic < ActiveRecord::Base set_primary_key :topic_id belongs_to :user, :foreign_key => 'topic_poster' has_many :phpbb_posts def last_post PhpbbPost.find( self.topic_last_post_id ) end end
然后有一个类似以下的用户数据模型
class User < ActiveRecord::Base set_primary_key "user_id" set_table_name :phpbb_users has_many :phpbb_posts, :foreign_key => 'poster_id', :order=>'post_time DESC' has_one :phpbb_session, :foreign_key=>'session_user_id' def is_online? tmp = User.find_by_sql( "SELECT session_user_id, session_logged_in FROM phpbb_sessions WHERE session_user_id=#{self.user_id}" )[0] if self.user_allow_viewonline == 1 && self.user_id != -1 && !tmp.nil? return true else return false end end def sid return self.phpbb_session.nil? ? -1 : self.phpbb_session.session_id end # Grab latest post for this user def latest_post self.phpbb_posts.first end end
现在你很方便的做:
Post.find( 1 ).text Post.find( 1 ).userPost.find( 1 ).topicPost.find( 1 ).forumUser.find( 2 ).last_post.text