Mình đã làm việc với cả hai frameworks là Laravel 5.x và CakePHP 3.x (trong bài này
mình không so sánh hai frameworks đó). Mình thấy trong Laravel 5.x có một tính năng
rất hay là có thể bật và tắt chế độ bảo trì bằng CLI, đó là artisan down
và artisan up
.
Trong CakePHP 3.x mình không thấy có tính năng này và mình bắt đầu tìm hiểu để
tích hợp thêm tính năng này cho CakePHP.
Đầu tiên mình đặt ra yêu cầu:
bin/cake
Đầu tiên mình nghĩ là nên tạo một action là maintenance rồi forward tất cả các requests
về action này khi bật một cái cờ. Cách này có vẻ đơn giản khi mình viết trong AppController
như sau:
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
<?php
namespace App\Controller;
use Cake\Controller\Controller;
use Cake\Event\Event;
class AppController extends Controller
{
// ....
public function beforeFilter(Event $event)
{
if ($this->enabledMaintenanceMode()) {
$this->setAction('maintenance');
}
}
public function maintenance()
{
// TODO: render alert page
}
/**
* @return boolean
*/
protected function enabledMaintenanceMode()
{
// TODO: check maintenance mode is enabled
}
// ...
}
Tuy đơn giản nhưng mình thấy nó còn có nhiều hạn chế, đặc biệt nó vẫn phải chạy sau nhiều xử lý khác hoặc có thể bị AuthComponent chặn, bắt login, …
Mình tiếp tục nghiên cứu thêm thì thấy cái dispatcher nó có hệ thống event chạy trước khi dispatch. Hay quá, nếu bắt event này và chạy thì nó sẽ chưa cần phải dispatch, nhẹ hơn cho server. Mình đã viết một class DispatcherFilter để kiểm tra và cho hiển thị trang cảnh báo.
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
<?php
namespace App\Routing\Filter;
use Cake\Core\Configure;
use Cake\Event\Event;
use Cake\Routing\DispatcherFilter;
class MaintenanceModeFilter extends DispatcherFilter
{
/**
* @var int This filter should run first
*/
protected $_priority = -1;
public function implementedEvents()
{
return [
'Dispatcher.beforeDispatch' => [
'callable' => 'handle',
'priority' => $this->_config['priority']
],
];
}
public function handle(Event $event)
{
if ($this->enabledMaintenanceMode()) {
// stop event
$event->stopPropagation();
$request = $event->data['request'];
$response = $event->data['response'];
// TODO: render maintenance alert page
$response->body('Maintenance mode ON');
return $response;
}
}
/**
* @return boolean
*/
protected function enabledMaintenanceMode()
{
// TODO: check maintenance mode is enabled
}
}
Như các bạn thấy, mình set property $_priority = -1
là để đảm bảo nó được thực thi
trước các filter khác. Mình cũng viết class shell để có hai commands bật và tắt
chế độ bảo trì. Để tạo cờ chó việc bặt tắt chế độ bảo trì, mình đã sử dụng một cách
là khi bật chế độ bảo trì, mình tạo ra một file là maintenance.php
ở trong thư mục
TMP
của ứng dụng, khi tắt chế độ bảo trì thì sẽ xóa nó đi. Nội dung của file này
là các config giúp cho mình render trang cảnh bảo.
Mình cũng đã dóng gói thành một plugin để cho mọi người có thể dễ dàng sử dụng hơn. Mọi người có thể cài đặt nó và sử dụng tại đây
Comments