Melhores práticas recomendadas para desenvolvimento de plug-ins? [fechadas]

128

Iniciando um wiki da comunidade para coletar as melhores práticas do objetivo para o desenvolvimento de plug-ins. Esta questão foi inspirada nos comentários da @ EAMann sobre wp-hackers .

A ideia é colaborar em quais objetivos as melhores práticas podem ser, para que possamos usá-las eventualmente em algum processo de revisão de colaboração da comunidade.

ATUALIZAÇÃO: Depois de ver as primeiras respostas, fica claro que precisamos ter apenas uma idéia / sugestão / melhor prática por resposta e as pessoas devem rever a lista para garantir que não haja cópias antes postagem.

    
por MikeSchinkel 17.02.2011 / 17:29
fonte

37 respostas

66

Use ações e filtros

Se você acha que as pessoas gostariam de adicionar ou alterar alguns dados: forneça apply_filters () antes de retornar .

  

P.S. Uma coisa que acho um pouco decepcionante e que os endereços das suas perguntas são a porcentagem de plugins projetados apenas para usuários finais, ou seja, que não possuem ganchos próprios. Imagine se o WordPress fosse projetado como a maioria dos plugins? Seria inflexível e uma solução muito nicho.

     

Talvez as coisas fossem diferentes se o WordPress tivesse a capacidade de instalar plugins de que outros plugins dependessem? Como normalmente eu tenho que escrever muito da funcionalidade que preciso do zero porque os clientes querem as coisas de uma certa maneira e os plugins disponíveis, enquanto 90% lá, não me permitem a flexibilidade de atualizar os 10% restantes. p>      

Eu realmente gostaria que os líderes da comunidade WordPress identificassem uma maneira de garantir que os plugins sejam recompensados por seguir as melhores práticas (como adicionar ganchos para outros desenvolvedores), assim como boas respostas são recompensadas em um site do StackExchange.

Vamos dar um exemplo em outra pergunta :

  

Exemplo: eu quero fazer algo no meu plugin quando alguém retweets um artigo. Se houvesse um gancho personalizado em qualquer plug-in retweet popular que eu pudesse ligar e disparar, seria ótimo. Não existe, então eu posso modificar o seu plugin para incluí-lo, mas isso só funciona para a minha cópia, e eu não quero tentar redistribuir isso.

Relacionado

por Arlen Beiler 13.04.2017 / 14:37
fonte
53

Carregar Scripts / CSS com wp_enqueue_script e wp_enqueue_style

Os plug-ins não devem carregar / tentar carregar versões duplicadas de arquivos JS / CSS, especialmente jQuery e outros arquivos JS incluídos no WP Core.

Os plug-ins devem sempre usar wp_enqueue_script e wp_enqueue_style ao vincular arquivos JS e CSS e nunca diretamente via <script> tags.

Relacionado

por hakre 13.04.2017 / 14:37
fonte
49

suporte ao i18n

Todas as sequências de saída devem ser vinculadas a um domínio de texto apropriado para permitir a internacionalização pelas partes interessadas, mesmo que o desenvolvedor não tenha interesse em traduzir seu próprio plug-in.

Observe que é muito importante carregar os arquivos de idioma durante a ação init para que o usuário possa entrar na ação.

Veja o Codex: I18n para desenvolvedores do WordPress

E também este artigo: Carregando corretamente os arquivos de idioma do WP .

Desde o WordPress 4.6 +

O WP 4.6 alterou a ordem de carregamento e os locais, o que facilitou muito para desenvolvedores e usuários.

Considerando um plugin com um textdomain 'meu-plugin', o WordPress irá agora procurar um arquivo de tradução em: /wp-content/languages/plugins/my-plugin-en_US.mo

Se ele não encontrar um, ele procurará um no qual o plugin diz para procurar (normalmente na pasta 'idioma' do pluigns se seguir o codex): / wp-content / plugins /my-plugin/languages/my-plugin-en_US.mo

Por fim, se nenhum arquivo de idioma for encontrado, ele verificará o local padrão de: /wp-content/languages/my-plugin-en_US.mo

A primeira checagem foi adicionada na versão 4.6 e dá aos usuários um lugar definido para adicionar um arquivo de idioma, já que antes eles precisariam saber onde o desenvolvedor adicionou o arquivo de idioma, agora o usuário só precisa saber o textdomain do plugin: /wp-content/languages/plugins/TEXTDOMAIN-LOCAL.mo

Abaixo está o caminho antigo (Não relevante desde o WP 4.6 +)

  

[...]
  Finalmente, gostaria de salientar que é importante carregar arquivos de idioma de usuário personalizados de WP_LANG_DIR antes de carregar os arquivos de idioma que acompanham o plug-in . Quando vários arquivos mo são carregados para o mesmo domínio, a primeira tradução encontrada será usada. Dessa forma, os arquivos de idioma fornecidos pelo plug-in servirão como um substituto para cadeias não traduzidas pelo usuário.

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/' 
    );
}
    
por Stiofan O'Connor 04.05.2017 / 20:59
fonte
45

Certifique-se de que os plug-ins não gerem erros com WP_DEBUG

Sempre teste seus plug-ins com WP_DEBUG ativado e idealmente ativá-lo durante todo o processo de desenvolvimento. Um plugin não deve lançar nenhum erro com WP_DEBUG on. Isso inclui avisos preteridos e índices não verificados.

Para ativar a depuração, edite o arquivo wp-config.php para que a constante WP_DEBUG seja definida como true . Consulte o Codex na depuração para obter mais detalhes.

    
por John P Bloch 25.08.2010 / 22:13
fonte
40

Primeiro, use as funções existentes no WordPress Core

Se você puder: use as funções existentes incluídas no núcleo do WordPress em vez de escrever as suas próprias. Somente desenvolva funções PHP personalizadas quando não houver uma função pré-existente apropriada no núcleo do WordPress.

Um benefício é que você pode usar "avisos obsoletos de log" para monitorar facilmente as funções que devem ser substituídas. Outro benefício é que os usuários podem visualizar a documentação da função no Codex e entender melhor o que o plug-in faz, mesmo que não sejam um desenvolvedor PHP experiente.

Relacionado

por hakre 13.04.2017 / 14:37
fonte
33

Evitar a injeção de SQL com dados de entrada

Um plugin deve limpar todas as entradas do usuário recuperadas direta ou indiretamente (por exemplo, via $_POST ou $_GET ) antes de usar valores de entrada para consultar o banco de dados MySQL. / p>

Veja: Formatando instruções SQL .

    
por hakre 25.08.2010 / 21:00
fonte
33

A desinstalação deve remover todos os dados de um plug-in

Ao ser removido de uma instalação do WordPress, um plug-in deve excluir todos os arquivos, pastas, entradas de banco de dados e tabelas que ele criou, bem como os valores de opção criados .

Os plug-ins podem oferecer uma opção para exportar / importar configurações, para que as configurações possam ser salvas fora do WordPress antes da exclusão.

Relacionado

por hakre 13.04.2017 / 14:37
fonte
30

Use um código PHP5 orientado a classes e objetos

Não há razão para não escrever código PHP5 limpo e orientado a objetos. O suporte PHP4 será eliminado após o próximo lançamento (WP 3.1). É claro que você pode prefixar todos os nomes de suas funções para que acabem com endlessly_long_function_names_with_lots_of_underscores, mas é muito mais fácil escrever apenas uma classe simples e agrupar tudo nela. Além disso, coloque sua turma em um arquivo separado e nomeie-a de acordo para poder estendê-la e mantê-la facilmente:

// 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
    }
}
    
por Husky 01.09.2010 / 16:58
fonte
29

Prefixo todos os itens do namespace global

Um plugin deve prefixar corretamente TODOS os itens do namespace global (constantes, funções, classes, variáveis, até mesmo coisas como taxonomias customizadas, tipos de postagens, widgets, etc.). Por exemplo, não crie uma função chamada init() ; em vez disso, nomeie-o como jpb_init() .

É comum usar um prefixo de três ou quatro letras na frente dos nomes ou fazer uso do PHP Recurso Namespace . Compare: Prefixo de letra única para constantes de classe PHP?

Relacionado

por hakre 23.05.2017 / 14:40
fonte
25

A desativação não deve provocar perda de dados

Um plug-in não deve excluir nenhum de seus dados após a desativação .

Relacionado

por MikeSchinkel 13.04.2017 / 14:37
fonte
23

Inclua apenas arquivos de que você precisa ...

Se você estiver no front end, não inclua o código relacionado à área do administrador.

    
por Denis de Bernardy 13.01.2011 / 23:05
fonte
21

Anunciar perda de dados na desinstalação de plug-ins

Após a desinstalação , um plug-in deve solicitar que um usuário exclua seus dados e receba uma confirmação de que o usuário está autorizado a excluir os dados antes de fazer isso e um plugin deve também permitir ao usuário a opção de manter os dados após a desinstalação. (Esta ideia de @EAMann.)

Relacionado

por hakre 13.04.2017 / 14:37
fonte
19

Permitir que o nome da pasta do plugin seja alterado

/ plugins / pluginname / {various}

O "pluginname" usado para a pasta deve ser sempre alterável.

Normalmente, isso é tratado definindo constantes e consistentemente usando-as em todo o plug-in.

Escusado será dizer que muitos plugins populares são pecadores.

Relacionado:

  • plugins_url() para facilitar a vinculação a recursos, incluídos no plug-in.
por AndyBeard 10.01.2011 / 08:39
fonte
18

Use o WordPress (embutido) Tratamento de erros

Não apenas return; se alguma entrada do usuário estiver errada. Entregue-lhes algumas informações sobre o que foi feito de errado.

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...
}

Um erro (objeto) para todos

Você pode configurar um objeto de erro global para o seu tema ou plug-in durante o bootstrap:

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' );

Mais tarde, você pode adicionar erros ilimitados sob demanda:

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...
}

Depois, você pode buscá-los no final do seu tema. Dessa forma, você não interrompe a renderização da página e ainda pode gerar todos os erros para desenvolver

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' );

Você pode encontrar mais informações em este Q . Um ticket relacionado para corrigir o "trabalho em conjunto" de WP_Error e wp_die() está vinculado a partir dele e outro ticket será exibido. Comentários, críticas e tal é apreciado.

    
por kaiser 13.04.2017 / 14:37
fonte
17

Minimizar os nomes adicionados ao espaço de nomes global

Um plugin deve reduzir o impacto ao máximo minimizando o número de nomes adicionados ao namespace global .

Isso pode ser feito encapsulando as funções do plug-in em uma classe ou usando o recurso namespaces do PHP . Prefixar tudo pode ajudar também, mas não é tão flexível.

Próximo a funções e classes, um plugin não deve introduzir variáveis globais. O uso de classes normalmente os torna obsoletos e simplifica a manutenção do plug-in.

Relacionado

por hakre 13.04.2017 / 14:37
fonte
16

Proteger Privacidade de Usuários de Plug-in

(Anteriormente: comunicação anônima da API)

Se um plug-in se comunica com um sistema externo ou API (por exemplo, algum Webservice), deve fazê-lo anonimamente ou fornecer ao usuário uma opção anônima que garanta que nenhum dado relacionado ao usuário do plugin vaze para um segundo festa descontrolada.

    
por EAMann 23.08.2010 / 22:17
fonte
16

Comente usando PhpDoc

A prática recomendada está próxima do estilo PhpDoc. Se você não usa uma IDE como "Eclipse", pode dar uma olhada no PhpDoc Manual .

Você não precisa saber exatamente como isso funciona. Os desenvolvedores profissionais podem ler o código de qualquer maneira e só precisam disso como um resumo. Os codificadores e usuários do hobby podem apreciar a maneira como você explica isso no mesmo nível de conhecimento.

    
por kaiser 25.08.2010 / 22:00
fonte
16

Use a API de configurações antes de add_option

Em vez de adicionar opções ao banco de dados por meio da função add_option, você deve armazená-las como uma matriz usando a API de configurações cuida de tudo para você.

Use a API de modificação de temas antes de add_option

A API de modificações é uma construção simples e segura, que permite adicionar e recuperar opções. Tudo é salvo como valor serializado em seu banco de dados. Fácil, seguro & simples.

    
por kaiser 28.10.2011 / 11:51
fonte
14

Plugins do Host no WordPress.org

Use o repositório do SVN fornecido no WordPress.org para hospedagem de plugins. Isso facilita a atualização da experiência do usuário e, se você nunca usou o SVN anteriormente, ele faz com que você realmente entenda, usando-o em um contexto que o justifique.

    
por MikeSchinkel 25.08.2010 / 21:45
fonte
14

Fornecer controle de acesso usando permissões

Em muitos casos, os usuários podem não querer que todos tenham acesso a áreas criadas por seu plug-in, especialmente com plug-ins que realizam várias operações complexas. Uma única verificação de capacidade codificada pode não ser suficiente.

No mínimo, tenha verificações de capacidade apropriadas para todos os diferentes tipos de procedimentos para os quais seu plugin pode ser usado.

    
por eddiemoya 25.08.2010 / 21:47
fonte
12

Configurações do plug-in de importação / exportação

Não é comum em plugins, mas se o seu plugin tem (algumas) configurações, deve fornecer Import / Export de dados como configuração e entrada do usuário .

Importar / Exportar melhora a usabilidade de um plugin.

Um exemplo de plugin com essa funcionalidade de importação e exportação (e também um mecanismo de desfazer) é Breadcrumb NavXT ( Plugin Wordpress) (divulgação completa: algum pequeno código meu lá dentro, a maioria foi feita por mtekk).

Relacionado

por hakre 13.04.2017 / 14:37
fonte
12

Organize seu código

É difícil ler código que não está escrito na ordem em que foi executado. Primeiro inclua / require, define, wp_enqueue_style & _script, etc., então as funções que o plugin / theme precisa e, finalmente, o construtor (ex. tela admin, coisas que se integram no tema, etc.).

Tente separar itens como css e js em suas próprias pastas. Também tente fazer isso com funções que são apenas ajudantes, como niveladores de matriz e similares. Manter o arquivo "principal" limpo e fácil de ler é uma maneira que ajuda os usuários, desenvolvedores e você, quando você tenta atualizar em um ano e não vê o código por mais tempo.

Também é bom ter uma estrutura que você repita com frequência, para que você sempre encontre o caminho. Desenvolver em uma estrutura conhecida em diferentes projetos lhe dará tempo para torná-la melhor e mesmo que seu cliente mude para outro desenvolvedor, você nunca ouvirá "ele deixou um caos". Isso constrói sua reputação e deve ser uma meta de longo prazo.

    
por kaiser 06.01.2011 / 22:12
fonte
11

Morra com estilo

morre de maneira decente Todas as funções de plugins (e até temas) devem usar wp_die() em lugares críticos para oferecer ao usuário um pouco de informação sobre o que aconteceu. Erros de php são irritantes e wp_die pode dar ao usuário uma mensagem estilizada sobre o que o plugin (ou eles) fez errado. Além disso, se o usuário tiver depuração desativada, o plug-in será interrompido.

Usar wp_die() também ajuda seus plugins / temas a serem compatíveis com o wordpress testsuite .

Relacionado:
por hakre 13.04.2017 / 14:37
fonte
10

Oferecer formulários extensíveis

Quando um plugin oferece a possibilidade de inserir dados, ele deve sempre ter um gancho no final, logo antes do botão "enviar" e / ou "redefinir", para que os desenvolvedores possam estender facilmente o formulário com não apenas campos, mas botões também.

Veja: API de configurações

Relacionado

por hakre 13.04.2017 / 14:37
fonte
10

Fornecer telas de ajuda para usuários

É melhor dizer RTFM (clique em ajuda) como resposta do que ter que responder a pergunta várias vezes.

/**
  * 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);

update / note: (veja os comentários do kaiser): o exemplo acima deve ser usado em uma classe

    
por edelwater 04.12.2013 / 11:09
fonte
9

incluir função sempre via gancho, não diretamente.

Exemplo:

  • Não use para incluir a classe do plugin via new sem hook

  • Use o gancho plugins_loaded

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

Atualização: um pequeno exemplo ao vivo: Plugin-svn-trunk-page e um pseudo exemplo

//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

Você também pode carregar via mu_plugins_loaded em multisite-install, veja o codex para referência de ação: enlace Também aqui você vê, como inlcude wP com este gancho: enlace Eu uso isso com muita freqüência e não é tão difícil e cedo, melhor como uma nova classe difícil ();

    
por bueltge 14.02.2011 / 22:13
fonte
8

Plugins de Licença sob uma Licença Compatível com GPL

Plug-ins e temas devem ser licenciados sob uma licença compatível com o WordPress. Isso permite que eles sejam redistribuídos com o WordPress como um "programa". Uma licença recomendada é a GPL . Tome cuidado para que todas as bibliotecas de código incluídas no plug-in sejam compatíveis com a mesma licença.

(Isso tem sido um problema e sério ponto de debate tanto no passado como present .)

    
por EAMann 13.04.2017 / 14:37
fonte
8

A descrição do seu plugin deve detalhar com precisão as funções do seu plugin. Existem 10 plugins de post em destaque. Todos exibem posts em destaque, mas muitos possuem recursos diferentes. Deve ser fácil comparar o seu plugin com plugins similares lendo a descrição.

Você deve evitar se gabar sobre a simplicidade do seu plug-in, a menos que seja realmente básico. Você deve incluir links úteis na descrição, como o link para as configurações.

    
por Greg 30.08.2010 / 05:41
fonte
7

Minimize os efeitos colaterais de fontes de dados remotas e serviços Web

Um plug-in deve Atendimento de cache / escudo e / ou solicitações XMLRPC / SOAP por meio de uma camada de provedor de dados / armazenamento em cache se você usá-los por isso, para não fazer solicitações antecipadas à espera de uma resposta (lenta) ao serviço da Web.

Isso inclui o download de feeds RSS e outras páginas. Crie seus plugins para solicitar dados em segundo plano.

Um possível STEP é (Leve a postagem para o ping.fm como exemplo): Crie uma tabela de buffer, digamos: ping_fm_buffer_post ( data, hora, mensagem, submitted_time, status )

  1. Para cada vez que você quiser enviar uma atualização para o ping.fm, adicione-a a esta tabela.
  2. Agora, precisamos criar um plug-in para lidar com esses dados. Este plugin será executado via crontab para verificar todas as atualizações que ainda não foram enviadas
  3. Como temos essa tabela, também podemos listar todas as mensagens enviadas ao ping.fm e verificar o status de cada postagem. Apenas no caso de haver problemas no lado do ping.fm, podemos reenviá-lo.
por hakre 30.08.2010 / 04:53
fonte
7

Teste seu plug-in

Devemos ter definitivamente algumas ferramentas de teste em nosso ambiente de desenvolvimento de plug-ins.

Baseado em esta resposta por Ethan Seifert para uma questão de teste, estas são boas práticas a seguir:

  • Seu teste de unidade deve testar a menor quantidade de comportamento que uma classe pode realizar.
  • Quando você chega ao nível de testes funcionais, é onde você pode testar seu código com dependências do Wordpress.
  • Dependendo do que seu plug-in faz, considere o uso de testes baseados no Selenium que testam a presença de dados no DOM usando IDs
por Fernando Briano 13.04.2017 / 14:37
fonte