CakePHP 3.0自定义事件实现

时间:2015-03-12 11:39:00

标签: php cakephp observer-pattern cakephp-3.0

我正在测试CakePHP v3.0.0-RC2上的事件系统以用于我的项目目的。我首先要为长篇文章道歉。

基本上我创建了一个包含字段id,name和surname的users表。然后,我创建了另一个名为user_statistics的表,该表记录了每月用户创建的数量。下面是保存用户,为UserStatistics表对象创建事件,然后最终调度事件的函数。

use Cake\Event\Event;
class UsersTable extends Table
{
  //Other code
   public function createUser($user)
   {
      if( $this->save( $user )){

        $event = new Event('Model.User.afterPlace', $this, array( 
           'user' => $user 
          ));

        $this->eventManager()->dispatch( $event );

        return true;
       }
      return false;
    }
  }

这个函数完成了预期的工作 - 部分是这样 - 因为它似乎不会调度事件而只保存用户数据。也许问题在于UserStatistics表对象。下面是我如何实现处理用户统计的函数的代码片段。

use Cake\Event\EventListenerInterface;

class UserStatistics extends Table implements EventListenerInterface
{
   //Code ommitted for in account of relevence

    public function tallyUsers( $event )
    {
       $data = array();
       if(!empty($event->subject()->user)){

          $date = date('Y-m-d');

          // Check existing record of today 
          $record = $this->find()->where(array('date' => $date));

          if(empty($record)){

             //Insert new record if none exist for the current date
             $data = array(
               'date' => $date,
               'count' => 1
             );
           }else{

             //Update record if date exist by incerementi count field by one
             $count = (int) $record->count + 1;

             $data = array(
                'id' => $record->id,
                'date' => $date,
                'count' => $count
               );
           }

          if($this->save($data))
            return true;
          else
            return false;
        }
    }
}  

在此之后,我对我在哪里注册UserStatistics以使其能够观察User对象有一点误解。当然,我在UserStatistics表对象上实现了implementsEvents()方法(见下文):

public function implementedEvents()
{
   return array(
      'Model.User.afterPlace' => 'tallyUsers'
    );
}

我发现我应该在UsersController中注册我的观察者(UserStatistics)。以下是我去做的方式:

...
publiv function add()
{
   if($this->request->is('post')){

      $this->loadModel('UserStatistics');
      $this->Users->eventManager()->on( $this->UserStatistics );

      if($this->Users->createUser( $user )){
        ....
      }
   }
}

问题(S):

  1. 如何访问在Users表对象上传递的数组用户,即array('user'=> $ user)?
  2. 在Users表对象的createUser方法中返回true或false的假设是什么?
  3. 我是否在控制器内的主题模型上传递了观察者对象?
  4. 我的UserStatistics tallUsers()方法应该返回任何内容吗?
  5. 请帮助我理解,因为我无法从文档本身或任何其他地方找到有关此主题的清晰读物。

1 个答案:

答案 0 :(得分:0)

我设法让两个表对象相互通信。每次用户对象创建新用户时都会使用记录更新用户统计信息表,在我们的例子中是用户对象。

为了让它发挥作用,我遇到了很多例外。基本上我必须强制执行主键,因为它无法创建没有id的新实体。我希望能够在特定月份没有记录时创建新记录,否则如果记录存在则更新计数字段。所以问题不在其他地方,而是在下面的代码上:

public function update( $event )
{
  if(!empty( $event->data)){

    // find current month's record
     if( empty( $record )){
       //Create a new row
       $entity = new \App\Model\Entity\UserStatistic(['id' => 1, 'date' => $date, 'count' => 1]);
       $update = $this->save($entity);
     }else{
       $entity = new \App\Model\Entity\UserStatistic(['id' => $record->id + 1, 'count' => (int) $record->count + 1]);

       $updated = $this->save( $entity );
      }
   }
}

这段代码出了点问题我无法理解,但最终我能够试验框架提供的事件系统以及我现在遇到的问题我想要相信事件系统相关。任何有关上述解释的帮助都将不胜感激。