В первых двух частях этой серии мы завершили полнофункциональный плагин, который показывает нам статус сервера в виде виджета на приборной панели. Как таковой, он доступен каждому зарегистрированному пользователю. Некоторая информация может быть конфиденциальной, и мы не хотим, чтобы они ее видели, поэтому лучше проверить роль пользователя, чтобы определить, следует ли нам сделать виджет доступным для них.
Использование ролей или возможностей для ограничения видимости
WordPress использует концепцию ролей , разработанную, чтобы дать владельцу сайта возможность контролировать то, что пользователи могут и не могут делать на сайте. Каждой роли разрешено выполнять набор задач под названием « Возможности» . Мы можем настроить роль и ее возможности с помощью функций add_roles и add_cap .
Наш плагин создаст новую возможность вызова servermetric
. Только пользователь, обладающий такой возможностью, может загрузить наши виджеты панели мониторинга. Мы добавим эту возможность для роли администратора, чтобы все пользователи администратора видели ее по умолчанию.
Для других пользователей вы можете использовать плагин User Role Editor для управления возможностями любого конкретного пользователя, а также назначить для servermetic
возможность servermetic
.
Мы используем add_cap для добавления новой возможности, однако, эта функция записывает в базу данных, поэтому мы должны делать это только при активации плагина. После деактивации мы должны очистить базу данных, удалив роль с помощью remove_cap .
01
02
03
04
05
06
07
08
09
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
|
class Dashboard {
//…other code
const CAP_METRIC = ‘server_metric’;
/**
* Start to setup hook
*/
public function run() {
add_action( ‘wp_dashboard_setup’, array( $this, ‘add_dashboard_widgets’ ) );
add_action( ‘admin_enqueue_scripts’, array($this, ‘add_asset’));
add_action( ‘admin_footer’, array($this, ‘footer’));
register_activation_hook(__FILE__, array($this, ‘add_servermetric_caps’));
register_deactivation_hook(__FILE__, array($this, ‘remove_servermetric_caps’));
}
/**
* Add severmetric capability for admin by default
*/
function add_servermetric_caps() {
// gets the author role
$role = get_role( ‘administrator’ );
// This only works, because it accesses the class instance.
// would allow the author to edit others’ posts for current theme only
$role->add_cap( self::CAP_METRIC );
}
function remove_servermetric_caps() {
// get_role returns an instance of WP_Role.
$role = get_role( ‘administrator’ );
$role->remove_cap( self::CAP_METRIC );
}
//…
}
|
Мы создаем новый константный вызов CAP_METRIC
и устанавливаем его значение равным server_metric
чтобы впоследствии легко было легко изменить имя возможности. Мы модифицируем наш метод run
для добавления двух хуков.
Register_activation_hook запускается при активации плагина. Он принимает два параметра:
- (строка) имя файла: путь к основному файлу плагина
- ( обратный вызов ) ( обязательно ) Функция, запускаемая при активации плагина
register_deactivation_hook запускается при деактивации плагина. Он принимает тот же параметр, что и register_activation_hook.
administrator
ролей и вызывать add_cap
или remove_cap
для объекта ролей . add_dashboard_widgets
наш метод add_dashboard_widgets
чтобы зарегистрировать виджеты только в том случае, если текущий пользователь имеет servermetric
.
01
02
03
04
05
06
07
08
09
10
11
12
|
/**
* Register dashboard widget proider to show up on dashboard
*/
function add_dashboard_widgets() {
if (!current_user_can(self::CAP_METRIC)) {
return false;
}
$widget = Widget::instance();
foreach ($widget->get_provider() as $name=>$provider) {
$widget->register($name);
}
}
|
Затем мы используем current_user_can, чтобы проверить, имеет ли текущий пользователь возможность запроса.
Теперь только администратор увидит виджет при загрузке панели инструментов. Если вы хотите включить виджет состояния сервера для других пользователей, вы можете установить плагин User Role Editor для управления ролями и возможностями для любых пользователей.
Затем на экране возможностей мы можем назначить ограничение server_metric
.
Используя роли и возможности, мы повысили безопасность нашего плагина, чтобы сделать наш виджет доступным только пользователю, которому мы доверяем.
Кэширование метрики сервера
WordPress использует API-интерфейс Transient в качестве API-интерфейса кеша. Данные сериализуются и сохраняются в таблицу wp_option
WordPress с указанием срока действия кэша.
Вместо того, чтобы получать метрические данные для каждого HTTP-запроса, мы можем получить данные один раз и кэшировать их. Однако мы не можем просто поместить все в кеш или использовать то же время истечения. Например, дисковое пространство можно кэшировать в течение 15 минут, а информацию о сервере можно кэшировать в течение 60 минут, поскольку они редко меняются. Точно так же установленное программное обеспечение может быть кэшировано на день, так как оно редко изменяется после настройки сервера и подготовки к работе.
В основном мы используем get_transient
и set_transient
при работе с API. Согласно документации WordPress:
-
get_transient( $transient )
: получить временное имя в виде строки и вернуть его данные. Если срок действия данных истек, возвращается false. Мы должны использовать оператор===
для проверки, потому что мы можем хранить пустое значение для переходного процесса. -
set_transient( $transient, $value, $expiration )
: извлекает три параметра: имя переходного процесса, его значение и время его истечения в секундах. Обратите внимание, что временное имя не должно быть длиннее 45 символов.
Наши два варианта — рассмотреть возможность кэширования данных метрики или кэширования сгенерированных данных HTML. Кэширование данных HTML может сделать наш сайт очень быстрым, но это создает нагрузку на базу данных. С этой целью мы могли бы сделать тест, чтобы решить, какой из них лучше.
Для нашего урока давайте просто кешируем данные метрики. Кроме того, у нас должен быть способ аннулировать кэш — например, привязку — который позволит нам перезагружать данные панели мониторинга и принудительно загружать данные, а не из кэша.
Кэширование данных для виджета
Мы можем напрямую использовать функцию get_transient
или set_transient
для работы с Transient API. Однако, если мы решим изменить способ, которым мы использовали Transient API, мы должны перейти к каждому месту, где мы его используем, и изменить его для каждого виджета.
Давайте добавим еще один слой, чтобы абстрагировать механизм кэширования. Мы разработаем простой класс кэша для нашего виджета, который имеет три метода:
-
set
: установить данные кеша для виджета -
get
: получить данные кеша для виджета -
load
: попытаться загрузить из кеша, если не существует, рассчитать данные, установить кеш и вернуть
Давайте widget/cache.php
файл widget/cache.php
следующим образом. Обратите внимание, что в соответствии с соглашением об автоматической загрузке имя класса будет Cache
а его пространство имен — AX\StatBoard\Widget
01
02
03
04
05
06
07
08
09
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
|
<?php
namespace AX\StatBoard\Widget;
use AX\StatBoard\Widget\Provider;
class Cache {
/**
* Get cache for a particular widget
*/
static function get(Provider $provider) {
$cache_id = get_class($provider);
if (false !== $data = get_transient($cache_id)) {
return $data;
}
return false;
}
/**
* Default we cached 5 minutes
*/
static function set(Provider $provider, $value, $cache_time = 300) {
$cache_id = get_class($provider);
set_transient($cache_id, $value, $cache_time);
}
/**
* Load data from cache.
* put into cache.
*
*/
static function load(Provider $provider, $cache_time = 300) {
if (false !== $data = static::get($provider)) {
return $data;
}
//no data yet, let’s pull it and put it into cache
$data = $provider->get_metric();
static::set($provider, $data, $cache_time);
return $data;
}
}
|
Во-первых, обратите внимание, что мы пометили наши методы кэширования как статические. Наши методы set
и get
являются просто обертками для get_transient
и set_transient
. Метод load
находится поверх set
и get
. Все эти методы рассчитывают получить объект провайдера виджета; поэтому внутри метода load
мы можем вызвать метод get_metric
для получения реальных данных.
Время использовать наш класс Cache
. Мы постараемся реализовать Cache
для widget/software.php
. Измените наш оригинальный метод get_content
на:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
|
<?php
namespace AX\StatBoard\Widget;
class Software implements Provider {
//…
public function get_content() {
$cmds = Cache::load($this, 3600 * 24);
$content = »;
foreach ($cmds as $cmd=>$info) {
$content .= «<p><strong>$cmd</strong> $info</p>»;
}
echo $content;
}
//…
}
|
Вы можете видеть, что мы избавились от $cmds = $this->get_metric()
и просто заменили его на Cache::load
который будет загружать данные из кеша или загружать их из системы, если кеша не было.
Теперь, когда у вас есть идея, вы можете повторить с любым другим виджетом, который вы хотели бы кэшировать. Просто замените get_metric
внутри get_content
на:
1
|
Cache::load($this, $time_in_second);
|
чтобы он позаботился о своем кешировании.
Данные об использовании диска могут кэшироваться часами, а интерфейс Ethernet может кэшироваться в течение дня или около того. Вам решать, как долго вы хотите его кешировать. Мы также можем создать страницу параметров для плагина, чтобы управлять этими значениями времени жизни кэша. Это может быть упражнение для вас, чтобы продолжить работать после того, как мы закончили эту статью.
У нас есть один последний пример с widget/ethernet.php
. Мы можем добавить кеш-способность следующим образом:
1
2
3
4
5
6
|
<?php
namespace AX\StatBoard\Widget;
class Ethernet implements Provider {
//…
}
|
Опять же, нам нужно только заменить get_metric
на Cache::load
. Информация о Ethernet и его IP-адрес, вероятно, никогда не изменятся, поэтому я установил очень длительное время жизни кэша в одну неделю: 3600 секунд * 24 часа * 7 дней.
Принудительная загрузка реальных данных
После того, как мы добавили возможность кэширования, мы должны поддерживать механизм, позволяющий администратору извлекать виджет без его кэширования. Самый простой способ сделать это — использовать специальный параметр запроса, чтобы указать, что нам нужны реальные данные.
Как насчет небольшого параметра, такого как nocache
для этого? Таким образом, вместо стандартного URL панели WordPress с domain.com/wp-admin/
мы можем использовать domain.com/wp-admin/?nocache
.
Звучит легко? Давай сделаем это.
Отредактируйте наш метод get
в widget / cache.php
01
02
03
04
05
06
07
08
09
10
|
static function get(Provider $provider) {
if (isset($_GET[‘nocache’])) {
return false;
}
$cache_id = get_class($provider);
if (false !== $data = get_transient($cache_id)) {
return $data;
}
return false;
}
|
Пока nocache
параметр запроса nocache
, мы мгновенно возвращаем false и, следовательно, заставляем nocache
реальные данные вместо кэшированных данных.
Теперь давайте подумаем о добавлении этой функции без класса Cache. Возможно, нам придется перейти к каждой строке get_transient
и проверить там параметр запроса. Поэтому, рассмотрите возможность разбить вещи на несколько слоев при разработке вашего плагина. Не помещайте все в один файл и не копируйте код вставки снова и снова.
Теперь давайте попробуем посетить domain.com/wp-admin and domain.com/wp-admin?nocache
и заметить разную скорость.
Вот результат с ?nocache=1
добавленным к URL.
Использование cronjob для генерации кэша
Несмотря на то, что мы реализовали и использовали кеш, если кеш отсутствует, страница все еще работает медленно. Все еще нужно время, чтобы получить данные с сервера. У нас еще есть возможность улучшить cronjob. Мы можем запланировать запуск нашего плагина через определенный интервал. WordPress позволяет нам делать это через wp_schedule_event
. В идеале мы можем использовать wp_schedule_event
для планирования перехвата, который будет выполняться через определенный интервал.
Глядя на этот пример , наш плагин может запланировать перехват вызова каждые три минуты, перехватчик, в свою очередь, вызовет другую функцию для извлечения метрических данных. Данные всегда доступны в кеше и достаточно свежие.
Откройте наш основной файл плагина serverdashboard.php
и обновите метод run, включив в него новый обработчик и новый обработчик обработчиков.
01
02
03
04
05
06
07
08
09
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
|
<?php
/**
* Start to setup hook
*/
public function run() {
add_action( ‘wp_dashboard_setup’, array( $this, ‘add_dashboard_widgets’ ) );
add_action( ‘admin_enqueue_scripts’, array($this, ‘add_asset’));
add_action( ‘admin_footer’, array($this, ‘footer’));
register_activation_hook(__FILE__, array($this, ‘add_servermetric_caps’));
register_deactivation_hook(__FILE__, array($this, ‘remove_servermetric_caps’));
//New code to handle cronjob
add_filter( ‘cron_schedules’, array($this, ‘cron_3min’) );
add_action( ‘metric_generate_every_3min’, array($this, ‘generate_metric’) );
add_action( ‘init’, array($this, ‘setup_schedule’) );
}
/**
* Define a new kind of interval
* https://codex.wordpress.org/Function_Reference/wp_get_schedules
*/
function cron_3min($schedules) {
$schedules[‘3min’] = array(
‘interval’ => 3 * 60,
‘display’ => __( ‘Once every 3 minutes’ )
);
return $schedules;
}
/**
* Setup schedule for event.
* we register it to
*/
function setup_schedule() {
if ( ! wp_next_scheduled( ‘metric_generate_every_3min’ ) ) {
wp_schedule_event( time(), ‘3min’, ‘metric_generate_every_3min’);
}
}
/**
* The main function that runs on cron and
* generate data
*/
function generate_metric() {
$widget = Widget::instance();
foreach ($widget->get_provider() as $name=>$provider) {
//By calling get_content, we trigger Cache::load process.
$provider->get_content();
}
}
}
|
Во-первых, метод wp_schedule_event поддерживает только три типа повторения: ежедневно, ежечасно и дважды. Мы должны добавить новый тип повторения с фильтром wp_get_schedules .
1
2
3
4
5
|
$schedules[‘3min’] = array(
‘interval’ => 3 * 60,
‘display’ => __( ‘Once every 3 minutes’ )
);
return $schedules;
|
Мы можем настроить значение интервала на то, сколько секунд мы хотим, чтобы работа повторялась. Затем мы metric_generate_every_3min
хук metric_generate_every_3min
.
1
|
add_action( ‘metric_generate_every_3min’, array($this, ‘generate_metric’) );
|
Это наш пользовательский хук, он не существует в WordPress. Мы регистрируем дескриптор с методом generate_metric
для этого хука. Всякий раз, когда metric_generate_every_3min
хук metric_generate_every_3min
, будет выполняться generate_metric
.
В следующем операторе мы подключаемся к действию init
с setup_schedule
метода setup_schedule
чтобы проверить наличие следующего запланированного события ловушки metric_generate_every_3min
. Если он еще не определен, мы запланируем событие с помощью wp_schedule_event
, используя наши пользовательские повторения каждые три минуты для этой ловушки.
Внутри метода generate_metric
мы перебираем все доступные get_content
виджета и вызываем их метод get_content
. Делая это, мы запускаем процесс Cache::load
для этой метрики.
WordPress автоматически запускает эти запланированные события всякий раз, когда кто-то посещает ваш сайт WordPress. Он попытается найти запланированное событие, которое нужно запустить, и вызвать его.
Тем не менее, вы также можете запустить их вручную. WordPress запускает cronjob, посещая файл wp-content.php
с URL yourdomain.com/wp-cron.php?doing_wp_cron
.
Возможно, вы захотите обновить свой cronjob, чтобы добавить новую работу, которая пингует вышеуказанный URL каждую минуту
Давайте откроем ваш crontab на сервере с помощью crontab -e
и добавим в конце следующую строку:
1
|
0 * * * *wget domain.com/wp-cron.php?doing_wp_cron > /dev/null 2>&1
|
Мы использовали wget для отправки HTTP-запроса в файл wp-cron.php. Так как нас не волнует вывод и какие-либо ошибки, мы перенаправляем весь вывод в /dev/null
.
Вы можете прочитать больше о настройке этих cronjob в следующих статьях:
- http://tommcfarlin.com/wordpress-cron-jobs/
- Http: //code.tutsplus.com/articles/insights-into-wp-cron-an-introduction-to-scheduling-tasks-in-wordp …