Uma peça chave do sucesso do WordPress é justamente sua capacidade de aceitar plugins e widgets, além , é claro, dos milhares de programadores que desenvolvem os mais diversos plugins que fazem de tudo um pouco.
Algum tempo atrás fui abordado pelo Manoel Lemos do BlogBlogs para discutirmos uma missão, criar um plugin para o WordPress, baseado na API do site. Comecei entao minha saga atrás de como desenvolver um plugin. O material estava lá, espalhado em vários sites, mas estava lá.
Então agora com o sucesso do BBUinfo e na véspera de novos projetos, decidi tentar consolidar este conhecimento adquirido e focar ele no público brasileiro. Vou procurar mostrar o caminho das pedras de como começar e onde buscar os dados necessário para integrar seu código ao do WP.
O WP, como eu disse, foi desenhado com plugins em mente. Sua estrutura possui diversos componentes desenhados para que seu plugin se “encaixe” no ponto certo (attach points ou hooks) e na hora certa. Mas para isso é importante observar alguns passos, para melhor desenhar seu plugin.
Os passos a seguir são a minha recomendação de como desenvolver um plugin, e evitar maiores problemas e dificuldades. Para poder acompanhar melhor o código produzido, vou estar criando com vocês o meuPrimeiroPlugin, que será descrito passo a passo abaixo.
Passo 1: Planejamento
No desenvolvimento de qualquer sistema o primeiro passo deve sempre ser uma análise e planejamento do que será feito, com plugins, embora pequenos, isto se mantém.Como em sistemas é importante identificar neste momento o que se deseja fazer, qual o objetivo do plugin. Levantar entradas e saídas, dados externos e suas fontes, enfim, definir de forma geral o que o plugin faz, com que dados ele faz isso e como obter os dados necessários.Faça perguntas como:
- Preciso de um banco de dados?
- Preciso acessar dados externos por webservice ou uma API?
- Vou mostrar algo visual para o usuário?
- O que pretendo fazer?
- Qual o nome darei ao plugin?(se você consegue definir o nome, sabe o que quer)
Um bom exercício para este momento é utilizar o padrão de arquivo readme do WP e já iniciar a escrita da descrição resumida e detalhada do plugin, pois este será seu guia. (você pode validar o arquivo aqui)
meuPrimeiroPlugin
Este plugin, desenhado para o aprendizado de como desenvolver plugins, executa ações básicas e didáticas, mas sem muito uso. Para mostrar todos os limites, o plugin fará as seguintes ações:
- Acrescentará ao final de cada comentário o texto: “O conteúdo deste comentário é de responsabilidade de: {AUTOR}”
- Criará uma tabela nova que irá armazenar uma contagem de visitas a cada post, e mostrará esta contagem logo ao final do POST.
- Substituir a palavra XXX por um link
Exemplos
- Arquivo readme.txt
- Meu brainstorm (idéias para o plugin):
Produtos desta etapa
Arquivo readme.txt, arquivo com “brainstorm” (tente um mindmap, como acima)
Passo 2: Projeto
Esta etapa segue os padrões de projetos de sistema, mas com algumas adições específicas do WordPress. Como base sugiro que use a linguagem UML para definir seu projeto e faça um diagrama de MER (base de dados).
Embora não seja obrigatório, a criação do plugin como um objeto, é recomendável e mais fácil de manter do que código estruturado, além claro de ser uma “prática recomendada” para o PHP5. Outra grande vantagem nesta orientação é que como os métodos são chamados de dentro do objeto a preocupação com “nomes coincidentes” é nula, sendo reduzida apenas ao nome do objeto que deve ser único.
Então defina o seu objeto com métodos que se identifiquem com as diversas ações que o plugin vai executar, por exemplo: adicionarAssinatura(), pegarDadosExternos(), salvarDados()…
Agora entra o ponto onde o WordPress traz toda sua mágica com os seus “hooks”, ou ganchos.
Ganchos do WordPress
Para facilitar que se ligue o plugin às ações doWP, são definidos ganchos em sua programação, ou seja, em pontos específicos do funcionamento do plugin, são disponibilizados pontos onde as funções podem se “pendurar”. Desta forma caso deseje criar um plugin, que deve executar determinada função no momento em que um comentário é salvo, você usaria o gancho “comment_post”.
Estes ganchos são divididos em 2, ações e filtros.
- Ações são eventos disparados em momentos exatos durante a execução do WordPress.
- Filtros são lançados no momento de gravação ou apresentação de um texto para que seja possível modificá-lo.
Outros Links: Todos Hooks de todas versões do WP
Para definir os ganchos você pode se perguntar “Em que momento devo fazer isso?” para cada ação e então verificar a lista de ganchos de ações e filtros para achar qual lhe atende.
meuPrimeiroPlugin
Neste caso podemos usar os seguintes pontos para anexar nossas funções:
- Instalar: ligada ao “register_activation_hook” que é executado na ativação de um plugin no menu
- Desinstalar: Estas funções foram bastante discutidas, mas ainda não existe um hook fixo.
- Inicializar: Esta deve ser executada logo no início, para isso temos o filtro “init”
- Aba de opções: para fazer a aba precisamos de dois pontos, a ação “admin_menu” e o “add_options_page”.
- Contar Visita: poderia ser melhor,mas o filtro “the_content” garante a contagem na hora mais certa.
- Inserir texto no comentário: Para isso o filtro “get_comment_text” é perfeito
- Substituir palavras: este é bem direto também, vamos usar o filtro “the_content”
Juntamente com este raciocínio, fiz o mapeamento da classe e do que seria necessário na base de dados:
Diagrama de classe do plugin
MER do Banco
Produtos desta etapa: diagrama de classe do seu plugin, um MER do banco de dados e uma lista de possíveis pontos de inserção (ganchos).
Passo 3: Desenvolvendo
Com o caminho a sua frente devidamente mapeado, agora podemos nos aprofundar no código, além de conhecer algumas possibilidades que o WP traz embutidas em si mesmo.
O ideal é que seu plugin caiba dentro de um arquivo só, mas caso isso não seja possível, recomenda-se que todos arquivos sejam jogados dentro de uma pasta com o mesmo nome do plugin. O nome do plugin também pode (recomenda-se) ser o nome de seu arquivo principal, isso irá lhe facilitar usar funções “on activation” disparadas na ativação do plugin. Portanto teremos a seguinte estrutura para nosso exemplo:
A primeira coisa que deve aparecer em nosso arquivo meuPrimeiroPlugin.php é o cabeçalho. Este cabeçalho é usado pelo WP para mostrar os dados de seu plugin na página de administração de plugins, então é muito importante manter estes dados corretos, o cabeçalho segue o padrão abaixo:
/* Plugin Name: Nome do Plugin Plugin URI: http://Endereço_da_pagina Description: Descrição simples e curta do plugin Version: A versão atual do plugin, ex.: 1.0 Author: Nome do Autor do Plugin Author URI: http://Endereço_do_site_do_autor */
Após isso podemos começar a definir a classe. A definição segue o padrão normal de um objeto em PHP (4 ou 5). Aqui vamos seguir uma orientação PHP5 por sua enorme vantagem e pelo “fim” do PHP
O site do WP possui muito material sobre padrões de codificação, e eu recomendo uma leitura, mas são padrões bem estabelecidos que muitos programadores já devem usar normalmente.
Como vimos no passo anterior montamos um diagrama de classe e nesse diagrama já identificamos as funções que precisamos desenvolver em nosso plugin, portanto a seguir vou seguir passo a passo deste arquivos criando e explicando cada uma destas funções, e no final comentarei sobre os ganchos que serão colocados fora do escopo do objeto e porque.
Função Inicializar
Esta função serve para centralizar todas as ações que devem ser sempre tomadas para integrar o plugin com o WP, sejam elas ações de adição/remoção de filtros/ações ou instanciação de objetos, cópias de variáveis globais, enfim, todas ações que serão executadas sempre que o WP carregar.
public static function inicializar(){ global $wpdb; //Definir ganchos add_filter("get_comment_text", array("meuPrimeiroPlugin","exonerarComentarios")); add_filter("the_content", array("meuPrimeiroPlugin","contarVisita")); add_filter("the_content", array("meuPrimeiroPlugin","processarSubstituicao")); add_action('admin_menu', array('meuPrimeiroPlugin','adicionarMenu')); //Mapear objetos WP meuPrimeiroPlugin::$wpdb = $wpdb; //Outros mapeamentos meuPrimeiroPlugin::$info['plugin_fpath'] = dirname(__FILE__); }
Como podemos ver, no caso do meuPrimeiroPlugin, estamos cadastrando as outras funções com seus devidos filtros, ou seja, os ganchos que irão executá-las e copiando o objeto $wpdb para dentro do nosso script, podendo agora ser referenciado como: meuPrimeiroPlugin::$wpdb que é melhor que ficar sempre usando “global” no início da função. Além disso aproveita-se para obter a localização do plugin, usando a constante __FILE__ do PHP que define o caminho até o arquivo onde esta.
$wpdb
Este objeto sempre presente no WordPress é responsável pela sua conexão com a base de dados, ele pode executar queries, buscar dados, e realizar diversas funções relacionadas a base de dados. Veja aqui a lista de métodos [aqui]
Função Instalar
Esta função é mapeada para ser executada no momento que o plugin é ativado na aba de plugins do WordPress. Como nosso plugin utiliza dados que serão salvos e lidos de bases de dados é necessário que elas sejam criadas antes de seu uso, o momento de ativação é excelente para isso, porém o plugin pode ser ativado e desativado diversas vezes (quando se faz upgrade do WordPress por exemplo) e não podemos simplesmente criar a tabela sempre, por isso observe o comando para criar apenas caso não exista.
public static function instalar(){ if ( is_null(meuPrimeiroPlugin::$wpdb) ) meuPrimeiroPlugin::inicializar(); //Criar base de dados $sqlContador = "CREATE TABLE IF NOT EXISTS `".meuPrimeiroPlugin::$wpdb->prefix."mpp_post_visitas` ( `id_post` INT NOT NULL , `visitas` INT NULL , PRIMARY KEY (`id_post`) )"; $sqlPalavras = "CREATE TABLE IF NOT EXISTS `".meuPrimeiroPlugin::$wpdb->prefix."mpp_substituicao` ( `idmpp_substituicao` INT NOT NULL AUTO_INCREMENT , `orig_palavra` VARCHAR(255) NULL , `subst_palavra` VARCHAR(255) NULL , PRIMARY KEY (`idmpp_substituicao`) )"; meuPrimeiroPlugin::$wpdb->query($sqlContador); meuPrimeiroPlugin::$wpdb->query($sqlPalavras); //Criar opções add_option("mpp_texto_exonerar","O conteúdo deste comentário é de responsabilidade de: "); }
Neste caso, de forma puramente didática, criei uma opção para armazenar o texto que será inserido nos comentários. Esta opção foi criada apenas para mostrar como elas podem ser utilizadas. Estas opções são gravadas na tabela de opções do próprio WordPress e acessadas com estes métodos: add_option, update_option, delete_option, get_option.
Note que no ínicio da função chamo a função de inicialização, isso é importante pois no ato em que a função de instalação é chamada o gancho “init” ainda não foi chamado e por isso não temos nossa conexão com o banco por exemplo. Isto causaria erros na ativação do plugin.
Dica:
Se você receber um aviso “cannot redeclare class” na ativação do plugin, 9 em 10 vezes o erro não esta na declaração do plugin e sim omitido pelo WordPress, em sua função de captura de erros, que infelizmente possui algumas falhas, como essa.Para ver o erro verdadeiro vá até o arquivo wp-admin/plugin.php e comente as linhas 14 e 15, mostradas abaixo:
wp_redirect(add_query_arg('_error_nonce', wp_create_nonce('plugin-activation-error_' . $plugin), 'plugins.php?error=true&plugin=' . $plugin)); // we'll override this later if the plugin can be included without fatal error ob_start();
Função Desinstalar
Esta função não possui um hook para ser executada de forma automática, mas é uma função que recebeu muita atenção nos últimos tempos em diversas discussões pela internet. Nossa aba de opções deve implementar uma chamada a esta função, mas em breve o WordPress deve implementar um hook para ela.
Sua função é bem direta e simples, remover tudo que foi criado pela função de instalação. Por isso não é possível ligar ela ao ato de “desativar” o plugin, pois o usuário perderia suas preferências a cada vez que fizesse upgrade do WordPress (é recomendado que se desative os plugins para tal).
public static function desinstalar(){ //Remover bases de dados $sqlContador = "DROP TABLE `".meuPrimeiroPlugin::$wpdb->prefix."mpp_post_visitas`"; $sqlPalavras = "DROP TABLE `".meuPrimeiroPlugin::$wpdb->prefix."mpp_substituicao`"; meuPrimeiroPlugin::$wpdb->query($sqlContador); meuPrimeiroPlugin::$wpdb->query($sqlPalavras); //Remover opções delete_option("mpp_texto_exonerar"); }
Como podemos ver apenas é feito um DROP nas tabelas e a remoção da opção que foi criada na própria tabela do WordPress.
Função adicionarMenu
Esta função indica ao WordPress que ao montar o menu da administração ele deve inserir uma nova aba que aponta para uma função de nosso plugin.
public static function adicionarMenu(){ add_options_page('meuPrimeiroPlugin - Gerenciamento','meuPrimeiroPlugin',10,__FILE__,array("meuPrimeiroPlugin","abaOpcoes")); }
A sintaxe deste comando é a seguinte:
add_menu_page(titulo_da_pagina, titulo_do_menu, nivel_de_acesso, arquivo, [função]);
O nível de acesso diz respeito as permissões do usuário, o arquivo é o arquivo de nosso plugin (__FILE__) e a função é a função de nossa classe em formato de call_user_func
Função abaOpcoes
Esta função é a que setamos no exemplo anterior para ser executada quando o usuário clicar na nossa aba do menu. Neste caso fiz uma implementação simplificada, onde uma mesma função mostra o menu e executa as operações de salvar e atualizar as opções.
Para salvar as opções fazemos inserções usando novamente o $wpdb->query(). Esta operação é executada sempre que o array de POST (dados enviados pelo form) possuir algum conteúdo.
Para mostrar o formulário utilizei uma implementação simplificada de templates, onde tenho um arquivo .tpl externo com o layout do menu e chaves especiais ({PALAVRAS},{STATS}…) que são substituídas pelo conteúdo que quero gerar. Você pode usar outra técnica e até usar código espageti com HTML no meio de seu plugin, depende da sua facilidade e organização. Para gerar o conteúdo dinâmico, faço diversas queries no banco buscando os dados que são necessários.
public static function abaOpcoes(){ //Predefinidos $templateVars['{UPDATED}'] = ""; $templateVars['{ERROS}'] = ""; //Executar operações definidas if (count($_POST) > 0){ $ins = meuPrimeiroPlugin::$wpdb->query("INSERT INTO ".meuPrimeiroPlugin::$wpdb->prefix."mpp_substituicao (idmpp_substituicao,orig_palavra,subst_palavra) VALUES (NULL,'".$_POST['orig']."','".$_POST['subst']."') "); $templateVars['{UPDATED}'] = '<div id="message" class="updated fade"><p><strong>'; if ($ins){ $templateVars['{UPDATED}'] .= "Dados atualizados!"; }else{ $templateVars['{UPDATED}'] .= "Erro ao atualizar dados!"; } $templateVars['{UPDATED}'] .= "</strong></p></div>"; } //Ler arquivo de template usando funções do WP $admTplObj = new FileReader(meuPrimeiroPlugin::$info['plugin_fpath']."/admin_tpl.htm"); $admTpl = $admTplObj->read($admTplObj->_length); //pegar palavras $resultados = meuPrimeiroPlugin::$wpdb->get_results( "SELECT orig_palavra,subst_palavra FROM ".meuPrimeiroPlugin::$wpdb->prefix."mpp_substituicao" ); foreach($resultados as $res){ $palavras .= "<li><b>".$res->orig_palavra." -></b> ".$res->subst_palavra."</li>"; } $templateVars['{PALAVRAS}'] = $palavras; //pegar estatisticas $resultados = meuPrimeiroPlugin::$wpdb->get_results( "SELECT post_title,visitas FROM ".meuPrimeiroPlugin::$wpdb->prefix."mpp_post_visitas LEFT JOIN ".meuPrimeiroPlugin::$wpdb->prefix."posts AS posts ON mpp_post_visitas.id_post = posts.ID" ); foreach ($resultados as $res){ $stats .= "<dt>".$res->post_title."</dt>"; $stats .= "<dd>".$res->visitas." Visitas</dd>"; } $templateVars['{STATS}'] = $stats; //Substituir variáveis no template $admTpl = strtr($admTpl,$templateVars); echo $admTpl; }
Observe o uso da classe FileReader para leitura do arquivo .tpl. Esta classe é nativa do WordPress portanto a preferência de se utilizar ela ao invés de utilizar funções como fopen ou similares. É importante lembrar que o WordPress possui diversas classes disponíveis em suas pastas, e é uma boa idéia ver se existe alguma para executar a operação que você procura.
Função contarVisita
Como foi dito esta função é convocada pelo gancho “the_content” sempre que o conteúdo de um post for resgatado do banco para exibição. Então para fazer uma simples contagem de visualizações de um post, sem entrar em muitos detalhes, filtros por IP nem nada do tipo, apenas fazemos uma inserção no banco, em nossa tabela de contagem.
public static function contarVisita($post_texto){ global $post; $sql = "INSERT INTO ".meuPrimeiroPlugin::$wpdb->prefix."mpp_post_visitas (id_post,visitas) VALUES ('".$post->ID."',1) ON DUPLICATE KEY UPDATE visitas=visitas+1"; meuPrimeiroPlugin::$wpdb->query($sql); return $post_texto; }
Note neste caso que a função recebe um parâmetro que chamei de $post_texto. Sempre que uma função usa o gancho “the_content” ela receberá o conteúdo do post como parâmetro. Ao final da função este conteúdo, alterado ou não, deve ser retornado com uma chamada return, caso contrário o blog não exibirá o conteúdo do post.
Para o comando de SQL caso interesse usei o ON DUPLICATE KEY UPDATE, que verifica se já existe um registro para o post e faz a atualização do mesmo, caso contrário cria o novo registro. Ela é bem útil para não ser necessário fazer um select para decidir se devemos usar um INSERT ou UPDATE.
Função processarSubstituicao
Esta função, também ligada ao “the_content” efetua a troca das palavras que cadastrarmos, por outras que forem escolhidas. É interessante notar que podemos ter várias funções ligadas a um mesmo gancho e elas serão executadas na ordem que os ganchos são designados, por isso a importância ressaltada na função anterior, onde o parâmetro deve ser retornado no final.
Para fazer a substituição usei um método simples também, busquei no banco os pares (palavra original => nova palavra) e montei um array de “tradução”. Usando a função strtr do PHP eu passo este array e o texto do post e a função se encarrega de fazer a troca e me devolver o texto alterado.
public static function processarSubstituicao($post_texto){ //Montar array de palavras para substituirmos $resultados = meuPrimeiroPlugin::$wpdb->get_results("SELECT orig_palavra,subst_palavra FROM ".meuPrimeiroPlugin::$wpdb->prefix."mpp_substituicao"); foreach($resultados as $res){ $aTraducao[$res->orig_palavra] = $res->subst_palavra; } $post_text = strtr($post_texto,$aTraducao); return $post_texto; }
Função exonerarComentarios
Finalmente esta função será a responsável por incluir um texto ao final do comentário para nos exonerar das palavras do seu autor. Para isto usamos o gancho get_comment_text que é similar ao get_content acima, mas se refere ao comentário.
public static function exonerarComentarios($cmt_texto){ global $comment; $anexo = "<br><br><b><i>".get_option('mpp_texto_exonerar').$comment->comment_author."</i></b>"; $cmt_texto .= $anexo; return $cmt_texto; }
Como antes, recebemos o texto como parâmetro e devemos retornar ele ao final para evitar quebrar outros plugins ou ocultar comentários .
Nota: Quando desenvolvi meu primeiro plugin de WordPress, usei o gancho get_comment_ID e não fiz o retorno do meu parâmetro ao final. Resultado, todos plugins executados após este quebravam, pois não recebiam um ID e sim uma string vazia.
Usando o contexto global, a variável $comment é um objeto que representa todos os dados do comentário atual, por isso como pode ser visto acima, posso acessar o nome do autor, para agregá-lo à mensagem, que foi buscada da tabela de opções pela chamada get_option. Ao final tudo isso é concatenado ao texto no comentário que segue em frente para outros plugins, ou é simplesmente mostrado.
Código remanescente
Para inicializar nosso plugin o código abaixo é inserido solto em nosso arquivo, para que seja executado diretamente quando o arquivo for incluso, já que tudo que esta no escopo da classe não é executado sem sua instanciação.
$mppPluginFile = substr(strrchr(dirname(__FILE__),DIRECTORY_SEPARATOR),1).DIRECTORY_SEPARATOR.basename(__FILE__); /** Funcao de instalacao */ register_activation_hook($mppPluginFile,array('meuPrimeiroPlugin','instalar')); /** Funcao de inicializacao */ add_filter('init', array('meuPrimeiroPlugin','inicializar'));
Nestes ganchos determinamos a execução da função instalar na ativação do plugin e da init na inicialização do WordPress. Para o gancho de ativação definimos a variável $mppPluginFile que determina a pasta onde o plugin esta, e para isso o plugin deve estar em uma sub-pasta de plugin e não na raiz. Com esta combinação de funções e as constantes DIRECTORY_SEPARATOR (barra invertida ou não), e o __FILE__, saimos com algo como “mpp/meuprimeiroplugin.php” ou seja, pasta e arquivo necessários para a detecção de ativação.
Divulgando seu plugin
Para divulgar seu plugin o primeiro e mais importante passo é adicionar ele no repositório do WordPress. Isso é uma excelente ferramenta, pois além de fornecer um repositório SVN que pode lehe ajudar a melhor controlar seu desenvolvimento ele permite que o usuário de seu plugin possa ser notificado de novas versões diretamente na página de plugins.
Divulgue o seu plugin no repositório oficial do WordPress: http://wordpress.org/extend/plugins/ usando o link http://wordpress.org/extend/plugins/add/. A única exigência é que o plugin deve ser licenciado como GPL (detalhes)
Conclusão
Espero que com este artigo (que atrasou mais do que devia) muitos usuários de WordPress e desenvolvedores da comunidade possam embarcar no desenvolvimento de novos plugins e que todos tenham uma noção do poder que o blog oferece permitindo tamanha integração de forma tão simplificada e acessível.
O plugin criado neste exemplo esta 100% funcional e pode até ser usado, mas use-o para aprender e vá muito mais longe. Abaixo deixo os links para download caso lhes interesse.
Com o atraso do artigo estamos na beira do WordPress 2.5, mas tudo indica que além da carinha nova da administração, não haverá impactos no processo descrito acima, e inclusive este exemplo já funciona na nova versão e foi testado aqui com ela.
não esqueçam: se quiserem agradecer, contribuam com uma graninha ou um presente da lista ao lado….
Caramba Rafael, de PRIMEIRÍSSIMA QUALIDADE seu material.
Meus parabéns, tenho certeza que será muito útil para quem está começando a desenvolver plugins para o WP.
Dá só uma olhadinha aqui embaixo dos comentários que tá dando erro.
WordPress database error: [Unknown table ‘wp_posts’ in on clause]
SELECT p.ID, p.post_title FROM wp_posts AS p INNER JOIN wp_post2lang p2l ON wp_posts.ID = p2l.post_id INNER JOIN wp_languages l ON p2l.language_id = l.language_id WHERE p.post_date ‘2008-03-10 10:40:10’ AND p.post_type = ‘post’ AND p.post_status = ‘publish’ AND p.ID != 147 AND l.language_id IN (1) ORDER BY p.post_date ASC LIMIT 1
Meu, show de bola, parabéns!!!
Rafael,
Obrigado.
Sobre o erro, sim é o Gengo que ainda não esta compativel e nao tive tempo de arrumar, mas felizmente o erro é só visual, não afeta o funcionamento do blog, por isso nao pus urgencie nele, com o WP 2.5 isso deve se resolver.
Abraço.
Oi Rafael, existe alguma diferença para plugins WordPress 2.5 em relação as instruções que você dá aqui?
Acredito que estas instruções também funcionaram em plugins para WordPress 2.5, mas com todas as funcionalidades que a versão 2.5 dispoe?
Isto é a 2.5 tem novos padrões para desenvolver plugins?
Desde já agradeço sua atenção,
Sardano
Sardano,
Não olhei com cuidado as novidades ainda, mas todos plugins que fiz estão funcionando normalmente como era esperado. Então o tutorial vale sim para a versão 2.5 e os padrões são os mesmo até o momento.
Na versão 2.5 temos novidades sim, uma delas é a ShortCode API que permite tags como [gallery] dentro do post que são depois substituidas por algo, vou ver se escrevo sobre isso depois.
Abraço!
salve pessoal,
eu fiz uma tradução do plugin download manager pt-BR
quem tiver interesse baixa no meu site e testa esse trem…blz
valews
http://www.viz.com.br/?page_id=100
Ola Rafael,
Muito bom viu.. estou usando seu tutorial para criar um plugin aqui no meu trabalho… Ainda estou começando a mexer.
Só um detalhe, você esqueceu de por o gancho register_deactivation_hook chamando a função de desinstalar…
Parabens
[]s
Humberto
Humberto,
Na verdade este gancho não pode ser usado para desinstalação, pois no ato do upgrade do WP cada plugin é desativado, entao imagine qu voce perderia suas configurações cada vez que o plugin for desativado. Eu falo sobre isso na função desinstalar.
Abraço!
olá grande rafael!
gostei muito do seu post, estou a apenas 2 semanas estudando programação (principalmente OO) e mesmo assim tive uma compreenção clara do seu artigo, ótima didática.
gostaria de saber se em vez de declararmos os métodos dentro de uma classe poderiamos criar uma interface ou uma classe abstrata e estender o plug-in?
seria possível aplicar uma arquitetura MVC para um plug-in wordpress?
Obrigado pelos elogios.
Bem, você pode criar a estrutura que desejar, portanto que mapeie os filtros para as funções de um classe.
No meu plugin BlogblogsUserInfo, eu uso uma pseudo-camada de templates improvisada inclusive, então cair em algo MVC é possível sim.
Você pode usar interfaces e classes abstratas, mas terá de ter uma classe que implemente ou extenda estas, não existe uma classe plugin do próprio WP que possa ser estendida.
Abraço!
Muito bom, Parabens pelo blog!
para estudos….
Seu tutorial me foi muito útil essa semana! Obrigado!
Olá, Rafael!
Parabéns pelo ótimo tutorial. Pela primeira vez em quase 3 anos mexendo com o WordPress precisarei desenvolver pequenos hacks ou até mesmo plugins. Seu tutorial foi muito bem estruturado e explicado.
Sucesso com o blog!
Parabéns muito bom tutorial
adicionei seu blog aos favoritos
abraço
Parabéns, estou começando hoje a aprender e está sendo muito bom.
Abaixei e instalei como está para testar no meu 2.7 e notei que:
* no admin não exibia as visitas por posts (este resolvi adicionando um ” AS mpp_post_visitas” que faltou na linha 136
* um warning sobre um segundo parâmetro da linha 185 não ser array ocorre se não houver nenhuma palavra cadastrada para substituição
foi ótimo!
obrigado e abraço!
Luciano,
No 2.7 algumas coisasa mudaram , eu tenho que revisr este plugin, mas obrigado pelas dicas.
Abraço
Testei no 2,7, e ele não substitui as palavras.
Fala ae cara beleza?
O seu artigo está de 100%, mas estou com algumas dúvidas aqui.
Estou escrevendo um plugin ou melhor dizendo, tentando, que funcione da seguinte forma:
após um novo cadastro no WordPress o plugin seria disparado, este por sua vez, pegaria o email cadastrado pelo visitante e enviaria um email usando a classe PHPMailer para um email de assinatura de uma lsta de discussão.
Estava navegnado pelos hooks para tentar identificar qual seria o melhor gancho para isso, achei o register_form ou o user_register
Mas minha dúda alem de saber como identificar o melhor hook para os diversos casos, como pegar o email previamente cadastrado?
depois vou aperfeiçoar o plugin, fazendo uma aba no admin do WP para que seja possível informar quel o email que irá receber o registro e tal.
Pode ma ajudar a sanar minhas dúvidas?
abraços.
Gerson,
Procure no código fonte onde o hook é disparado e veja quais objetos estao disponiveis, ou veja se existe uma funçao que busque estes dados.
Nem sempre é facil, mas já é um caminho para começar.
Fala Rafael, blz?
Cara, consegui fazer o plugin, ainda que basico, seguinda a propria documentação do WP…
tentei usar o add_filter da forma como estava aqui na suas explicações e deu vários erros..
mudei para add_filter(“filtro”, “função/metodo”);
e funcionou sem o uso de array e tal….
mas é isso. com tempo vou melhorar ele e posto aqui as dificuldades e o que foi aprendido..
compartilhar.
abraços.
Gerson,
O array é apenas usado se vc for chamar uma método de um objeto, se for chamar uma função é só botar o nome. Verifique “callbacks” no manual do PHP.
O que me impressionou foi vc ter usado padrões de projeto modelagem e etc em algo tão simples cara. Isso mostra o alto nivel do desenvolvedor e da linguagem. parabens Dohms
Desenvolver plugins para wordpress é um ótimo benefício para os internaltas que usam essa ferramenta. Parabéns.
Fala rafael tudo bom ?
muito seu material sobre desenvolvimento de plugins!!
bem ve se vc pode me ajudar com uma coisa,(sei que nao tem haver com o post entao pode apagar se preferir) eu criei 3 cartegorias, sendo que a primeira e a mãe(nao contem post) e as duas restantes sao filhas (contem post), crie a pagina cartegory.php pra quando clicar na categoria mãe, apresentar as informacoes sobre os posts, mas gostaria de apresentar o resultado ordenado por categoria e nao em ordem cronologica, utilizei a seguinte funcao :
query_posts(”{$query_string}&orderby=category”) antes do have_post(). mas nao obtive sucesso =(
vc teria alguma dica pra resolver esse meu problema?
http://www.periclessantana.com.br/arq/query.jpg esse e o link do print do codigo, caso vc ou alguem queira da uma ajuda.
Agradeço desde ja
[ ]’s
Cordialmente Romulo
Muito bom o tuto. Tive a necessidade de fazer um plugin para wordpress sem qualquer experiência nisso. Baseado no seu guia eu consegui realizar. Em breve vou disponibilizar o plugin no site do wordpress, espero ajudar a comunidade. É um plugin de pesquisa (parecido com o wp-surveys), porém mais flexível.
Um abraço a todos.
Olá rapaz, belo tutorial, me ajudou a construir meu primeiro plugin
Publiquei meu plugin no banco de dados de plugins do wordpress aqui http://wordpress.org/extend/plugins/admiyn-twitter/
O Meu plugin atualiza o status no Twitter sempre quando um novo artigo ou comentário é pubicado.
Valew pela contribuição. CEY
Muito bom mesmo! Parabéns pelo post.
Your blog is very interresting for me, i will come back here..
Boa Tarde Rafael,
Excelente tutorial, ajudou muito no desenvolvinmento do meu primeiro plugin!
Vê se você pode me dar mais uma ajuda: eu preciso exibir o resultado da busca que o plugin faz na base de dados em uma página que eu o usuário criar (já vi que os plugins que usam este recurso fazem isso usando o nome do plugin entre colchetes dentro da página, ex.: [contactform] / [newsletter] ), vocÊ sabe me dizer como posso fazer isso?
Grato,
Andre
Andre,
Isso é o recurso mais usado mesmo, a nao ser que vá mostrar o reslutado em um widget.
Para fazer isso é simples, use o hook de post_content, acho que é esse, verifique, e use um comando str_replace substituindo o texto nos colchetes pelo conteudo da sua busca.
Abraço
Olá Rafael,
Favor desconsiderar o email que lhe enviei! Achei a solução neste mesmo artigo seu, trocando o loop de while para foreach e o script funcionou perfeitamente!
Continuarei acompanhando seu blog, que traz um excelente trabalho!
Abçs
Andre
Parabéns pelo texto …
Simplesmente surpeendente a organização, conteúdo e empenho.
Sucesso..
Valeu pelo Post
Obrigado pelo tutorial. Aquela televisão/monitor de 22′ que vc quer, está indisponível no site, portanto terei que achar outra coisa.
Abraço.
Gostei do artigo, mas uma coisa que eu quero aprender eu acabei não aprendendo, como eu faço para que meu plug-in seja carregado no lugar do conteúdo do site?
Pois eu quero integrar o conteúdo que o plug-in gera no WordPress, pretendo fazer um site de downloads integrado com o blog, já está até pronto, mas aparece o meu conteúdo (do plug-in) e logo abaixo o conteúdo da homepage do do próprio WordPress.
Bom, é isso, eu quero desativar o conteúdo principal a partir de um IF, mas não sei como fazer isso.
Obrigado pelo artigo, me ajudou muito, mas ainda falta este "detalhe" pra mim terminar.
Gostei do artigo, mas uma coisa que eu quero aprender eu acabei não aprendendo, como eu faço para que meu plug-in seja carregado no lugar do conteúdo do site?
Pois eu quero integrar o conteúdo que o plug-in fera no WordPress, pretendo fazer um site de downloads integrado com o blog, já está até pronto, mas aparece o meu conteúdo (do plug-in) e logo abaixo o conteúdo da homepage do do próprio WordPress.
Bom, é isso, eu quero desativar o conteúdo principal a partir de um IF, mas não sei como fazer isso.
Obrigado pelo artigo, me ajudou muito, mas ainda falta este “detalhe” pra mim terminar.
Pronto!!! Não é mais necessário, eu desativei no tema!
Já que meu plug-in só funciona junto com o tema, crie umas variáveis para eles interagirem entre sí e deu certo!!!
Muito obrigado pelo post e parabéns!!! 😉
Caro Rafael:
Já lhe enviei uma mensagem pelo seu Blog, mas como o computador pendurou, não sei se recebeu a mesma.
Vamos ao que interessa, instalei o “meuprimeiroplugin” sem problemas, mas quando vou Menu de Administrador e clico em “Opções / meuprimeiroplugin” recebo o seguinte erro:
“Fatal error: Class ‘FileReader’ not found in /home/ruimacd1/public_html/wordpress/wp-content/plugins/meuprimeiroplugin/meuprimeiroplugin.php on line 125”
Pode-me ajudar com o presente erro?
Já agora, tenho um PlugIn que queria desenvolver, gostava de saber se está interessado em fazê-lo, eu Pago! Se estiver interessado ou souber de alguém que está interessado por favor contactem-me através do meu email.
Rui Macdonald
Ok! Já funciona!
No meuprimeiroplugin.php logo depois dos cometários iniciais inclui:
include(ABSPATH . ‘wp-includes/streams.php’);
E passou funcionar.
Segundo li, é devido à Class FileReader não ser standard agora no WordPress.
Fiquem Bem!
Rui Macdonald
Oi Rafael,
Muito rico e bem detalhado este seu tutorial. Meus parabéns!
aguardo resposta!!!!!!!!!!!!!!!!!
Cara, muito bom mesmo, simplesmente nunca vi um tutorial tão completo, explicativo e com inovações como este.
Atenção especial para o ‘ON DUPLICATE KEY UPDATE’, que particularmente não conhecia e é de grande importância no desenvolvimento.
Parabéns!
Sobre a correção do strems.php, encontrei no blog http://wordpress.org/support/topic/289304 uma solução a qual passei a usar.
No caso do erro relatado pelo Rui McDonald, e depois dado solução por ele mesmo, no meu caso não funciona pois não existe o arquivo stream.php no WPMU. O que fazer?
Estou com o mesmo problema do FileReader o arquivo strems.php não existe como devo proceder, achar este arquivo na internet e colocar salvar na pasta?
blog.rafaeldohms.com.br's done it again. Superb article.
Olá Rafael,
Olha eu aí de novo! O meu plugin cria tabelas próprias na rotina de instalação e elimina essas tabelas na rotina de desinstalação, então quando o plugin tiver uma atualização as tabelas serão apagadas e recriadas? Ou o wordpress reconhece que é uma atualização e não executa a rotina de desinstalação?
Estou querendo lançar minha primeira atualização, mas estou com receio devido a essa questão.
Grato,
André