捣蛋phpwind控制器注入
在PwBaseController 里面,会有这个方法的存在
/**
* action Hook 注册
*
* @param string $registerKey 扩展点别名
* @param PwBaseHookService $bp
* @throws PwException
* @return void
*/
protected function runHook($registerKey, $bp) {
if (!$registerKey) return;
if (!$bp instanceof PwBaseHookService) {
throw new PwException('class.type.fail',
array(
'{parm1}' => 'src.library.base.PwBaseController.runHook',
'{parm2}' => 'PwBaseHookService',
'{parm3}' => get_class($bp)));
}
if (!$filters = PwHook::getRegistry($registerKey)) return;
if (!$filters = PwHook::resolveActionHook($filters, $bp)) return;
$args = func_get_args();
$_filters = array();
foreach ($filters as $key => $value) {
$args[0] = isset($value['method']) ? $value['method'] : '';
$_filters[] = array('class' => $value['class'], 'args' => $args);
}
$this->resolveActionFilter($_filters);
}
我们先不理这个东西是什么,看它到底是怎样调用的
/**
* 发帖
*/
public function doaddAction() { list($title, $content, $topictype, $subtopictype, $reply_notice, $hide) = $this->getInput(array('atc_title', 'atc_content', 'topictype', 'sub_topictype', 'reply_notice', 'hide'), 'post');
$pwPost = $this->post;
$this->runHook('c_post_doadd', $pwPost); $postDm = $pwPost->getDm();
$postDm->setTitle($title)
->setContent($content)
->setHide($hide)
->setReplyNotice($reply_notice); //set topic type
$topictype_id = $subtopictype ? $subtopictype : $topictype;
$topictype_id && $postDm->setTopictype($topictype_id); if (($result = $pwPost->execute($postDm)) !== true) {
$data = $result->getData();
$data && $this->addMessage($data, 'data');
$this->showError($result->getError());
}
$tid = $pwPost->getNewId(); $this->showMessage('success', 'bbs/read/run/?tid=' . $tid . '&fid=' . $pwPost->forum->fid, true);
}
$this->runHook('c_post_doadd', $pwPost);
之前发帖的时候发现页面有添加话题的内容,但是在控制器入面却没有发现有这种逻辑的操作,后来才知道是通过注入去操作的,我们看看数据库入面的纪录

再看看它们是怎样定义的
/**
* 帖子发布 - 话题相关
*
* @author jinlong.panjl <jinlong.panjl@aliyun-inc.com>
* @copyright ©2003-2103 phpwind.com
* @license http://www.phpwind.com
* @version $Id$
* @package wind
*/
class PwPostDoTagInjector extends PwBaseHookInjector { public function doadd() {
$tagNames = (array)$this->getInput('tagnames', 'post');
if (!is_array($tagNames) || !count($tagNames)) return;
Wind::import('SRV:forum.srv.post.do.PwPostDoTag');
return new PwPostDoTag($this->bp,$tagNames);
} public function domodify() {
$tagNames = (array)$this->getInput('tagnames', 'post');
Wind::import('SRV:forum.srv.post.do.PwPostDoTag');
return new PwPostDoTag($this->bp,$tagNames);
}
}
doadd 这个方法就算添加标签的
它的父类是什么玩意
<?php
defined('WEKIT_VERSION') || exit('Forbidden'); Wind::import('WIND:filter.WindActionFilter'); /**
* PwHook action拦截过滤器抽象接口定义
*
* 通过继承该接口,可以实现在Controller层注入扩展实现.该接口默认调用'run'方法.
* 支持多参数扩展.
* @author Qiong Wu <papa0924@gmail.com> 2011-12-2
* @copyright ©2003-2103 phpwind.com
* @license http://www.windframework.com
* @version $Id: PwBaseHookInjector.php 8692 2012-04-24 05:56:29Z jieyin $
* @package src
* @subpackage library.filter
*/
abstract class PwBaseHookInjector extends WindActionFilter { private $callback = 'run';
private $args = array();
/**
* @var PwBaseHookService
*/
protected $bp = null; /**
* @param WindForward $forward
* @param WindErrorMessage $errorMessage
* @param WindRouter $router
* @param array $args
*/
public function __construct($forward, $errorMessage, $router, $args = array()) {
parent::__construct($forward, $errorMessage, $router);
!empty($args[0]) && $this->callback = $args[0];
isset($args[1]) && $this->bp = $args[1];
if (count($args) > 2) {
unset($args[0], $args[1]);
$this->args = $args;
}
} /* (non-PHPdoc)
* @see WindHandlerInterceptor::preHandle()
*/
public function preHandle() {
if (!method_exists($this, $this->callback)) return;
$injector = call_user_func_array(array($this, $this->callback), $this->args);
if ($injector) $this->bp->appendDo($injector);
} /* (non-PHPdoc)
* @see WindHandlerInterceptor::postHandle()
*/
public function postHandle() {} }
?>
原来是继承了过滤器,呵呵,所以这个比较强大啊,可以这样用
我们在看看上面控制器的这个方法 resolveActionFilter
/**
* action过滤链策略部署
*
* @example <pre>
* $filters = array(array('expression'=>'', 'class'=>'',
* args=array()));
* </pre>
* @param array $filters
* @return void
*/
protected function resolveActionFilter($filters) {
if (!$filters) return;
$chain = WindFactory::createInstance('WindHandlerInterceptorChain');
$args = array($this->getForward(), $this->getErrorMessage(), null);
foreach ((array) $filters as $value) {
$chain->addInterceptors(
WindFactory::createInstance(Wind::import($value['class']),
(empty($value['args']) ? $args : array_merge($args, array($value['args'])))));
}
$chain->getHandler()->handle();
}
流程是这样的,先建立过滤链 ,把过滤器一一添加实例化,哈哈,跟我们之前的没什么区别
但是事情还没有结速
class PwPostDoTag extends PwPostDoBase {
private $loginUser;
private $defaultType = 'threads';
private $tagNames = array();
private $typeId = '';
public function __construct(PwPost $pwpost,$tagNames) {
$this->loginUser = $pwpost->user;
$tagNames = $tagNames ? $tagNames : array();
$this->tagNames = array_unique($tagNames);
$this->typeId = $this->_getService()->getTypeIdByTypeName($this->defaultType);
}
public function addThread($tid) {
$this->_getService()->addTags($this->_buildTagDm($tid));
}
public function updateThread($tid) {
$this->_getService()->updateTags($this->typeId,$tid,$this->_buildTagDm($tid));
}
public function getDm() {
return new PwTagDm();
}
public function dataProcessing($postDm) {
if (!is_array($this->tagNames) || !$this->tagNames) return $postDm;
$postDm->setTags(implode(',',$this->tagNames));
return $postDm;
}
private function _buildTagDm($tid) {
if (!is_array($this->tagNames) || !$this->tagNames) return false;
$dmArray = array();
foreach ($this->tagNames as $value) {
$value = trim($value);
$dm = $this->getDm();
$dmArray[$value] =
$dm->setName($value)
->setTypeId($this->typeId)
->setParamId($tid)
->setIfhot(1)
->setCreateUid($this->loginUser->uid)
;
}
return $dmArray;
}
public function check($postDm) {
if (!is_array($this->tagNames) || !$this->tagNames) return true;
$count = count($this->tagNames);
foreach ($this->tagNames as $v) {
$dm = $this->getDm();
$dm->setName($v);
if(($return = $dm->beforeAdd()) instanceof PwError) return $return;
}
if ($count > 5) {
return new PwError("Tag:tagnum.exceed");
}
if ($count && $this->loginUser->getPermission('tag_allow_add') < 1) {
return new PwError("TAG:right.tag_allow_add.error");
}
return true;
}
/**
* Enter description here ...
*
* @return PwTagService
*/
protected function _getService() {
return Wekit::load('tag.srv.PwTagService');
}
}
那么 addThread 是在什么时候调用的呢,又是怎样调用的呢 看这里
/**
* @see PwPostAction.afterRun
*/
public function afterRun() {
$this->runDo('addThread', $this->tid);
}
这个类是 PwTopicPost 也正是我们在控制器里面刚刚实例化的 ,我们断点调式下看看
关键在这里
/* (non-PHPdoc)
* @see WindHandlerInterceptor::preHandle()
*/
public function preHandle() {
if (!method_exists($this, $this->callback)) return;
$injector = call_user_func_array(array($this, $this->callback), $this->args);
if ($injector) $this->bp->appendDo($injector);
}
把过滤器又加入到_do里面,不知道为什么要这样呢
$this->bp的值是多少呢

原来是这个pwPost
class PwPost extends PwBaseHookService {
public $action;
public $forum;
public $user;
public $special; // 帖子类型
public function __construct(PwPostAction $action) {
$this->action = $action;
$this->forum = $action->forum;
$this->user = $action->user;
$this->special = $action->getSpecial();
/** hook **/
$this->action->setSrv($this);
}
/**
* 发帖之前检测
*
* @return bool
*/
public function check() {
if (($result = $this->isInit()) !== true) {
return new PwError('data.error');
}
if (($result = $this->checkForum()) !== true) {
return $result;
}
if (($result = $this->checkPost()) !== true) {
return $result;
}
if ($this->isBan()) {
return new PwError('ban');
}
if (($result = $this->action->check()) !== true) {
return $result;
}
return true;
}
/**
* 初始化信息是否满足要求
*
* @return bool
*/
public function isInit() {
return $this->action->isInit();
}
/**
* 检测是否拥有该版操作权限
*
* @return bool
*/
public function checkForum() {
if (!$this->forum->isForum()) {
return new PwError('BBS:post.forum.not.exists');
}
if (($result = $this->forum->allowVisit($this->user)) !== true) {
return new PwError('BBS:forum.permissions.visit.allow',
array('{grouptitle}' => $this->user->getGroupInfo('name')));
}
return true;
}
/**
* 检测是否允许发帖
*
* @return bool
*/
public function checkPost() {
if ($this->user->groupid == 7) {
return new PwError('REG_CHECK');
}
/*
$config = Wekit::C('bbs');
if ($config['post.timing.open'] && !$this->user->inGroup($config['post.timing.groups']) && !self::inTime($config['post.timing.start_hour'], $config['post.timing.start_min'], $config['post.timing.end_hour'], $config['post.timing.end_min'])) {
return new PwError('BBS:post.timing');
}
*/
return true;
}
/**
* 检测用户是否被禁言
*
* @return bool
*/
public function isBan() {
if ($this->user->gid == 6) {
Wind::import('SRV:user.srv.PwBanBp');
$banBp = new PwBanBp($this->user->uid);
$memberid = 0;
if (false === $banBp->checkIfBanSpeak()) {
$memberid = $banBp->recoveryBanSpeaKError();
} elseif ($banBp->endDateTimeBanSpeak()) {
$memberid = $banBp->callEndDateTimeBanSpeak();
}
if ($memberid) {
$this->user->info['groups'] = '';
$this->user->info['groupid'] = 0;
$this->user->info['memberid'] = $memberid;
$this->user->groups = array($memberid);
$this->user->resetGid($memberid);
return false;
}
return true;
}
return false;
}
public function getDm() {
return $this->action->getDm();
}
/**
* 各应用获取该用户dm来设置,以达到更新用户信息的目的
*
* @return object PwUserInfoDm
*/
public function getUserDm() {
return $this->action->getUserDm();
}
public function getAttachs() {
return $this->action->getAttachs();
}
/**
* 发布
*
* @param object $postDm 帖子数据模型
* @return bool
*/
public function execute(PwPostDm $postDm) {
if (($result = $this->action->beforeRun($postDm)) instanceof PwError) {
return $result;
}
if (($result = $this->action->dataProcessing($postDm)) !== true) {
return $result;
}
if (($result = $this->action->execute()) !== true) {
return $result;
}
$this->action->afterRun();
$this->updateUser();
return true;
}
public function getInfo() {
return $this->action->getInfo();
}
public function getNewId() {
return $this->action->getNewId();
}
public function getDisabled() {
return $this->action->isDisabled();
}
/**
* 更新用户信息 /积分/发帖数/等
*/
public function updateUser() {
Wind::import('SRV:credit.bo.PwCreditBo');
$credit = PwCreditBo::getInstance();
if ($operation = $this->action->getCreditOperate()) {
$credit->operate($operation, $this->user, true,
array('forumname' => $this->forum->foruminfo['name']),
$this->forum->getCreditSet($operation));
}
$credit->execute();
$this->action->updateUser();
if ($userDm = $this->action->getUserDm(false)) {
Wekit::load('user.PwUser')->editUser($userDm, PwUser::FETCH_DATA);
}
}
public function appendDo($do) {
$this->action->appendDo($do);
}
public function runDo($method) {
$args = func_get_args();
call_user_func_array(array($this->action, 'runDo'), $args);
}
原来是这样,看到这里基本明白啦

基本上发帖中就要牵涉到这里操作了,如果第三方插件要加入的话就要加上服务当中
话题对应的hook 是 c_post_doadd
而发帖本身的hook是 m_PwTopicPost
来看看它是怎样定义的
<?php
defined('WEKIT_VERSION') || exit('Forbidden'); Wind::import('SRV:forum.srv.post.do.PwPostDoBase');
/**
* 帖子发布 - 话题
*
* @author jinlong.panjl <jinlong.panjl@aliyun-inc.com>
* @copyright ©2003-2103 phpwind.com
* @license http://www.phpwind.com
* @version $Id$
* @package wind
*/
class PwReplyDoRemind extends PwPostDoBase { private $loginUser;
private $_reminds = array();
private $_atc_title;
private $_maxNum; public function __construct(PwPost $pwpost) {
$this->loginUser = $pwpost->user;
$this->_maxNum = $this->loginUser->getPermission('remind_max_num');
} public function addPost($pid, $tid) {
$this->_addRemind($pid, $tid);
} public function updatePost($pid, $tid) {
$this->_addRemind($pid, $tid);
} public function dataProcessing($postDm) {
if ($this->_check() !== true) return $postDm;
$atc_content = $postDm->getField('content');
$atc_content = preg_replace('/\[quote(=.+?\,\d+)?\].*?\[\/quote\]/is', '', $atc_content);
$this->_atc_title = Pw::substrs(trim(Pw::stripWindCode($atc_content,true)),20); $reminds = $this->_getRemindService()->bulidRemind($atc_content);
$this->_reminds = $this->_getRemindService()->buildUsers($this->loginUser->uid,$reminds,$this->_maxNum);
$reminds = $this->_getRemindService()->formatReminds($this->_reminds);
$postDm->setReminds($reminds);
return $postDm;
} private function _addRemind($pid, $tid) {
if ($this->_check() !== true) return false;
if (!$this->_reminds) return false;
$reminds = ($this->_maxNum && count($this->_reminds) > $this->_maxNum) ? array_slice($this->_reminds, 0, $this->_maxNum) : $this->_reminds;
$remindUids = array_keys($reminds);
$this->_getRemindService()->addRemind($this->loginUser->uid, $remindUids); //发送通知
$extendParams = array(
'remindUid' => $this->loginUser->uid,
'title' => $this->_atc_title,
'remindUsername' => $this->loginUser->username,
'notice' => '在回帖 <a href="' . WindUrlHelper::createUrl('bbs/read/run', array('tid'=>$tid), $pid) . '" target="_blank">' . $this->_atc_title . '</a> @了您',
);
// 是否黑名单
$remindUids = $this->_checkBlack($remindUids);
foreach ($remindUids as $uid) {
$this->_getPwNoticeService()->sendNotice($uid,'remind',$pid,$extendParams);
}
} private function _check() {
if ($this->loginUser->getPermission('remind_open') < 1) {
return new PwError("bbs:remind.remind_open.error");
}
return true;
} /**
* 是否开启权限
*
* @param array $remindUids
* @return bool
*/
private function _checkBlack($remindUids) {
$result = Wekit::load('user.PwUserBlack')->checkUserBlack($this->loginUser->uid, $remindUids);
if ($result) {
$remindUids = array_diff($remindUids,$result);
}
return $remindUids;
} /**
* @return PwNoticeService
*/
protected function _getPwNoticeService(){
return Wekit::load('message.srv.PwNoticeService');
} /**
* PwRemindService
*
* @return PwRemindService
*/
private function _getRemindService(){
return Wekit::load('remind.srv.PwRemindService');
}
}
不同的类有不同的方法,可能就是调用时机不同,责任不同,总之就比较复杂
捣蛋phpwind控制器注入的更多相关文章
- 捣蛋phpwind之WindFrameWork
一直都有关注phpwind这个开源产品,从9.0开始就好关注拉,因为官方说把之前的代码重写了一遍,融入了windFramework这个框架,代码真的挺优美的,今日在做社区的一些功能,心血来潮就参考了p ...
- 捣蛋phpwind过滤器执行流程
从上一篇我们就大概就知道过滤器的定义和怎样去配置,这一节来说说执行流程 public function run($handlerAdapter = null) { $handlerAdapter != ...
- 007.ASP.NET MVC控制器依赖注入
原文链接:http://www.codeproject.com/Articles/560798/ASP-NET-MVC-Controller-Dependency-Injection-for-Be 前 ...
- ADO.NET .net core2.0添加json文件并转化成类注入控制器使用 简单了解 iTextSharp实现HTML to PDF ASP.NET MVC 中 Autofac依赖注入DI 控制反转IOC 了解一下 C# AutoMapper 了解一下
ADO.NET 一.ADO.NET概要 ADO.NET是.NET框架中的重要组件,主要用于完成C#应用程序访问数据库 二.ADO.NET的组成 ①System.Data → DataTable, ...
- ASP.NET MVC 控制器激活(二)
ASP.NET MVC 控制器激活(二) 前言 在之前的篇幅中,用文字和图像来表示了控制器的激活过程,描述的角度都是从框架默认实现的角度去进行描述的,这样也使得大家都可以清楚的知道激活的过程以及其中涉 ...
- ASP.NET MVC 控制器激活(三)
ASP.NET MVC 控制器激活(三) 前言 在上个篇幅中说到从控制器工厂的GetControllerInstance()方法来执行控制器的注入,本篇要讲是在GetControllerInstanc ...
- angularJS推荐显示注入写法
使用js压缩工具时发现压缩之后的控制器注入参数由原来的$scope变成了a,b...这样的字母而导致js失效,那么我们推荐使用完整的显示注入方式来解决此问题! //隐式注入的写法 angular.mo ...
- MVC 控制器激活
MVC 控制器激活 ASP.NET MVC 控制器激活(三) 前言 在上个篇幅中说到从控制器工厂的GetControllerInstance()方法来执行控制器的注入,本篇要讲是在GetControl ...
- ASP.NET MVC Autofac依赖注入的一点小心得(包含特性注入)
前言 IOC的重要性 大家都清楚..便利也都知道..新的ASP.NET Core也大量使用了这种手法.. 一直憋着没写ASP.NET Core的文章..还是怕误导大家.. 今天这篇也不是讲Core的 ...
随机推荐
- 运行java -version报cannot restore segment prot after reloc: Permission denied
linux 安装jdk1.6后,运行java -version,没有出现相关的版本信息,而是出现了以下错误: dl failure on line 685Error: failed /usr/loca ...
- java遍历Map时remove删除元素
public class T { /** * @param args */ public static void main(String[] args) { // TODO Auto-generate ...
- Android模拟器使用教程
Using the Emulator In this document Overview Android Virtual Devices and the Emulator Starting and S ...
- apiCloud创建APP项目
1.注册一个apiCloud账户 2.创建一个应用 3.安装sublime插件 4.用sublime创建应用 5.配置参数,保证一致 6.上传代码,两种方式 一种是压缩成zip 一种是配置svn,通过 ...
- find-all-anagrams-in-a-string
https://leetcode.com/problems/find-all-anagrams-in-a-string/ package com.company; import java.util.A ...
- Sublime Text 插件列表(整理中...)
作为Java Web的开发者,前端和后端的技术都会用到,用了几款文本编辑器,Uedit32.EditPlus.Sublime Text等,发现还是Sublime Text用起来最方便. 首先安装pac ...
- 使用ajaxfileupload插件提示Uncaught TypeError:has no method 'handleError'
最近使用ajaxfileupload插件上传文件时,后台正常运行时,可以正常使用:当后台出现异常时,上传后没有任何反应,也无任何返回信息,使用chrome查看时,发现ajaxfileupload插件报 ...
- QQ互发消息
private NewsData data; private void button3_Click(object sender, EventArgs e) //发送 { string x = text ...
- CSS之切出横幅
简述 上节分享了clip-path来实现一个剪切横幅,本节通过另外一种方式来实现一个更经典的横幅. 简述 最终效果 小三角 效果 源码 阴影分割 效果 源码 合并 最终效果 我们先看一下最终要实现的效 ...
- UVa 10048 Audiophobia【Floyd】
题意:给出一个c个点,s条边组成的无向图,求一点到另一点的路径上最大权值最小的路径,输出这个值 可以将这个 d[i][j]=min(d[i][j],d[i][k]+d[k][j]) 改成 d[i][j ...