[英]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.