Como personalizar a classe wpdb e adicionar novos métodos
Publicados: 2018-07-10A camada de abstração do banco de dados WordPress, mais conhecida como wpdb, é uma classe baseada em ezSQL responsável por interagir com o banco de dados. A classe wpdb também é um drop-in – uma parte do código principal do WP que pode ser facilmente substituída por outra parte de código com funcionalidade semelhante (uma lista atualizada de drop-ins está disponível em WP Code Reference).
Modificar a classe padrão #wpdb não é complicado. Você pode facilmente adicionar, remover ou modificar apenas alguns métodos. Não há necessidade de substituir toda a classe. #wordpress
CLIQUE PARA TWEETÉ aqui que entra em jogo um grande equívoco. As pessoas percebem “substituído” como em “escrever minha própria classe de banco de dados completa”. Felizmente, você não precisa escrever toda a classe de banco de dados. Você pode pegar a classe existente e adicionar, remover ou modificar apenas as funções que você precisa. E é isso que vamos fazer.
Por que modificar a classe wpdb?
Certamente, wpdb tem tudo que você precisa!? Todo o WP é construído em cima dele. Tecnicamente está correto. Usando o método $wpdb->query()
você pode executar qualquer comando SQL. Mas com essa lógica aplicada nunca teríamos ou precisaríamos de métodos como $wpdb->insert()
ou $wpdb->get_var()
. Mas nós fazemos, porque eles economizam tempo, reduzem bugs e mantêm as consultas ruins afastadas. Então, quais funções estão faltando? Isso depende do projeto em que você está trabalhando. Precisávamos de suporte para essas duas consultas:
INSERT IGNORE INTO tbl_name ...
INSERT INTO tbl_name ... ON DUPLICATE KEY UPDATE ...
Passo #1 – Crie o drop-in
O processo de criação de um drop-in de banco de dados é simples e o resultado final combina perfeitamente com o WP.
Crie um arquivo chamado db.php
e coloque-o na pasta /wp-content/
. Dê ao arquivo um cabeçalho de plugin padrão e crie uma classe que estenda wpdb. Algo assim:
<?php /* Plugin Name: Extended wpdb Description: A few extra functions for wpdb Version: 1.0 Author: WebFactory Ltd */ class wpdb_extended extends wpdb { public function __construct(){ parent::__construct( DB_USER, DB_PASSWORD, DB_NAME, DB_HOST ); } public function test() { echo 'Extended wpdb is running.'; } } global $wpdb; $wpdb = new wpdb_extended();
O cabeçalho é bastante auto-explicativo. O método construct garante que criamos uma nova conexão de banco de dados assim que um objeto é construído e usa o construtor wpdb original para isso. Essas constantes de banco de dados são definidas em wp-config.php
. Como dissemos no início – estamos apenas adicionando algumas funções e reutilizando todo o resto. O segundo método test()
é puramente para ver se tudo funciona corretamente.
As duas últimas linhas são cruciais. Como esta é uma classe personalizada, o WP não criará o objeto $wpdb
para nós automaticamente. Temos que fazê-lo nós mesmos. Lembre-se de usar a palavra-chave global
porque, caso contrário, você criará uma variável local.
Passo #2 - Teste antes de ir mais fundo
Abra seu WP Dashboard e vá para Plugins. Além das habituais abas Todos, Ativos e Inativos (plugins), você verá uma aba Drop-ins e nela, por mágica, nossa classe de banco de dados personalizada.
Como o administrador está funcionando corretamente, sabemos que fizemos um bom trabalho. Nossa nova classe personalizada e estendida chegou e nada mudou. Excelente! Mas, apenas para uma boa medida, coloque essas três linhas de código no functions.php
do tema (ou em algum lugar dentro de um plugin onde ele será executado imediatamente):
global $wpdb; $wpdb->test(); die;
Execute qualquer página de administrador ou front-end e o que você vê? “ O wpdb estendido está em execução. " Perfeito. Agora para nossas funções do mundo real.
Passo #3 - Criar, modificar ou substituir funções
A consulta INSERT IGNORE
parece bem fácil de fazer. Nós já temos $wpdb->insert() então estamos apenas perdendo uma única palavra. Infelizmente, devido à falta de filtros nos lugares certos, não serão duas linhas de código.
Se você abrir wp-db.php e for até o método insert()
na linha #2100, você verá que ele usa o método _insert_replace_helper()
da linha #2151. E essa função não tem um único filtro ou ação. Também não podemos envolver a função porque ela retorna imediatamente o resultado da consulta e não a própria consulta que poderíamos modificar. Desapontamento. Teremos que substituir os métodos insert()
e _insert_replace_helper()
. Adicionaremos um parâmetro extra – $ignore
. Um booleano com o valor padrão false
.
public function insert( $table, $data, $format = null, $ignore = false ) { return $this->_insert_replace_helper( $table, $data, $format, 'INSERT', $ignore = false ); }
Em qualquer outra circunstância, uma função com cinco parâmetros seria uma boa candidata para transformá-los em um array associativo. Mas queremos compatibilidade com versões anteriores, então não estamos fazendo isso. As alterações na outra função também são pequenas:
function _insert_replace_helper( $table, $data, $format = null, $type = 'INSERT', $ignore = false ) { $this->insert_id = 0; if ( ! in_array( strtoupper( $type ), array( 'REPLACE', 'INSERT' ) ) ) { return false; } $data = $this->process_fields( $table, $data, $format ); if ( false === $data ) { return false; } $formats = $values = array(); foreach ( $data as $value ) { if ( is_null( $value['value'] ) ) { $formats[] = 'NULL'; continue; } $formats[] = $value['format']; $values[] = $value['value']; } $fields = '`' . implode( '`, `', array_keys( $data ) ) . '`'; $formats = implode( ', ', $formats ); // modification for IGNORE keyword if (true == $ignore && 'INSERT' == $type) { $type = 'INSERT IGNORE'; } $sql = "$type INTO `$table` ($fields) VALUES ($formats)"; $this->check_current_query = false; return $this->query( $this->prepare( $sql, $values ) ); }
Por que os desenvolvedores não fazem isso com mais frequência?
Se você precisar de uma consulta personalizada apenas algumas vezes, poderá usar facilmente $wpdb->query()
. Não há necessidade de substituir a classe padrão. Você também pode escrever uma classe personalizada que estenda o padrão, mas não substitua o objeto wpdb. Nesse caso, você usaria $mycustomclass->method()
, mas isso não é o fim do mundo.
Além do óbvio fator de frieza, estender a classe wpdb padrão é algo que deve ser feito no WP e não é hack, então fique à vontade para brincar com isso. Tenha duas coisas em mente:
- quando estiver enviando seu projeto para alguém, não esqueça de incluir o arquivo
db.php
; não estará em nenhum tema ou pasta de plugins - fique de olho nas mudanças no
wp-db.php
, pois elas podem afetar sua classe personalizada (embora isso seja altamente improvável)