Объективные рекомендации по разработке плагинов? [закрыто]


Запуск вики-сообщества для сбора цель лучшие практики разработки плагинов. Этот вопрос был вдохновлен комментариями @EAMann о wp-хакеры.

Идея состоит в том, чтобы совместно определить, какими могут быть объективные лучшие практики, чтобы мы могли потенциально в конечном итоге использовать их в каком-либо процессе обзора сотрудничества сообщества.

ОБНОВЛЕНИЕ: После просмотра первых нескольких ответов становится ясно, что нам нужно иметь только одну идею/предложение/передовую практику для каждого ответа, и люди должны просмотреть список, чтобы убедиться, что перед публикацией нет дубликатов.

Author: MikeSchinkel, 2010-08-23

30 answers

Используйте действия и фильтры

Если вы думаете, что люди хотели бы добавить или изменить некоторые данные: предоставьте apply_filters() перед возвращением.

P.S. Одна вещь, которую я нахожу немного разочаровывающей и к которой относится ваш вопрос, - это процент плагинов, предназначенных только для конечных пользователей, т.Е. у которых нет собственных крючков. Представьте, если бы WordPress был разработан как большинство плагинов? Это было бы негибким и очень узкоспециализированным решением.

Может быть все было бы иначе, если бы WordPress имел возможность автоматически устанавливать плагины, от которых зависели другие плагины? Как правило, мне приходится писать большую часть необходимых мне функций с нуля, потому что клиенты хотят, чтобы все было определенным образом, и доступные плагины, хотя их 90%, не позволяют мне гибко обновлять оставшиеся 10%.

Я действительно желаю, чтобы те, кто возглавляет сообщество WordPress, нашли способ гарантировать, что плагины будут вознаграждены за лучшее следование практики (такие как добавление крючков для других разработчиков), подобные хорошим ответам, вознаграждаются на сайте StackExchange.

Давайте возьмем пример из другого вопроса:

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

Связанные

 74
Author: Arlen Beiler, 2020-06-15 08:21:38

Загружайте скрипты/CSS с помощью wp_enqueue_script и wp_enqueue_style

Плагины не должны загружать /пытаться загружать дубликаты версий файлов JS/CSS, особенно jQuery и других файлов JS, включенных в ядро WP.

Плагины всегда должны использовать wp_enqueue_script и wp_enqueue_style при связывании файлов JS и CSS и никогда напрямую через теги <script>.

Связанные

 55
Author: hakre, 2020-06-15 08:21:38

Поддержка I18n

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

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

Смотрите Кодекс: I18n для разработчиков WordPress

А также эта статья: Загрузка языковых файлов WP правильно.

Начиная с WordPress 4.6+

WP 4.6 изменил порядок загрузки и проверенные местоположения, это значительно упростило задачу для разработчиков и пользователей.

Учитывая плагин с текстовым доменом "мой-плагин", WordPress теперь СНАЧАЛА будет искать файл перевода в:
/ wp-контент/языки/плагины/мой-плагин-en_US.mo

Если ему не удастся найти его там, он будет искать тот, где плагин говорит ему искать (обычно на языке pluigns' папка, если следовать кодексу):
/ wp-контент/плагины/мой-плагин/языки/мой-плагин-en_US.mo

Наконец, если языковой файл не найден, он проверит расположение по умолчанию:
/ wp-контент/языки/мой-плагин-en_US.mo

Первая проверка была добавлена в 4.6 и предоставляет пользователям определенное место для добавления языкового файла, так как раньше им нужно было знать, где разработчик добавил языковой файл, теперь пользователю просто нужно знать, какой плагин текстовый домен: /wp-контент/языки/плагины/ТЕКСТОВЫЙ ДОМЕН-ЛОКАЛЬНЫЙ.mo


Ниже приведен старый способ (не актуально с WP 4.6+)

[...]
Наконец, я хотел бы отметить, что важно загрузить пользовательские языковые файлы пользователя из WP_LANG_DIR, прежде чем загружать языковые файлы, поставляемые с плагином. Когда для одного домена загружается несколько mo-файлов, будет использоваться первый найденный перевод. Таким образом, языковые файлы, предоставляемые плагин будет служить резервным вариантом для строк, не переведенных пользователем.

public function load_plugin_textdomain()
{
    $domain = 'my-plugin';
    // The "plugin_locale" filter is also used in load_plugin_textdomain()
    $locale = apply_filters( 'plugin_locale', get_locale(), $domain );

    load_textdomain( 
            $domain, 
            WP_LANG_DIR . '/my-plugin/' . $domain . '-' . $locale . '.mo' 
    );
    load_plugin_textdomain( 
            $domain, 
            FALSE, 
            dirname( plugin_basename(__FILE__) ) . '/languages/' 
    );
}
 49
Author: Stiofan O'Connor, 2017-05-04 18:59:36

Убедитесь, что плагины Не генерируют ошибок с помощью WP_DEBUG

Всегда тестируйте свои плагины с помощью WP_DEBUG включен и в идеале должен быть включен на протяжении всего процесса разработки. Плагин не должен выдавать НИКАКИХ ошибок при включении WP_DEBUG. Это включает устаревшие уведомления и непроверенные индексы.

Чтобы включить отладку, отредактируйте файл wp-config.php так, чтобы константа WP_DEBUG была установлена в true. Увидеть Кодекс по отладке для получения более подробной информации.

 48
Author: John P Bloch, 2020-06-15 08:21:38

Сначала используйте существующие функции в ядре WordPress

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

Одним из преимуществ является то, что вы можете использовать "регистрировать устаревшие уведомления" , чтобы легко отслеживать функции, которые следует заменить. Еще одно преимущество заключается в том, что пользователи могут просматривать документацию по функциям в Кодексе и лучше понимать что делает плагин, даже если он не является опытным разработчиком PHP.

Связанные

 42
Author: hakre, 2020-06-15 08:21:38

Удаление должно удалить все данные плагина

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

Плагины могут предлагать возможность экспорта/импорта настроек, чтобы настройки можно было сохранить за пределами WordPress перед удалением.

Связанные

 35
Author: hakre, 2020-06-15 08:21:38

Предотвратить внедрение SQL с входными данными

Плагин должен очистите весь пользовательский ввод, полученный прямо или косвенно (например, через $_POST или $_GET) перед использованием входных значений для запроса базы данных MySQL.

См.: Форматирование инструкций SQL.

 34
Author: hakre, 2010-08-25 19:00:22

Префикс Всех Элементов Глобального Пространства Имен

Плагин должен правильно добавлять префиксы КО ВСЕМ элементам глобального пространства имен (константы, функции, классы, переменные, даже такие вещи, как пользовательские таксономии, типы сообщений, виджеты и т. Д.). Например, не создавайте функцию с именем init(); вместо этого назовите ее чем-то вроде jpb_init().

Его общий должен использовать префикс из трех или четырех букв перед именами или использовать функцию пространства имен PHP. Сравните: Однобуквенный префикс для класса PHP константы?

Связанные

 31
Author: hakre, 2020-06-15 08:21:38

Используйте класс и объектно-ориентированный код PHP5

Нет причин не писать чистый, объектно-ориентированный код PHP5. Поддержка PHP4 будет прекращена после следующего выпуска (WP 3.1). Конечно, вы можете добавить префикс ко всем своим именам функций, чтобы в итоге получить endlessly_long_function_names_with_lots_of_underscores, но гораздо проще просто написать простой класс и объединить все в нем. Кроме того, поместите свой класс в отдельный файл и назовите его соответствующим образом, чтобы вы могли легко расширять и поддерживать это:

// in functions.php
require 'inc/class-my-cool-plugin.php';
new MyCoolPlugin();

// in inc/class-my-cool-plugin.php
class MyCoolPlugin {
    function __construct() {
        // add filter hooks, wp_enqueue_script, etc.

        // To assign a method from your class to a WP 
        // function do something like this
        add_action('admin_menu', array($this, "admin"));
    }

    public function admin() {
        // public methods, for use outside of the class
        // Note that methods used in other WP functions 
        // (such as add_action) should be public
    }

    private function somethingelse() {
        // methods you only use inside this class
    }
}
 31
Author: Husky, 2010-09-01 14:58:59

Деактивация не должна приводить к потере данных

Плагин не должен удалите любые его данные после деактивации .

Связанные

 26
Author: MikeSchinkel, 2020-06-15 08:21:38

Включайте только те файлы, которые вам нужны...

Если вы находитесь в интерфейсе, не включайте код, относящийся к области администрирования.

 23
Author: Denis de Bernardy, 2011-01-13 22:05:25

Объявить о потере данных при удалении плагина

После удаления плагин должен попросите пользователя, чтобы он удалил свои данные, и получите подтверждение, что пользователь согласен с удалением данных, прежде чем сделать это, и плагин должен также разрешить пользователю возможность сохранить данные при удалении. (Эта идея от @EAMann.)

Связанные

 21
Author: hakre, 2020-06-15 08:21:38

Пусть имя папки плагина будет изменено

/плагины/имя плагина/{различные}

"Имя подключаемого модуля", используемое для папки, всегда должно быть изменяемым.

Обычно это решается путем определения констант и последовательного их использования во всем плагине.

Излишне говорить, что многие популярные плагины являются грешниками.

Связанные:

  • plugins_url() для удобства подключения к ресурсам, входящим в комплект плагина.
 19
Author: AndyBeard, 2011-01-10 07:39:59

Используйте встроенную обработку ошибок WordPress

Не просто return;, если какой-то пользовательский ввод был неправильным. Доставьте им некоторую информацию о том, что было сделано неправильно.

function some_example_fn( $args = array() ) 
{
    // If value was not set, build an error message
    if ( ! isset( $args['some_value'] ) )
        $error = new WP_Error( 'some_value', sprintf( __( 'You have forgotten to specify the %1$s for your function. %2$s Error triggered inside %3$s on line %4$s.', TEXTDOMAIN ), '$args[\'some_value\']', "\n", __FILE__, __LINE__ ) );

    // die & print error message & code - for admins only!
    if ( isset( $error ) && is_wp_error( $error ) && current_user_can( 'manage_options' ) ) 
        wp_die( $error->get_error_code(), 'Theme Error: Missing Argument' );

    // Elseif no error was triggered continue...
}

Одна ошибка (объект) для всех

Вы можете настроить глобальный объект ошибки для своей темы или плагина во время начальной загрузки:

function bootstrap_the_theme()
{
    global $prefix_error, $prefix_theme_name;
    // Take the theme name as error ID:
    $theme_data = wp_get_theme();
    $prefix_theme_name = $theme_data->Name;
    $prefix_error = new WP_Error( $theme_data->Name );

    include // whatever, etc...
}
add_action( 'after_setup_theme', 'bootstrap_the_theme' );

Позже вы можете добавлять неограниченное количество ошибок по требованию:

function some_theme_fn( $args )
{
    global $prefix_error, $prefix_theme_name;
    $theme_data = wp_get_theme();
    if ( ! $args['whatever'] && current_user_can( 'manage_options' ) ) // some required value not set
        $prefix_error->add( $prefix_theme_name, sprintf( 'The function %1$s needs the argument %2$s set.', __FUNCTION__, '$args[\'whatever\']' ) );

    // continue function...
}

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

function dump_theme_errors()
{
    global $prefix_error, $prefix_theme_name;

    // Not an admin? OR: No error(s)?
    if ( ! current_user_can( 'manage_options' ) ! is_wp_error( $prefix_error ) )
        return;

    $theme_errors = $prefix_error->get_error_messages( $prefix_theme_name );
    echo '<h3>Theme Errors</h3>';
    foreach ( $theme_errors as $error )
        echo "{$error}\n";
}
add_action( 'shutdown', 'dump_theme_errors' );

Дополнительную информацию вы можете найти в в этом вопросе . Связанный билет для исправления "совместной работы" WP_Error и wp_die() связан оттуда, и за ним последует другой билет. Комментарии, критика и тому подобное приветствуются.

 19
Author: kaiser, 2017-04-13 12:37:35

Минимизировать имена, добавленные в Глобальное пространство имен

Плагин должен уменьшите его влияние как можно больше, сведя к минимуму количество имен, которые он добавляет в глобальное пространство имен.

Это можно сделать, инкапсулировав функции плагина в класс или используя функцию пространства имен PHP. Добавление префиксов ко всему также может помочь, но не настолько гибко.

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

Связанные

 18
Author: hakre, 2020-06-15 08:21:38

Комментарий с использованием PHPDoc

Наилучшая практика близка к стилю PHPDoc. Если вы не используете IDE, такую как "Eclipse", вы можете просто взглянуть на руководство PHPDoc.

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

 17
Author: kaiser, 2020-06-15 08:21:38

Используйте API настроек перед добавлением опции

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

Используйте API изменений темы перед добавлением опции

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

 17
Author: kaiser, 2011-10-28 09:51:26

Защита конфиденциальности пользователей Плагинов

(Ранее: Анонимная связь API)

Если плагин взаимодействует с внешней системой или API (например, с каким-либо веб-сервисом), он должен делать это анонимно или предоставлять пользователю анонимную опцию, которая гарантирует, что никакие данные, связанные с пользователем плагина, не будут бесконтрольно передаваться второй стороне.

 16
Author: EAMann, 2010-08-23 20:17:46

Размещайте плагины на WordPress.org

Используйте SVN репозиторий , предоставленный на WordPress.org для размещения плагинов. Это упрощает процесс обновления, и если вы никогда раньше не использовали SVN, это поможет вам понять, используя его в контексте, который его оправдывает.

 15
Author: MikeSchinkel, 2020-06-15 08:21:38

Обеспечить контроль доступа с помощью разрешений

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

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

 15
Author: eddiemoya, 2020-06-15 08:21:38

Импорт/Экспорт настроек плагина

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

Импорт/экспорт улучшает удобство использования плагина.

Примером плагина, который имеет такую функциональность импорта и экспорта (а также механизм отмены), является Breadcrumb NavXT (плагин Wordpress) (полное раскрытие: там есть небольшой код, написанный мной, большая часть была сделана mtekk).

Связанные

 12
Author: hakre, 2020-06-15 08:21:38

Организуйте свой код

Всегда трудно читать код, который написан не в том порядке, в котором он выполняется. Сначала включите/требуйте, определите, wp_enqueue_style и _script и т. Д., Затем функции, необходимые плагину/теме, и, наконец, конструктор (например, экран администратора, материал, который интегрируется в тему и т. Д.).

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

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

 12
Author: kaiser, 2020-06-15 08:21:38

Умри со стилем

Умри достойным образом Все функции плагинов (и даже тем) должны использовать wp_die() в критических местах, чтобы предоставить пользователю небольшую информацию о том, что произошло. Ошибки Php раздражают и wp_die могут дать пользователю приятное сообщение о том, что плагин (или они) сделали неправильно. Кроме того, если пользователь отключил отладку, плагин просто сломается.

Использование wp_die() также помогает обеспечить совместимость ваших плагинов/тем с тестовый пакет wordpress.

Связанный:
 11
Author: hakre, 2017-04-13 12:37:38

Предоставление экранов справки для пользователей

Приятнее говорить RTFM (нажмите "Справка") в качестве ответа, чем снова и снова отвечать на вопрос.

/**
  * Add contextual help for this screen
  * 
  * @param $rtfm
  * @uses get_current_screen
  */ 
  function ContextualHelp( /*string*/ $rtfm) 
  { 
     $current_screen = get_current_screen();
     if ($current_screen->id == $this->_pageid) 
     {
        $rtfm .= '<h3>The WordPress Plugin - Screen A</h3>';
        $rtfm .= '<p>Here are some tips: donate to me ' .
     }
     return $rtfm; 
  }
add_action('contextual_help', array($this,'ContextualHelp'),1,1);

Обновление / примечание: (см. Комментарии кайзера): приведенный выше пример должен использоваться в классе

 11
Author: edelwater, 2020-06-15 08:21:38

Предлагать расширяемые формы

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

См.: API настроек

Связанные

 10
Author: hakre, 2020-06-15 08:21:38

Включать функцию всегда через хук, а не напрямую.

Пример:

  • Не используйте для включения класса плагина через новый без крючка

  • Используйте крючок plugins_loaded

    // add the class to WP                                   
    function my_plugin_start() {                                                               
        new my_plugin();   
    }                                                        
    add_action( 'plugins_loaded', 'my_plugin_start' );
    

Обновление: небольшой живой пример: Плагин-svn-магистральная страница и псевдо-пример

//avoid direct calls to this file where wp core files not present
if (!function_exists ('add_action')) {
        header('Status: 403 Forbidden');
        header('HTTP/1.1 403 Forbidden');
        exit();
}

if ( !class_exists( 'plugin_class' ) ) {
    class plugin_class {

        function __construct() {
        }

    } // end class

    function plugin_start() {

        new plugin_class();
    }

    add_action( 'plugins_loaded', 'plugin_start' );
} // end class_exists

Вы также можете загрузить через mu_plugins_loaded на многоузловой установке, см. Справочник по действиям в кодексе: http://codex.wordpress.org/Plugin_API/Action_Reference Также здесь вы видите, как включить WP с помощью этого крючка: http://adambrown.info/p/wp_hooks/hook/plugins_loaded?version=2.1&file=wp-settings.php Я использую это очень часто, и это не так сложно и рано, лучше как жесткий новый класс();

 9
Author: bueltge, 2011-02-14 21:13:29

Лицензионные плагины под лицензией, совместимой с GPL

Плагины и темы должны лицензироваться по лицензии, совместимой с WordPress. Это позволяет распространять их с WordPress в качестве "программы". Рекомендуемой лицензией является GPL. Убедитесь, что все библиотеки кода, включенные в плагин, совместимы с одной и той же лицензией.

(Это было проблемой и серьезной темой для обсуждения как в прошлом, так и настоящее время.)

 8
Author: EAMann, 2020-06-15 08:21:38

Описание вашего плагина должно точно описывать функции вашего плагина. Есть 10 рекомендуемых плагинов для публикации. Все они отображают избранные публикации, но многие из них имеют разные функции. Должно быть легко сравнить ваш плагин с аналогичными плагинами, прочитав описание.

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

 8
Author: Greg, 2010-08-30 03:41:47

Минимизировать побочные эффекты удаленных источников данных и веб-сервисов

Плагин должен Кэшируйте/защищайте веб-сервис и/или Запросы XMLRPC/SOAP через уровень кэширования/поставщика данных, если вы используете их таким образом, чтобы не делать предварительные запросы, ожидающие (медленного) ответа веб-сервиса.

Это включает загрузку RSS-канала и других страниц. Разработайте свои плагины, чтобы они запрашивали данные в фоновом режиме.

Одним из возможных ШАГОВ является (размещение в ping.fm в качестве пример): Создайте буферную таблицу, скажем: ping_fm_buffer_post( дата, время, сообщение, отправленное время, статус )

  1. Для каждого раза, когда вы хотите отправить обновление в ping.fm, добавьте его в эту таблицу.
  2. Теперь нам нужно создать плагин для обработки этих данных. Этот плагин будет запускаться через crontab для проверки каждого обновления, которое еще не отправлено
  3. Поскольку у нас есть эта таблица, мы также можем перечислить все сообщения, отправленные в ping.fm и проверьте статус каждого сообщения. На всякий случай, если есть проблема на ping.fm на стороне, мы можем повторно представить его.
 7
Author: hakre, 2010-08-30 02:53:52

Протестируйте свой плагин

Мы определенно должны иметь некоторые инструменты тестирования в нашей среде разработки плагинов.

Основываясь на этом ответе от Итана Сейферта на тестовый вопрос, следует следовать следующим рекомендациям:

  • Ваше модульное тестирование должно проверять наименьшее количество поведения, которое может выполнять класс.
  • Когда вы достигнете уровня функционального тестирования, именно здесь вы сможете протестировать свой код с помощью Wordpress зависимости.
  • В зависимости от того, что делает ваш плагин - рассмотрите возможность использования тестов на основе селена, которые проверяют наличие данных в DOM с помощью идентификаторов
 7
Author: Fernando Briano, 2020-06-15 08:21:38