cakephp3 event事件系统实战

cakephp3支持event了。更灵活,这样的话 我们就可以省很多代码,可以全局监听修改。

比如有如下需求:

1,对前台页面提交的post进行处理,如果有required_fields字段的内容,就把该内容插入notification_fielda表中

3,给前台页面动态插入js和html

2,对前台页面提交的post进行过滤,如果date类型的字段值为空的话,就转换成null,进行保存。

 

步骤:

1,先在config/bootstrap.php里最后一行添加监听的class

1
2
3
4
5
// Attach event listeners
use Cake\Event\EventManager;
use App\Controller\Event\NotificationSaveListener;
$myListener = new NotificationSaveListener();
EventManager::instance()->on($myListener);

 

2,class的代码。我放在了App\Controller\Event\NotificationSaveListener.php里

cakephp3自带了很多events,比如针对model的

1
2
3
4
5
6
7
8
9
10
11
12
在vendor/cakephp/src/ORM/Table.php
'Model.beforeMarshal'
'Model.buildValidator'
'Model.beforeFind'
'Model.beforeSave'
'Model.afterSave'
'Model.afterSaveCommit'
'Model.beforeDelete'
'Model.afterDelete'
'Model.afterDeleteCommit'
'Model.beforeRules'
'Model.afterRules'

还有针对控制器和view的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
在vendor/cakephp/src/Controller/Controller.php
'Controller.initialize'
'Controller.startup'
'Controller.shutdown'
'Controller.beforeRedirect'
'Controller.beforeRender'

在vendor/cakephp/src/View/View.php
'View.beforeRender'
'View.afterRender'
'View.beforeLayout'
'View.afterLayout'
'View.beforeRenderFile'
'View.afterRenderFile'
'View.beforeRender'
'View.afterRender'

 

那么针对我们任务要求,只需要3个event就行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
<?php
namespace App\Controller\Event;

use Cake\Event\EventListenerInterface;
use Cake\ORM\TableRegistry;
class NotificationSaveListener implements EventListenerInterface {
protected $allowTable = ['buildings','building_parking_spots','building_apartments','contracts','building_attachment'];
protected $allowController = ['Buildings','BuildingParkingSpots','BuildingApartments','Contracts','Attachments'];
protected $allowAction = ['add','edit','parking-spots-add','parking-spots-edit'];

public function implementedEvents() {
return array(
'Model.beforeMarshal' => 'beforeSaveFields',//系统自带的event,过滤date类型类型的值
'Model.afterSave' => 'saveNotificationRequiredFields',//系统自带的event,保存required_field的值
'View.afterLayout' => 'setNotificationJsAfterLayout',//系统自带的event,动态插入js和html
'Attachment.Update.Notification.Settings' => 'updateNotificationSettings'//这是自定义的event
);
}
public function updateNotificationSettings($event){
$subject = $event->getSubject();
$data = $event->getData('data');
if(isset($data['required_fields']) && $data['required_fields']){
$fieldsData = $data['required_fields'];
//print_r($fieldsData);die;
$table = 'building_attachment';
$entityId = $data['building_id'];
$this->saveData($table,$entityId,$fieldsData);
}
exit();
}
public function beforeSaveFields($event){
$request = new \Cake\Http\ServerRequest();
if ($request->is(['patch', 'post', 'put'])) {
$subject = $event->getSubject();
$data = $event->getData('data');
$schema = $subject->getSchema();
//$table = $subject->getTable();
//payall_payment_date_6
//var_dump($schema->getColumnType("payall_payment_date_4"));die;
$allowTypes = ['date'];
$unsetKeys = [];
// echo "<pre>";
// print_r($data);
// echo "</pre>";die;
foreach ($data as $key => $value) {
if($value == '' && in_array($schema->getColumnType($key), $allowTypes)){
array_push($unsetKeys, $key);
}
}
foreach ($unsetKeys as $key) {
unset($data[$key]);
}
foreach ($unsetKeys as $key) {
$data[$key] = null;
}
//print_r($unsetKeys);
//var_dump($data);die;
// $event->setData('data',$data);
}
}
public function saveNotificationRequiredFields($event) {
$subject = $event->getSubject();
$request = new \Cake\Http\ServerRequest();
if ($request->is(['patch', 'post', 'put'])) {
$table = $subject->getTable();
if($table){
if(in_array($table, $this->allowTable)){
$alias = $subject->getAlias();
$entity = $event->getData('entity');
//$urlParams = explode('/', trim($_SERVER['REQUEST_URI'],'/'));
if(isset($_POST['required_fields'])){
$fieldsData = $_POST['required_fields'];
//print_r($fieldsData);die;
$entityId = $entity->id;
if(isset($entity->entity_id)){
$entityId = $entity->entity_id;
}
$this->saveData($table,$entityId,$fieldsData);
}

}
}
}
}
public function setNotificationJsAfterLayout($event) {
$subject = $event->getSubject();
//echo $subject->name;
$request = $subject->request;
$controller = $request->getParam('controller');
$action = $this->uncamelize($request->getParam('action'));
//echo $controller.'|'.$action;
if(in_array($controller, $this->allowController) && in_array($action, $this->allowAction)){
$js = $subject->Html->script('notification_required_fields');
$controllerName = $this->uncamelize($controller);
$id = current($request->getParam('pass'));
$transStrs = ['Required','Notify after'];
$translates = [];
foreach ($transStrs as $str) {
$translates[$str] = __($str);
}
$js .= '<script>var currentPageUrlName = "'.$controllerName.'-'.$action.'";var notificationTranslates = '.json_encode($translates).';</script>';
if($id){
$notificationTable = TableRegistry::get('NotificationRequiredFields');
$tableName = $this->uncamelize($controller,'_');
if($tableName == 'attachments'){
$tableName = 'building_attachment';
}
$query = $notificationTable->find()->where(['entity_id' => $id, 'table_name' => $tableName]);
$result = [];
foreach ($query as $item) {
$result[$item->column_name]['required_type'] = $item->required_type;
$result[$item->column_name]['required_date'] = date('d.m.Y',strtotime($item->required_date));
}
$js .= '<script>var exsitNotificationRequiredFields = '.json_encode($result).'</script>';
//echo $tableName;die;
}
//get
//echo $controller.'-'.$action;
// var_dump($subject->getAction());
// print_r($subject->Blocks);
$pageHtml = $subject->Blocks->get('content');
$pageHtmlCompressed = $pageHtml.$js;
$event->subject()->Blocks->set('content', $pageHtmlCompressed);
}
}

function camelize($uncamelized_words,$separator='_')
{
$uncamelized_words = $separator. str_replace($separator, " ", strtolower($uncamelized_words));
return ltrim(str_replace(" ", "", ucwords($uncamelized_words)), $separator );
}
function uncamelize($camelCaps,$separator='-')
{
return strtolower(preg_replace('/([a-z])([A-Z])/', "$1" . $separator . "$2", $camelCaps));
}

 

3,关于自定义event。比如第二步里的Attachment.Update.Notification.Settings。

我是设置在App\Controller\AttachmentsController里的

updateNotificationSettings方法里

1
2
3
4
5
6
7
8
public function updateNotificationSettings(){
$data = $this->request->getData();
$event = new Event('Attachment.Update.Notification.Settings', $this, [
'data' => $data
]);
$this->eventManager()->dispatch($event);
//exit();
}

这样就能被监听到了。

 

4,参考

https://book.cakephp.org/3.0/en/core-libraries/events.html

坚持原创技术分享,您的支持将鼓励我继续创作!