Cómo personalizar la clase wpdb y agregar nuevos métodos

Publicado: 2018-07-10

La capa de abstracción de la base de datos de WordPress, más conocida como wpdb, es una clase basada en ezSQL responsable de interactuar con la base de datos. La clase wpdb también es un complemento: una parte del código principal de WP que se puede reemplazar fácilmente por otra pieza de código con una funcionalidad similar (una lista actualizada de complementos está disponible en WP Code Reference).

Modificar la clase #wpdb predeterminada no es complicado. Puede agregar, eliminar o modificar fácilmente solo algunos métodos. No es necesario reemplazar toda la clase. #wordpress

HAGA CLIC PARA TUITAR

Aquí es donde entra en juego un gran error. Las personas perciben "reemplazado" como "escribir mi propia clase de base de datos completa". Afortunadamente, no tiene que escribir toda la clase de la base de datos. Puede tomar la clase existente y agregar, eliminar o modificar solo las funciones que necesita. Y eso es lo que vamos a hacer.

¿Por qué modificar la clase wpdb?

¡Seguramente, wpdb tiene todo lo que necesitas!? Todo el WP está construido sobre él. Técnicamente eso es correcto. Usando el $wpdb->query() puede ejecutar cualquier comando SQL. Pero con esa lógica aplicada, nunca tendríamos ni necesitaríamos métodos como $wpdb->insert() o $wpdb->get_var() . Pero lo hacemos, porque ahorran tiempo, reducen los errores y evitan las consultas incorrectas. Entonces, ¿qué funciones faltan? Eso depende del proyecto en el que estés trabajando. Necesitábamos soporte para estas dos consultas:

INSERT IGNORE INTO tbl_name ...
INSERT INTO tbl_name ... ON DUPLICATE KEY UPDATE ...

Paso #1 - Crea el drop-in

El proceso de creación de una base de datos es simple y el resultado final se integra a la perfección en WP.
Cree un archivo llamado db.php y colóquelo en la carpeta /wp-content/ . Asigne al archivo un encabezado de complemento estándar y cree una clase que amplíe wpdb. Algo como esto:

<?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();

El encabezado es bastante autoexplicativo. El método de construcción se asegura de que creemos una nueva conexión de base de datos una vez que se construye un objeto y utiliza el constructor wpdb original para eso. Esas constantes DB se definen en wp-config.php . Como dijimos al principio, solo estamos agregando algunas funciones y reutilizando todo lo demás. El segundo método test() es puramente para ver si todo funciona correctamente.

Las dos últimas líneas son cruciales. Dado que esta es una clase personalizada, WP no creará el objeto $wpdb automáticamente. Tenemos que hacerlo nosotros mismos. Recuerde usar la palabra clave global porque, de lo contrario, creará una variable local.

Paso n.º 2: pruebe antes de profundizar más

Abra su panel de WP y diríjase a Complementos. Además de las pestañas habituales Todos, Activos e Inactivos (complementos), verá una pestaña Drop-ins y, por arte de magia, nuestra clase de base de datos personalizada.

Dado que el administrador funciona correctamente, sabemos que hicimos un buen trabajo. Nuestra nueva clase ampliada y personalizada ya está aquí y nada ha cambiado. ¡Estupendo! Pero, solo por si acaso, coloque estas tres líneas de código en functions.php del tema (o en algún lugar dentro de un complemento donde se ejecutará de inmediato):

global $wpdb;
$wpdb->test();
die;

Ejecute cualquier página de administrador o de front-end y ¿qué ve? “ Se está ejecutando wpdb extendido. " Perfecto. Ahora para nuestras funciones del mundo real.

Paso #3 – Crear, modificar o reemplazar funciones

La consulta INSERT IGNORE parece bastante fácil de hacer. Ya tenemos $wpdb->insert() así que solo nos falta una palabra. Desafortunadamente, debido a la falta de filtros en los lugares correctos, no serán dos líneas de código.

Si abre wp-db.php y se dirige al método insert() en la línea #2100, verá que usa el método _insert_replace_helper() de la línea #2151. Y esa función no tiene un solo filtro o acción. Tampoco podemos envolver la función porque devuelve inmediatamente el resultado de la consulta y no la consulta en sí misma que podríamos modificar. Gorrón. Tendremos que anular los métodos insert() y _insert_replace_helper() . Agregaremos un parámetro adicional: $ignore . Un valor booleano con el valor predeterminado de false .

public function insert( $table, $data, $format = null, $ignore = false ) {
  return $this->_insert_replace_helper( $table, $data, $format, 'INSERT', $ignore = false );
}

En cualquier otra circunstancia, una función que tenga cinco parámetros sería un buen candidato para convertirlos en una matriz asociativa. Pero queremos compatibilidad con versiones anteriores, así que no lo haremos. Los cambios en la otra función también son menores:

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 qué los desarrolladores no hacen esto con más frecuencia?

Si necesita una consulta personalizada solo unas pocas veces, puede usar fácilmente $wpdb->query() . No hay necesidad de reemplazar la clase predeterminada. También puede escribir una clase personalizada que amplíe la predeterminada pero que no anule el objeto wpdb. En ese caso, usaría $mycustomclass->method() pero ese no es el fin del mundo.

Además del factor de frescura obvio, extender la clase wpdb predeterminada es algo que debe hacerse en WP y no es un truco, así que siéntase libre de jugar con él. Ten en cuenta dos cosas:

  • cuando envíe su proyecto a alguien, no olvide incluir el archivo db.php ; no va a estar en ninguna carpeta de temas o complementos
  • Esté atento a los cambios en wp-db.php , ya que podrían afectar su clase personalizada (aunque eso es muy poco probable)