Статьи

Дополнительные советы по передовому опыту в разработке WordPress

Добро пожаловать во вторую часть серии. В первой статье мы объяснили стандарты кодирования WordPress, как избежать коллизий пространств имен, комментарии в коде и некоторые основные советы по безопасности.

Сегодня мы собираемся пойти немного дальше и написать еще немного кода и изучить некоторые методы для повышения производительности и безопасности наших плагинов. Мы рассмотрим следующие темы:

  1. Как и когда следует включать мои скрипты / стили
  2. Как правильно выполнять вызовы Ajax
  3. Фильтры и действия, чтобы дать свободу вашим пользователям

Возьмите свой редактор кода и будьте готовы играть с WordPress!

Первое, что вы должны иметь в виду, это то, что WordPress имеет две замечательные функции ( wp_enqueue_script и wp_enqueue_style ), которые позволяют вам включать ваши скрипты и стили. Для этого, пожалуйста, не добавляйте их вручную в заголовок или используя wp_head действия wp_head .

Если вы используете методы WordPress, плагины для кэширования и минимизации смогут включать ваши скрипты в свои функции, вы сможете очень легко размещать их в нижнем колонтитуле или заголовке, вы сможете добавлять зависимые скрипты, а также использовать все уловки, объясненные ниже наряду с другими особенностями.

Неправильно:

1
2
3
4
add_action( ‘wp_head’ , ‘my_custom_scripts’ );
function my_custom_scripts() {
    echo ‘<script src=»src/to/my.js»></script>’;
}

Верный:

1
2
3
4
5
6
add_action( ‘wp_enqueue_scripts’, ‘my_customs_scripts’ );
function my_customs_scripts(){
    
   wp_enqueue_script( ‘script-handler’, get_template_directory_uri() . ‘/js/my.js’, array(‘jquery’), ‘1.0.0’, true );
 
}

Я не буду давать вам полное руководство о том, как использовать wp_enqueue_xxxx, так как их доступно много (и Кодекс — отличный ресурс!), И я просто пытаюсь указать, как вы должны добавлять скрипты в свои темы или плагины. ,

То, что вам нужно всегда иметь в виду, — это оставить максимально возможный след. Это означает, что вы не должны включать файлы там, где их не должно быть.

Вы можете подумать, что «это просто файл, он не повлияет на веб-сайт», и с таким мышлением это все равно, что бросить бумагу в землю в парке, потому что это всего лишь один лист бумаги, но это не так, как все работает: если все разработчики оставляют свои скрипты повсюду, конечный пользователь получит полностью раздутый сайт, и мы этого не хотим

Теперь, когда мы рассмотрели это, давайте посмотрим несколько советов о том, как включать ваши сценарии только при необходимости.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
// FRONT END ONLY
add_action( ‘wp_enqueue_scripts’, ‘my_front_customs_scripts’ );
function my_customs_scripts(){
    
   wp_enqueue_script( ‘script-handler’, get_template_directory_uri() . ‘/js/my.js’, array(‘jquery’), ‘1.0.0’, true );
 
}
 
// BACKEND ONLY
add_action( ‘admin_enqueue_scripts’, ‘my_back_customs_scripts’ );
function my_customs_scripts(){
    
   wp_enqueue_script( ‘script-handler’, get_template_directory_uri() . ‘/js/my.js’, array(‘jquery’), ‘1.0.0’, true );
 
}

Но ждать! Давайте сделаем еще один шаг и включим только те скрипты, которые вам действительно нужны. Хороший метод — сначала зарегистрировать их, а затем поставить в очередь на нужные страницы.

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
//FRONT END ONLY
add_action( ‘wp_enqueue_scripts’, ‘my_front_customs_scripts’ );
function my_customs_scripts(){
    
   wp_register_script( ‘script-handler’, get_template_directory_uri() . ‘/js/my.js’, array(‘jquery’), ‘1.0.0’, true );
    
   if( is_page(‘my-page’) ) {
        wp_enqueue_script( ‘script-handler’ );
   }
   // Be creative to include files only when needed
   // if( is_single() )
   // if( is_home() )
   // if( ‘cpt-name’ == get_post_type() )
 
}
 
//BACKENDEND ONLY
add_action( ‘admin_enqueue_scripts’, ‘my_back_customs_scripts’ );
function my_customs_scripts( $hook ){
    
   wp_register_script( ‘script-handler’, get_template_directory_uri() . ‘/js/my.js’, array(‘jquery’), ‘1.0.0’, true );
    
   //To include it only when editing a post
   if( ‘edit.php’ == $hook ) {
        wp_enqueue_script( ‘script-handler’ );
    }
     
    // If you added an options page like this
    // $plugin_screen_id = add_options_page(…)
    // you can do
    $screen = get_current_screen();
    if ( $plugin_screen_id == $screen->id ) {
        wp_enqueue_script( ‘script-handler’ );
    }
 
}
/* Another way to use screen id */
add_action( ‘admin_print_styles-‘ . $plugin_screen_id, ‘my_back_customs_scripts’ );
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
//FRONT END ONLY
add_action( ‘wp_enqueue_scripts’, ‘my_front_customs_scripts’ );
function my_customs_scripts(){
    
    wp_register_script( ‘script-handler’, get_template_directory_uri() . ‘/js/my.js’, array(‘jquery’), ‘1.0.0’, true );
    
    // if you need a script to be included for a shortcode
    // Don’t add it everywhere
    // Instead you can include it only when needed
    global $post;
     
    if( is_a( $post, ‘WP_Post’ ) && has_shortcode( $post->post_content, ‘custom-shortcode’) ) {
        wp_enqueue_script( ‘script-handler’);
    }
 
}

Хотя другие фрагменты кода применимы как к сценариям, так и к стилям, следующее будет работать только с wp_enqueue_style (по крайней мере, на данный момент).

01
02
03
04
05
06
07
08
09
10
11
12
//FRONT END ONLY
add_action( ‘wp_enqueue_scripts’, ‘my_front_customs_styles’ );
function my_front_customs_styles(){
    
    wp_register_style( ‘my-plugin-css’, plugins_url( ‘my-plugin/css/plugin.css’ ) );
    
    // Let’s include this css only for old (and crappy) browsers
    wp_enqueue_style( ‘my-plugin-css’ );
    global $wp_styles;
    $wp_styles->add_data(‘my-plugin-css’, ‘conditional’, ‘lte IE 9’);
 
}

Вы можете увидеть еще несколько примеров в Кодексе. Еще один отличный пример, который вы можете использовать для запуска всех своих плагинов — это WordPress Plugin Boilerplate . Взгляните на код, чтобы увидеть, как включены скрипты и стили. Плагин Wpfavs (на основе WordPress Plugin Boilerplate) — это хороший пример того, как создать плагин для бэкэнда WordPress.

В этой теме я поделюсь некоторыми вредными привычками, которые я часто видел при работе с Ajax в WordPress, и их можно разделить на следующие предложения:

  • Ajax-вызовы не должны выполняться напрямую в файл
  • Ajax-вызовы должны использовать значение nonce
  • Проверьте наличие прав пользователя, если это необходимо
  • Переменные JavaScript должны быть включены в wp_localize_script

Я знаю, что jQuery заставляет Ajax вызывать ajax.php пирога, и мы можем просто создать файл с именем ajax.php , включить в него wp-load.php и выполнить там наш Ajax. Но это не «путь WordPress» — он не ориентирован на будущее. Более того, он менее безопасен, и вы упустите множество функций WordPress.

Правильный путь заключается в использовании wp_ajax_my_action действий wp_ajax_my_action и wp_ajax_nopriv_my_action . Основное различие между ними заключается в том, что первый используется для зарегистрированных пользователей, а второй — для не зарегистрированных пользователей.

Обратите внимание, что «my_action» должно быть изменено для имени вашего действия. Мы увидим, как это работает через мгновение.

Давайте посмотрим все это на простом примере с небольшим количеством кода и воображения. Давайте представим, что мы хотим отобразить 5 сообщений, когда какой-либо пользователь (вошел или нет) нажимает на кнопку. Мы собираемся назвать это действие cool_ajax_example , поэтому давайте начнем добавлять функции обратного вызова Ajax, которые будут возвращать данные.

Вы можете включить этот код в ваши functions.php или внутри вашего плагина.

1
2
3
4
5
6
7
//First we add the actions hooks
add_action(‘wp_ajax_cool_ajax_example’, ‘cool_ajax_example_callback’ );
add_action(‘wp_ajax_nopriv_cool_ajax_example’, ‘cool_ajax_example_callback’ );
 
function cool_ajax_example_callback() {
    …
}

Как видите, обе ловушки используют одну и ту же функцию обратного вызова, которая будет возвращать данные. Также обратите внимание, что имя нашего действия находится в конце имени ловушки wp_ajax_ cool_ajax_example

Это очень важно написать название действия прямо везде, или это не сработает вообще.

Прежде чем мы продолжим с функцией обратного вызова, давайте перейдем к jQuery, необходимому для вызова Ajax. Скрипт jQuery сработает, когда мы нажмем простую кнопку HTML, и нам нужно отправить этот запрос в файл admin-ajax.php который является скриптом, который обрабатывает все запросы AJAX в WordPress. Также нам нужно добавить одноразовый номер, как мы уже говорили, что мы хотим сделать его безопасным, поэтому здесь вступает в действие функция wp_localize_script .

Если вы правильно включили свои сценарии, как объяснялось в начале этой статьи, у вас есть имя обработчика сценариев (в наших примерах выше ‘script-handler’), поэтому давайте использовать его для передачи наших значений PHP в наш файл javascript. Вы можете включить этот бит кода сразу после функции wp_enqueue_function используемой для включения JavaScript.

1
2
3
4
5
6
7
8
wp_localize_script(
    ‘script-handler’,
    ‘MyVarName’,
    array(
        ‘ajax_url’ => admin_url( ‘admin-ajax.php’ ),
        ‘nonce’ => wp_create_nonce( ‘return_posts’ )
    )
);

Как вы можете видеть, wp_localize_script — это довольно простой способ передать любую переменную PHP в наши файлы JavaScript, и он напечатает действительный xhtml из-за тегов <![CDATA[ . Приведенный выше код будет напечатан в заголовке, когда будет загружен файл JavaScript с script-handler качестве имени, и он будет выглядеть примерно так:

1
2
3
<script type=»text/javascript»>/* <![CDATA[ */
var myVarName = {«ajax_url»:»http:\/\/www.tutsplus.com\/wp-admin\/admin-ajax.php»,»nonce»:»dsfsdf123r»};
/* ]]> */</script>

Теперь пришло время создать наш файл JavaScript, назовем его my.js и он будет выглядеть примерно так:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
(function( $ ) {
    $(function() {
     
        $(‘#button’).click(function(e){
            e.preventDefault();
         
            $.ajax({
                url: myVarName.ajax_url,
                data: {
                    action: ‘cool_ajax_example’,
                    nonce : myVarName.nonce },
                    success: function( response ) {
                                $(‘#response-container’).html( response );
                    },
                    type: «POST»,
            });
         
        });
     
    });
})( jQuery );

Обратите внимание, как мы используем nonce и ajax_url которые мы передали с помощью wp_localize_script . Также убедитесь, что мы передаем значение POST, называемое «action», которое соответствует имени действия, которое мы использовали в wp_ajax .

Теперь пришло время завершить нашу функцию обратного вызова. Первое, что нам нужно сделать, это проверить правильность одноразового номера, а затем мы можем вернуть несколько сообщений.

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
function cool_ajax_example_callback() {
    
    $nonce = $_POST[‘nonce’];
    //The first thing we do is check the nonce and kill the script if wrong
    if ( ! wp_verify_nonce( $nonce, ‘return_posts’ ) )
        die ( ‘Wrong nonce!’);
     
    $args = array(
        ‘post_type’ => ‘post’,
        ‘post_status’ => ‘publish’,
        ‘posts_per_page’ => 5,
    );
    // The Query
    $the_query = new WP_Query( $args );
 
    // The Loop
    if ( $the_query->have_posts() ) {
        echo ‘<div class=»myposts»>’;
        while ( $the_query->have_posts() ) {
            $the_query->the_post();
            echo ‘<h3>’ .
        }
        echo ‘</div>’;
    } else {
        echo ‘Posts not found’;
    }
    /* Restore original Post Data */
    wp_reset_postdata();
     
    // don’t forget this
    // We are doing a simple call we don’t want anything else to run
    die();
}

Если вам нужно что-то более сложное, например, удаление сообщения, всегда проверяйте права пользователей, как я уже упоминал в начале этой темы. Например, если вы хотите, чтобы только администраторы выполняли определенные действия, вы можете сделать в своем скрипте что-то вроде:

1
2
3
4
5
if( current_user_can( ‘administrator’ ) ) {
  
    wp_delete_post( $postid, $force_delete );
 
}

Со всеми советами выше вы теперь являетесь мастером в WordPress Ajax, и вы можете выполнять любые действия, которые вы хотите. Попробуйте поиграть с приведенным выше и настроить его под свои нужды. Лично мне нравится использовать тип данных json и я выполняю echo json_encode() вместо того, чтобы делать простые эхо для моих сценариев, но это другой вопрос.

Цель этого раздела не в том, чтобы научить вас, как работают фильтры и действия, по этой теме есть отличные учебники , которые объясняют это очень подробно. Я собираюсь объяснить вам здесь, почему вы должны добавить фильтры и действия в свои плагины и показать вам несколько примеров для облегчения понимания.

Но сначала давайте сделаем введение в эти понятия:

  • Хуки: ловушка действий добавляется в определенный момент вашего плагина, обычно вокруг важных действий (например, до контента, после контента). Любой пользователь может затем «подключиться» к нему с помощью функций для выполнения своего кода в этой точке. Когда запускается ловушка действий, все функции, которые подключены или «подключены» к нему, также будут работать.
  • Фильтры: крючок фильтра также помещен в ваш плагин для других функций для привязки. В этом случае фильтры позволяют манипулировать данными или изменять их перед использованием. Таким образом, вы обычно размещаете его с переменными, которыми вы хотите позволить пользователям манипулировать.

Проверьте Plugin API для получения дополнительной информации о хуках действий и фильтрах.

Это очень просто: потому что это делает ваш плагин лучше. Таким образом, разработчики и обычные пользователи вместе смогут расширять, адаптировать или улучшать ваш плагин за пределы его первоначальной цели, не затрагивая его суть.

Взять, к примеру, плагин электронной коммерции. Благодаря хукам и фильтрам вы можете создавать новые плагины, которые к ним подключаются, например, новые платежные шлюзы, функции доставки и многое другое.

Не сходите с ума, добавляя действия и фильтры везде. В начале вы найдете это немного сложным или раздражающим, поэтому попробуйте подумать, будто вы другой разработчик, глядя на новый плагин, и спросите себя: «Мне нужен здесь хук действия?». Кроме того, огромный процент действий и фильтров будут добавляться по требованию, как только вы начнете получать запрос в службу поддержки (да, вы всегда получаете их!) Или отзывы своих пользователей.

Как и все в жизни, как только это станет привычкой, вы очень четко увидите, куда их включить.

Несколько рекомендаций о том, где включать фильтры:

  • Когда массивы настроены, рекомендуется добавить фильтр, чтобы пользователи могли их изменять.
  • Когда объекты данных настроены, происходит то же самое. Вы можете разрешить пользователям изменять объект перед его использованием.
  • Когда строки данных настроены, вы можете добавить фильтры, чтобы позволить пользователям изменять их.

Давайте используем функцию обратного вызова, использованную в этой статье, чтобы увидеть пример рекомендаций, приведенных выше. Для создания фильтруемых переменных в этом случае мы используем apply_filters()

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
function cool_ajax_example_callback() {
    
    $nonce = $_POST[‘nonce’];
    //The first thing we do is check the nonce and kill the script if wrong
    if ( ! wp_verify_nonce( $nonce, ‘return_posts’ ) ) {
        die ( ‘Wrong nonce!’ );
    }
     
    $args = array(
        ‘post_type’ => ‘post’,
        ‘post_status’ => ‘publish’,
        ‘posts_per_page’ => 5,
    );
    // The Query
    $the_query = new WP_Query( apply_filters( ‘cool_ajax_query’, $args ) );
 
    // The Loop
    if ( $the_query->have_posts() ) {
        echo ‘<div class=»myposts»>’;
        while ( $the_query->have_posts() ) {
            $the_query->the_post();
            echo ‘<h3>’ .
        }
        echo ‘</div>’;
    } else {
        echo ‘Posts not found’;
    }
    /* Restore original Post Data */
    wp_reset_postdata();
     
    // don’t forget this
    // We are doing a simple call we don’t want anything else to run
    die();
}

Как вы можете видеть, я добавил фильтр в переменную $args который будет запускаться непосредственно перед WP_Query как WP_Query запрос. С помощью простого фильтра любой пользователь может, например, изменить количество возвращаемых сообщений.

1
2
3
4
5
function wpt_alter_coolajax_query( $args ) {
    $args[‘posts_per_page’] = 10;
    return $args;
}
add_filter( ‘cool_ajax_query’, ‘wpt_alter_coolajax_query’ );

Вы можете использовать фильтры в разных сценариях, просто используйте свое воображение. Например, в моем плагине WordPress Social Invitations я позволил пользователям менять всплывающую таблицу стилей с помощью фильтра, если они используют совершенно другой стиль.

1
<link rel=»stylesheet» href=»<?php echo apply_filters(‘collector_css_file’,plugins_url( ‘assets/css/collector.css?v=’.$this->WPB_VERSION, __FILE__ ));?>» type=»text/css» media=»all»>

Или в этом случае, когда плагин отправляет электронные письма, я даю возможность изменить «Из электронной почты», wp_mail() будет использовать wp_mail() .

1
2
3
4
5
6
7
8
9
function get_from_email() {
 
    if ( isset( $this->_user_data ) ) {
        return apply_filters( ‘wsi_from_email’, $this->_user_data->user_email );
    }
  
    return apply_filters( ‘wsi_from_email’, get_bloginfo( ‘admin_email’ ) );
     
}

Когда дело доходит до действий, это немного меняется. Вы хотите добавить ловушки действий в следующих сценариях (не ограничиваясь ими):

  • перед выполнением задания,
  • после того, как задачи выполнены,
  • во время выполнения задачи, например, для расширения разметки.

Для создания этих подключаемых областей мы используем do_action() . Давайте применим их в нашем примере.

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
function cool_ajax_example_callback() {
    
    $nonce = $_POST[‘nonce’];
    //The first thing we do is check the nonce and kill the script if wrong
    if ( ! wp_verify_nonce( $nonce, ‘return_posts’ ) )
        die ( ‘Wrong nonce!’);
     
    $args = array(
        ‘post_type’ => ‘post’,
        ‘post_status’ => ‘publish’,
        ‘posts_per_page’ => 5,
    );
    // The Query
    $the_query = new WP_Query( apply_filters( ‘cool_ajax_query’, $args ) );
 
    // The Loop
    if ( $the_query->have_posts() ) {
     
        // we run the hook before the loop is proccesed
        do_action( ‘cool_ajax_before_loop’, get_the_ID() );
     
        echo ‘<div class=»myposts»>’;
         
        while ( $the_query->have_posts() ) {
         
            $the_query->the_post();
             
            // we run the hook before the title is printed
            do_action( ‘cool_ajax_before_title’, get_the_ID() );
             
            echo ‘<h3>’ .
             
            // we run the hook after the title is printed
            do_action( ‘cool_ajax_after_title’, get_the_ID() );
        }
         
        echo ‘</div>’;
         
        // we run the hook after the loop is proccesed
        do_action( ‘cool_ajax_after_loop’, get_the_ID() );
         
    } else {
        echo ‘Posts not found’;
    }
    /* Restore original Post Data */
    wp_reset_postdata();
     
    // don’t forget this
    // We are doing a simple call we don’t want anything else to run
    die();
}

Как вы можете видеть, я get_the_ID() один аргумент get_the_ID() с помощью get_the_ID() . Любая функция, которая подключается к нашему обработчику действий, сможет использовать этот аргумент. Давайте посмотрим несколько примеров:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
/**
* Show post featured image before title
*/
function wpt_show_post_image( $post_id ) {
    echo get_the_post_thumbnail( $post_id, ‘thumbnail’ );
}
add_action( ‘cool_ajax_before_title’, ‘wpt_show_post_image’ );
 
/**
* Show post categories after title
*/
function wpt_show_post_cats( $post_id ) {
    echo get_the_category_list( », », $post_id );
}
add_action( ‘cool_ajax_after_title’, ‘wpt_show_post_cats’ );

Также вы можете использовать do_action() для запуска других действий вместо добавления новой разметки, как в примере выше. Например, в WordPress Social Invitations у меня есть ловушка действий, которая срабатывает при каждой отправке сообщения. Затем с помощью плагина myCRED я могу подключить действие, чтобы дать очки пользователю, который только что отправил сообщение.

Как видите, добавление хуков и фильтров не только пойдет на пользу вашему плагину, но и другим разработчикам и пользователям. Так почему бы не начать добавлять некоторые фильтры и действия вокруг?

Сегодня мы узнали, как включать скрипты и стили, как использовать Ajax-вызовы в WordPress, а также некоторые основные советы по фильтрации и действиям. У нас уже есть много информации для разработки хорошего плагина, и теперь я могу сказать, что эти серии близки к концу.

В следующей и финальной статье я собираюсь поговорить о интернационализации, отладке и документации, чтобы подвести итог тому, что я считаю наиболее важными при разработке плагина.