I was testing out the Events System on CakePHP v3.0.0-RC2 for my project purposes. I first have to apologise for the long text.
Basically I created a users table with fields id, name, and surname. I then created another table called user_statistics that tallies number of user creations per month. Below is the function that saves a user, create an event for the UserStatistics table object and then finally dispatch the event.
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;
}
}
This functions does what its expected - partially so - as it does not seem to dispatch the event but only save the user data. Perhaps the issue lies with the UserStatistics table object. Below is a code snippet of how I have implemented the function that handles tallying of users.
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;
}
}
}
After this I had a little misunderstanding as to where I am suppose to register the UserStatistics such that its able to observe the User object. Ofcourse I have implemented the implementedEvents() method on my UserStatistics table object (see below):
public function implementedEvents()
{
return array(
'Model.User.afterPlace' => 'tallyUsers'
);
}
I figured out that I should register my observer(UserStatistics) inside the UsersController. Below is how I went about doing it:
...
publiv function add()
{
if($this->request->is('post')){
$this->loadModel('UserStatistics');
$this->Users->eventManager()->on( $this->UserStatistics );
if($this->Users->createUser( $user )){
....
}
}
}
Question(s):
Please help me understand as I couldnt find clear readings on this subject from the doc itself or any other place.
I have managed to get the two table objects talking to each other. The user statistics table is updated with a record each and everytime a new user is created by the users object which in our case is our subject.
I have suffered so many exception in order to get it to work. Basically I had to enforce a primary key because it couldnt create a new entity without an id. I want to be able to create new records when no records exist for that particular month else update the count field if a record does exist. So the problem is nowhere else but on the code below:
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 );
}
}
}
Something is wrong with this code and I cannot put my finger on but ultimately I was able to experiment with the Event System provided by the framework and the issue I am having now I want to believe is Event System related. Any help with regards to the explanation provided above would be appreciated.