[英]CakePHP 2.x Achievements
我正在尝试使用CakeEvents在CakePHP应用程序中构建成就系统。 我一直在使用以下网站来帮助我将活动汇总: http : //martinbean.co.uk/blog/2013/11/22/getting-to-grips-with-cakephps-events-system/
在我的应用中,成就称为徽章,可以授予用户。 这些徽章是根据将徽章与Cake事件链接的规则授予的。
因此,例如,如果用户创建了一个帖子,则将触发Model.Post.add
事件,该事件应检查该事件是否存在任何规则,如果匹配,则参数匹配,如果所有签出都再次授予徽章与该规则相关联的用户。
该架构包含以下表格:
用户
帖子
徽章
事件
event_badges
badge_users
希望一切都有意义。 这里是展示它们如何连接的模型。
user.php的
class User extends AppModel
{
public $name = 'User';
public $hasMany = array(
'Post', 'Badge'
);
public $belongsTo = array(
'BadgeUser'
);
}
Badge.php
class Badge extends AppModel {
public $hasMany = array(
'BadgeUser'
);
public $actsAs = array('Containable');
}
Event.php
class Event extends AppModel {
public $hasMany = array(
'EventBadge'
);
public $actsAs = array('Containable');
}
EventBadge.php
class ActionBadge extends AppModel {
public $belongsTo = array(
'Action', 'Badge'
);
public $actsAs = array('Containable');
}
BadgeUser.php
class BadgeUser extends AppModel {
public $belongsTo = array(
'Badge', 'User'
);
public $actsAs = array('Containable');
}
**如果您认为该模式不正确,无法发表评论,请随时发表评论。**
因此,示例徽章可能是:
还有“事件”表中的一些示例规则:
如您所见,事件链接到上述徽章,并且使用CakeEvents系统调用事件。
好的,所以当一个人做某事时,比如说保存了一个新帖子,我在Post模型中有以下内容:
public function afterSave($created, $options = array()) {
if ($created) {
$event = new CakeEvent('Model.Post.add', $this, array(
'id' => $this->id,
'data' => $this->data[$this->alias]
));
$this->getEventManager()->dispatch($event);
}
}
第一个问题是,如何将不同的事件传递给afterSave? 由于控制器中的Add和Edit方法都会触发此操作...
然后我在/app/Event
有一个PostListener.php文件
class PostListener implements CakeEventListener {
public function implementedEvents() {
return array(
'Model.Post.add' => 'postAdded',
'Model.Post.edit' => 'postEdited',
'Model.Post.view' => 'postViewed',
'Model.Post.delete' => 'postDeleted',
);
}
public function postAdded(CakeEvent $event) {
$this->Badge->awardBadge($badgeId, $userId);
}
public function postEdited(CakeEvent $event) {
}
public function postViewed(CakeEvent $event) {
}
public function postDeleted(CakeEvent $event) {
}
}
因此,下一个问题是如何将事件侦听器链接回我的“事件”表?
然后授予与该动作相关的徽章? 请注意,有些用户将需要做额外的检查,例如用户必须创建10个帖子才能获得标记的10个帖子,而不仅仅是因为他们已经创建了一个帖子。
在Badge.php模型中,我具有以下授予徽章的功能:
public function awardBadge($badgeId, $userId) {
$controlFind = $this->BadgeUser->find(
'first',
array(
'conditions' => array(
'badge_id' => $badgeId,
'user_id' => $userId,
)
)
);
if(!$controlFind) {
$temp = array(
'BadgeUser' => array(
'badge_id' => $badgeId,
'user_id' => $userId,
'created' => date('Y-m-d H:i:s')
)
);
$collection[] = $temp;
return $this->BadgeUser->saveAll($collection, array('validate' => false));
}
}
因此,当事情与数据库规则匹配时,我需要从侦听器运行上面的代码。 只是努力使所有东西粘在一起。
我认为您的数据库架构可能由于具有事件概念而使事情复杂化。 就个人而言,我会有一个badges
表,用于存储徽章标题和描述(如果需要,还可以包含图像路径)。 然后,我将有一个与每个徽章相对应的事件侦听器,因此将涉及一定程度的体力劳动。
因此,让我们考虑一个示例方案。 假设用户发布100次,便会授予徽章。 因此,您将拥有一个Post
模型,该模型会在保存帖子时触发一个事件:
<?php
App::uses('CakeEvent', 'Event');
class Post extends AppModel {
public function afterSave($created, $options = array()) {
$event = new CakeEvent('Model.User.afterSave', $this);
$this->getEventManager()->dispatch($event);
}
}
然后,您可以创建一个相应的处理程序:
<?php
// Event/BadgeListener.php
App::uses('CakeEventListener', 'Event');
App::uses('ClassRegistry', 'Utility');
class BadgeListener implements CakeEventListener {
public function implementedEvents() {
return array(
'Model.Post.afterSave' => 'afterSaveListener'
);
}
public function afterSaveListener(CakeEvent $event) {
// check number of posts
$this->Post = ClassRegistry::init('Post');
$count = $this->Post->find('count', array(
'Post.author_id' => $event->subject()->data[$event->subject()->alias]['author_id'];
));
// award badge
if ($count > 100) {
// TODO: check user does not already have badge
$this->BadgeUser = ClassRegistry::init('BadgeUser');
$this->BadgeUser->create();
$this->BadgeUser->set('badge_id', 'whatever_badge_id_actually_is');
$this->BadgeUser->set('user_id', $this->Auth->user('id')); // logged in user ID
$this->BadgeUser->save();
}
}
}
这是一个粗略的示例,但希望它能引导您朝着正确的方向发展。
如果有什么要我清理的,请告诉我,我会尽力而为。
第一个问题 -区分新帖和编辑
要区分添加和编辑,您需要在创建CakeEvent时传递$created
参数。 像这样:
public function afterSave($created, $options = array()) {
//NOTICE: it's afterSave now, since this will be called after edit or new
$event = new CakeEvent('Model.Post.afterSave', $this, array(
'created' => $created, //NOW you will know when you process the even if this was a new post or post edit
'id' => $this->id,
'data' => $this->data[$this->alias]
));
$this->getEventManager()->dispatch($event);
}
您应该将事件以后处理和匹配规则所需的所有数据添加到事件数据中 。 如果您认为需要使用它来进行一些查询,甚至可以添加模型对象本身。
第二个问题 -如何将事件处理链接到事件表
在事件侦听器中,您可以使用ClassRegistry获取事件模型(以及您需要的任何其他模型)的实例。 您可以进行规则匹配,一旦拥有了所有需要的数据,便将徽章保存到数据库中。
由于您现在知道是编辑还是新帖子(来自event-> data),因此可以采取适当的措施。
编辑器ID我想您可以将它作为登录用户与Auth组件一起使用。 因此,您可以使用它从数据库中读取有关编辑器的需求。
总结一下:发送事件时,请使用事件数据在侦听器中传递所需的所有信息。 事件可以携带更多信息,而不仅仅是它们的名称和它们被触发的事实 。 您可以发送,然后查看整个“上下文”。
在侦听器中,充分利用从事件中获取的数据以及当前登录的用户ID或帖子作者,进行所需的匹配,然后为适当的用户保存徽章。
希望这是您正在寻找的:)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.