Recursos Plugin v2.0: unificando dos plugins en uno

plugin recursos

Valencia, 29/08/2026, G.B.
Uno de esos proyectos que llevaba tiempo rondándome era simplificar el mantenimiento de dos plugins de WordPress que, con el tiempo, habían acabado haciendo cosas muy parecidas. La solución: fusionarlos en uno solo, Recursos Plugin v2.0, y de paso aprovechar para resolver algunos problemas técnicos que arrastraba desde hacía tiempo.

Por qué unificar

Mantener dos plugins con funcionalidades solapadas significa duplicar esfuerzo cada vez que hay que tocar algo: dos bases de código que revisar, dos sitios donde aplicar el mismo parche, dos superficies de error. Unificarlos en un único plugin reduce esa carga de mantenimiento y deja un código más coherente y fácil de razonar.

Como en el resto de mis plugins, la premisa se mantiene: cero dependencias externas. Todo el código es PHP nativo, sin librerías de terceros que puedan quedar desactualizadas o introducir vulnerabilidades.

El reto técnico: búsqueda vía GET

La búsqueda de recursos funciona con parámetros en la URL (GET) en lugar de POST. Esto tiene una ventaja clara para el usuario: los resultados de búsqueda son enlazables y compartibles. Puedes copiar la URL después de buscar y enviarla directamente a alguien, o guardarla en marcadores, y al abrirla se reproduce la misma búsqueda.

Para los formularios que sí requieren envío de datos, apliqué el patrón POST/Redirect/GET: el formulario se envía por POST, el servidor procesa la petición y responde con una redirección a una URL GET. Esto evita el clásico problema de que, al recargar la página después de enviar un formulario, el navegador pregunte si quieres «reenviar los datos» —o peor, los reenvíe sin avisar duplicando la acción.

El arreglo de compatibilidad con MySQL

Este plugin hereda el mismo ajuste que ya había aplicado en mi plugin de Autores: cambiar la longitud de las claves de índice a VARCHAR(191).

¿Por qué 191 y no 255? Según lo que he consultado 191 es un límite práctico impuesto por MySQL 5.7 cuando se usa el juego de caracteres utf8mb4 (necesario para soportar emojis y caracteres Unicode completos). Con utf8mb4, cada carácter puede ocupar hasta 4 bytes, y el límite de InnoDB para un índice es de 767 bytes en total. Eso deja un máximo de 191 caracteres para columnas indexadas antes de que MySQL lance un error.

Es uno de esos detalles que no se nota hasta que un día, sin previo aviso, la creación de una tabla falla con un mensaje críptico. Ya solucionado, y de forma consistente en todos mis plugins.

Instrucciones rápidas (desde el panel de control del plugin)

  1. Rellena el formulario de abajo y pulsa «Añadir Recurso» para crear uno nuevo.
  2. Pulsa «Editar» en la tabla para modificar un recurso existente.
  3. Pulsa «Eliminar» para borrarlo (se pedirá confirmación).
  4. Para mostrar los recursos en una página o entrada, usa el shortcode mostrar_recursos (entre corchetes [ ])
    (con buscador y paginación).
  5. Para mostrar solo los 4 recursos más recientes, usa el shortcode ultimos_recursos (entre corchetes [ ])

    Ejemplo con el shortcode para mostrar los últimos recursos añadidos:

    Mega
    Servicio con sede en Nueva Zelanda que destaca por su cifrado de extremo a extremo por defecto (zero-knowledge): ni siquiera Mega puede acceder al contenido de tus archivos. Ofrece 20 GB gratuitos de entrada.
    Dropbox
    Uno de los pioneros del sector, conocido por su sincronización robusta y fiable entre dispositivos. Ofrece funciones interesantes de recuperación de versiones anteriores de archivos y buena integración con apps de terceros.
    OneDrive
    Servicio de Microsoft integrado de forma nativa en Windows y en la suite Office 365. Cómodo si ya trabajas en el ecosistema Microsoft, con edición colaborativa directa en Word, Excel y PowerPoint online.
    pCloud
    Almacenamiento en la nube con sede en Suiza, con opción de pago único de por vida (en lugar de suscripción mensual) y cifrado adicional opcional (pCloud Crypto). Buena alternativa para quien busca privacidad reforzada.

Resultado

Después de un tiempo probándolo en producción, el plugin unificado funciona correctamente. Un solo punto de mantenimiento, búsquedas enlazables, sin reenvíos de formulario molestos, y compatibilidad garantizada con instalaciones MySQL 5.7. Os dejo el enlace de descarga del plugin, por si álguien quiere probarlo:

Descargar plugin (en formato .zip) de mi cuenta de pCloud

Plugin de WordPress para frases aleatorias

Valencia, 29/08/2026, G.B.
Tal y comenté recientemente en este post, aquí va el plugin de WordPress para frases aleatorias. Os paso también el archivo.php.

Recordad que para subir un plugin a WordPress (que no esté en el repositorio, como es el caso), hay que crear una carpeta con el mismo nombre del archivo .php, comprimirlo en .zip y subirlo por FTP o S FTP (mejor esto último) al apartado del escritorio de WordPress «Subir plugin».

Aquí va e código de la primera versión del plugin. Si no consigues verlo correcatente en este post, descarga el archivo frases-aleatorias.zip de mi cuenta de pCloud e instálalo en WordPRess – > Plugins.

<?php
/**
* Plugin Name: Frases Aleatorias Widget
* Description: Widget, shortcode

y panel de administración para gestionar frases (añadir, editar, eliminar). Cada frase incluye enlace de traducción automática al castellano. Sin dependencias externas.
* Version: 2.0
* Author: Puntocomunica.com
*/

if ( ! defined( ‘ABSPATH’ ) ) {
exit; // Salida directa no permitida.
}

define( ‘FA_TABLA’, ‘fa_frases’ ); // se le añadirá el prefijo de WP al usarla

/* ==========================================================
* INSTALACIÓN: crea la tabla y la rellena con las 50 frases
* la primera vez que se activa el plugin.
* ========================================================== */
function fa_activar_plugin() {
global $wpdb;
$tabla = $wpdb->prefix . FA_TABLA;
$charset_collate = $wpdb->get_charset_collate();

$sql = «CREATE TABLE $tabla (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
texto TEXT NOT NULL,
autor VARCHAR(191) NOT NULL,
PRIMARY KEY (id)
) $charset_collate;»;

require_once ABSPATH . ‘wp-admin/includes/upgrade.php’;
dbDelta( $sql );

// Solo se siembran datos si la tabla está vacía (primera instalación)
$total = $wpdb->get_var( «SELECT COUNT(*) FROM $tabla» );
if ( (int) $total === 0 ) {
$frases_iniciales = array(
array( «He who blames others has a long way to go on his journey. He who blames himself is halfway there. He who blames no one has arrived.», «Chinese Proverb» ),
array( «The only way to do great work is to love what you do.», «Steve Jobs» ),
array( «In the middle of difficulty lies opportunity.», «Albert Einstein» ),
array( «It does not matter how slowly you go as long as you do not stop.», «Confucius» ),
array( «Fall seven times, stand up eight.», «Japanese Proverb» ),
array( «The journey of a thousand miles begins with a single step.», «Lao Tzu» ),
array( «Whether you think you can or you think you can’t, you’re right.», «Henry Ford» ),
array( «The best way to predict the future is to create it.», «Abraham Lincoln» ),
array( «Success is not final, failure is not fatal: it is the courage to continue that counts.», «Winston Churchill» ),
array( «Believe you can and you’re halfway there.», «Theodore Roosevelt» ),
array( «Do not go where the path may lead, go instead where there is no path and leave a trail.», «Ralph Waldo Emerson» ),
array( «The mind is everything. What you think you become.», «Buddha» ),
array( «Water which is too pure has no fish.», «Chinese Proverb» ),
array( «A smooth sea never made a skilled sailor.», «African Proverb» ),
array( «He that can have patience can have what he will.», «Benjamin Franklin» ),
array( «You miss 100% of the shots you don’t take.», «Wayne Gretzky» ),
array( «Life is what happens when you’re busy making other plans.», «John Lennon» ),
array( «The only impossible journey is the one you never begin.», «Tony Robbins» ),
array( «Not all those who wander are lost.», «J.R.R. Tolkien» ),
array( «It always seems impossible until it’s done.», «Nelson Mandela» ),
array( «Do what you can, with what you have, where you are.», «Theodore Roosevelt» ),
array( «If you want to go fast, go alone. If you want to go far, go together.», «African Proverb» ),
array( «The best time to plant a tree was 20 years ago. The second best time is now.», «Chinese Proverb» ),
array( «What lies behind us and what lies before us are tiny matters compared to what lies within us.», «Ralph Waldo Emerson» ),
array( «Turn your wounds into wisdom.», «Oprah Winfrey» ),
array( «Knowing yourself is the beginning of all wisdom.», «Aristotle» ),
array( «The unexamined life is not worth living.», «Socrates» ),
array( «He who has a why to live can bear almost any how.», «Friedrich Nietzsche» ),
array( «Out of difficulties grow miracles.», «Jean de La Bruyère» ),
array( «A journey of a thousand miles must begin with a single step.», «Lao Tzu» ),
array( «Even a small star shines in the darkness.», «Finnish Proverb» ),
array( «The bamboo that bends is stronger than the oak that resists.», «Japanese Proverb» ),
array( «Better to light a candle than curse the darkness.», «Chinese Proverb» ),
array( «When the winds of change blow, some build walls, others build windmills.», «Chinese Proverb» ),
array( «Fall down seven times, get up eight.», «Japanese Proverb» ),
array( «One who plants a tree knows they will not sit in its shade.», «Indian Proverb» ),
array( «The nail that sticks out gets hammered down.», «Japanese Proverb» ),
array( «A single arrow is easily broken, but not ten in a bundle.», «Japanese Proverb» ),
array( «He who has never failed has never tried anything new.», «African Proverb» ),
array( «Even the greatest of trees was once a nut who held its ground.», «American Proverb» ),
array( «The river that forgets its source will dry up.», «African Proverb» ),
array( «A bird does not sing because it has an answer, it sings because it has a song.», «Chinese Proverb» ),
array( «Patience is bitter, but its fruit is sweet.», «Aristotle» ),
array( «He who is not courageous enough to take risks will accomplish nothing in life.», «Muhammad Ali» ),
array( «The best preparation for tomorrow is doing your best today.», «H. Jackson Brown Jr.» ),
array( «Success usually comes to those who are too busy to be looking for it.», «Henry David Thoreau» ),
array( «Do not wait for the perfect moment, take the moment and make it perfect.», «Unknown» ),
array( «Great things are done by a series of small things brought together.», «Vincent van Gogh» ),
array( «Perseverance is not a long race; it is many short races one after the other.», «Walter Elliot» ),
array( «You cannot cross the sea merely by standing and staring at the water.», «Rabindranath Tagore» ),
);

foreach ( $frases_iniciales as $f ) {
$wpdb->insert( $tabla, array( ‘texto’ => $f[0], ‘autor’ => $f[1] ) );
}
}
}
register_activation_hook( __FILE__, ‘fa_activar_plugin’ );

/* ==========================================================
* FUNCIONES DE ACCESO A DATOS
* ========================================================== */
function fa_obtener_frases() {
global $wpdb;
$tabla = $wpdb->prefix . FA_TABLA;
return $wpdb->get_results( «SELECT id, texto, autor FROM $tabla ORDER BY id ASC» );
}

function fa_obtener_frases_json() {
$frases = fa_obtener_frases();
$salida = array();
foreach ( $frases as $f ) {
$salida[] = array( ‘texto’ => $f->texto, ‘autor’ => $f->autor );
}
return wp_json_encode( $salida );
}

/* ==========================================================
* RENDERIZADO EN PORTADA (widget y shortcode)
* Incluye enlace de traducción automática al castellano
* (Google Translate), generado por JS según la frase mostrada.
* ========================================================== */
function fa_render_markup_y_script( $instancia_id ) {
ob_start();
?>
<div id=»fa-widget-<?php echo esc_attr( $instancia_id ); ?>» class=»fa-widget» style=»font-family: Georgia, serif; padding: 16px; border-left: 4px solid #444; background: #f9f9f9;»>
<p class=»fa-texto» style=»font-style: italic; font-size: 16px; line-height: 1.5; margin: 0 0 8px 0;»></p>
<p class=»fa-autor» style=»text-align: right; font-weight: bold; margin: 0 0 8px 0;»></p>
<p style=»text-align: right; margin: 0 0 12px 0;»>
<a class=»fa-traducir» href=»#» target=»_blank» rel=»noopener noreferrer» style=»font-size: 13px; text-decoration: underline;»>Traducir al castellano</a>
</p>
<button class=»fa-btn» type=»button» style=»cursor: pointer; padding: 6px 14px; border: none; border-radius: 4px; background: #444; color: #fff; font-size: 14px;»>Otra frase</button>
</div>
<script>
(function() {
var frases = <?php echo fa_obtener_frases_json(); ?>;
var contenedor = document.getElementById(‘fa-widget-<?php echo esc_js( $instancia_id ); ?>’);
if (!contenedor || !frases.length) return;
var elTexto = contenedor.querySelector(‘.fa-texto’);
var elAutor = contenedor.querySelector(‘.fa-autor’);
var elTraducir = contenedor.querySelector(‘.fa-traducir’);
var elBtn = contenedor.querySelector(‘.fa-btn’);

function mostrarFraseAleatoria() {
var indice = Math.floor(Math.random() * frases.length);
var frase = frases[indice];
elTexto.textContent = ‘\u201C’ + frase.texto + ‘\u201D’;
elAutor.textContent = ‘\u2014 ‘ + frase.autor;
elTraducir.href = ‘https://translate.google.com/?sl=en&tl=es&text=’ + encodeURIComponent(frase.texto) + ‘&op=translate’;
}

elBtn.addEventListener(‘click’, mostrarFraseAleatoria);
mostrarFraseAleatoria();
})();
</script>
<?php
return ob_get_clean();
}

function fa_shortcode_frases_aleatorias() {
static $contador = 0;
$contador++;
return fa_render_markup_y_script( ‘sc-‘ . $contador );
}
add_shortcode( ‘frases_aleatorias’, ‘fa_shortcode_frases_aleatorias’ );

class FA_Widget_Frases extends WP_Widget {
public function __construct() {
parent::__construct(
‘fa_widget_frases’,
__( ‘Frase Aleatoria’, ‘frases-aleatorias’ ),
array( ‘description’ => __( ‘Muestra una frase célebre al azar, con enlace de traducción y botón para cambiarla.’, ‘frases-aleatorias’ ) )
);
}

public function widget( $args, $instance ) {
echo $args[‘before_widget’];
if ( ! empty( $instance[‘titulo’] ) ) {
echo $args[‘before_title’] . apply_filters( ‘widget_title’, $instance[‘titulo’] ) . $args[‘after_title’];
}
echo fa_render_markup_y_script( ‘widget-‘ . $this->id );
echo $args[‘after_widget’];
}

public function form( $instance ) {
$titulo = ! empty( $instance[‘titulo’] ) ? $instance[‘titulo’] : __( ‘Frase del día’, ‘frases-aleatorias’ );
?>
<p>
<label for=»<?php echo esc_attr( $this->get_field_id( ‘titulo’ ) ); ?>»><?php _e( ‘Título:’, ‘frases-aleatorias’ ); ?></label>
<input class=»widefat» id=»<?php echo esc_attr( $this->get_field_id( ‘titulo’ ) ); ?>» name=»<?php echo esc_attr( $this->get_field_name( ‘titulo’ ) ); ?>» type=»text» value=»<?php echo esc_attr( $titulo ); ?>»>
</p>
<?php
}

public function update( $new_instance, $old_instance ) {
$instance = array();
$instance[‘titulo’] = ( ! empty( $new_instance[‘titulo’] ) ) ? sanitize_text_field( $new_instance[‘titulo’] ) : »;
return $instance;
}
}
add_action( ‘widgets_init’, function () {
register_widget( ‘FA_Widget_Frases’ );
} );

/* ==========================================================
* PANEL DE ADMINISTRACIÓN: listar, añadir, editar, eliminar
* ========================================================== */
add_action( ‘admin_menu’, function () {
add_menu_page(
‘Frases Aleatorias’,
‘Frases Aleatorias’,
‘manage_options’,
‘fa-frases’,
‘fa_pagina_admin’,
‘dashicons-format-quote’,
58
);
} );

function fa_pagina_admin() {
if ( ! current_user_can( ‘manage_options’ ) ) {
return;
}

global $wpdb;
$tabla = $wpdb->prefix . FA_TABLA;

/* ———- Procesar acciones enviadas por formulario ———- */
if ( isset( $_POST[‘fa_accion’] ) && check_admin_referer( ‘fa_guardar_frase’, ‘fa_nonce’ ) ) {
$texto = isset( $_POST[‘fa_texto’] ) ? sanitize_textarea_field( wp_unslash( $_POST[‘fa_texto’] ) ) : »;
$autor = isset( $_POST[‘fa_autor’] ) ? sanitize_text_field( wp_unslash( $_POST[‘fa_autor’] ) ) : »;

if ( $texto !== » && $autor !== » ) {
if ( $_POST[‘fa_accion’] === ‘crear’ ) {
$wpdb->insert( $tabla, array( ‘texto’ => $texto, ‘autor’ => $autor ) );
echo ‘<div class=»notice notice-success is-dismissible»><p>Frase añadida.</p></div>’;
} elseif ( $_POST[‘fa_accion’] === ‘actualizar’ && ! empty( $_POST[‘fa_id’] ) ) {
$wpdb->update( $tabla, array( ‘texto’ => $texto, ‘autor’ => $autor ), array( ‘id’ => (int) $_POST[‘fa_id’] ) );
echo ‘<div class=»notice notice-success is-dismissible»><p>Frase actualizada.</p></div>’;
}
} else {
echo ‘<div class=»notice notice-error is-dismissible»><p>El texto y el autor no pueden estar vacíos.</p></div>’;
}
}

if ( isset( $_GET[‘fa_eliminar’] ) && check_admin_referer( ‘fa_eliminar_frase’ ) ) {
$wpdb->delete( $tabla, array( ‘id’ => (int) $_GET[‘fa_eliminar’] ) );
echo ‘<div class=»notice notice-success is-dismissible»><p>Frase eliminada.</p></div>’;
}

/* ———- ¿Estamos editando una frase? ———- */
$editando = null;
if ( isset( $_GET[‘fa_editar’] ) ) {
$editando = $wpdb->get_row( $wpdb->prepare( «SELECT * FROM $tabla WHERE id = %d», (int) $_GET[‘fa_editar’] ) );
}

$frases = fa_obtener_frases();
?>
<div class=»wrap»>
<h1>Frases Aleatorias</h1>
<p>Shortcode: <code>

</code> · También disponible como widget en Apariencia → Widgets.</p>

<h2><?php echo $editando ? ‘Editar frase’ : ‘Añadir nueva frase’; ?></h2>
<form method=»post» style=»max-width: 600px;»>
<?php wp_nonce_field( ‘fa_guardar_frase’, ‘fa_nonce’ ); ?>
<input type=»hidden» name=»fa_accion» value=»<?php echo $editando ? ‘actualizar’ : ‘crear’; ?>»>
<?php if ( $editando ) : ?>
<input type=»hidden» name=»fa_id» value=»<?php echo esc_attr( $editando->id ); ?>»>
<?php endif; ?>

<table class=»form-table»>
<tr>
<th><label for=»fa_texto»>Texto (inglés)</label></th>
<td><textarea name=»fa_texto» id=»fa_texto» rows=»3″ class=»large-text» required><?php echo $editando ? esc_textarea( $editando->texto ) : »; ?></textarea></td>
</tr>
<tr>
<th><label for=»fa_autor»>Autor</label></th>
<td><input type=»text» name=»fa_autor» id=»fa_autor» class=»regular-text» required value=»<?php echo $editando ? esc_attr( $editando->autor ) : »; ?>»></td>
</tr>
</table>

<?php submit_button( $editando ? ‘Actualizar frase’ : ‘Añadir frase’ ); ?>
<?php if ( $editando ) : ?>
<a href=»<?php echo esc_url( admin_url( ‘admin.php?page=fa-frases’ ) ); ?>» class=»button»>Cancelar edición</a>
<?php endif; ?>
</form>

<h2>Frases existentes (<?php echo count( $frases ); ?>)</h2>
<table class=»widefat striped»>
<thead>
<tr>
<th style=»width: 55%;»>Texto</th>
<th>Autor</th>
<th style=»width: 160px;»>Acciones</th>
</tr>
</thead>
<tbody>
<?php foreach ( $frases as $f ) : ?>
<tr>
<td><?php echo esc_html( $f->texto ); ?></td>
<td><?php echo esc_html( $f->autor ); ?></td>
<td>
<a href=»<?php echo esc_url( admin_url( ‘admin.php?page=fa-frases&fa_editar=’ . $f->id ) ); ?>»>Editar</a>
|
<a href=»<?php echo esc_url( wp_nonce_url( admin_url( ‘admin.php?page=fa-frases&fa_eliminar=’ . $f->id ), ‘fa_eliminar_frase’ ) ); ?>»
onclick=»return confirm(‘¿Eliminar esta frase?’);» style=»color: #b32d2e;»>Eliminar</a>
|
<a href=»https://translate.google.com/?sl=en&tl=es&text=<?php echo rawurlencode( $f->texto ); ?>&op=translate» target=»_blank» rel=»noopener noreferrer»>Traducir</a>
</td>
</tr>
<?php endforeach; ?>
<?php if ( empty( $frases ) ) : ?>
<tr><td colspan=»3″>Todavía no hay frases.</td></tr>
<?php endif; ?>
</tbody>
</table>
</div>
<?php
}

Cómo crear un tema hijo en WordPress: el caso de Twenty Seventeen

Child Theme

Si mantienes un sitio en WordPress durante años, tarde o temprano te enfrentas a un problema clásico: has personalizado el CSS, quizás también el header.php, y cada actualización del tema te obliga a repetir esos cambios desde cero. La solución habitual es un tema hijo (o child theme), y en este artículo repaso el proceso completo que he seguido en Indaga.net, incluyendo las dudas que me han surgido por el camino (hacía mucho tiempo que no hacía esto…).

Comentar que todo el proceso sirve para cualquier tema o theme de WordPress, no solo para Twenty Seventeen.

¿Qué es un tema hijo y por qué usarlo?

Un tema hijo es un tema que hereda toda la funcionalidad y las plantillas de otro tema, el «padre», pero permite sobreescribir archivos concretos sin tocar el original. La gran ventaja es que las actualizaciones del tema padre no borran tus personalizaciones, siempre que estén en el sitio correcto.

En mi caso, el tema padre es Twenty Seventeen, y el objetivo principal era mantener un CSS personalizado sin perderlo cada vez que WordPress actualiza el tema.

Estructura mínima necesaria

Contra lo que podría parecer, no hace falta replicar toda la estructura de carpetas del tema padre. Con dos archivos en la raíz ya es suficiente para tener un tema hijo funcional:

wp-content/themes/tema-hijo/
├── style.css
└── functions.php

El stylee.css necesita una cabecera específica que le indica a WordPress cuál es el tema padre:

/*
 Theme Name:   Indaga Child
 Template:     twentyseventeen
 Version:      1.0.0
*/

Y el functions.php se encarga de encolar primero el CSS del padre y después el propio, para que las reglas personalizadas puedan sobreescribir las originales:

<?php
add_action( 'wp_enqueue_scripts', 'indaga_child_enqueue_styles' );
function indaga_child_enqueue_styles() {
    wp_enqueue_style( 'twentyseventeen-parent-style', get_template_directory_uri() . '/style.css' );
    wp_enqueue_style( 'indaga-child-style',
        get_stylesheet_directory_uri() . '/style.css',
        array( 'twentyseventeen-parent-style' ),
        wp_get_theme()->get('Version')
    );
}

Con esto ya se puede activar el tema hijo desde Apariencia → Temas.

Carpetas opcionales

Solo tiene sentido crearlas si de verdad se van a usar:

  • /assets/css/: para separar el CSS en varios archivos en lugar de amontonarlo todo en style.css.
  • /assets/js/: si se añade JavaScript propio.
  • /inc/: para dividir functions.php en varios archivos PHP si crece mucho.
  • /template-parts/: solo si se van a sobreescribir plantillas concretas del padre (la ruta y el nombre de archivo deben coincidir exactamente con los del tema original para que WordPress detecte la sustitución).
  • /languages/: si se traducen cadenas propias del tema hijo.

La duda del «AdSense desaparecido»

Al activar el tema hijo, me surgió una duda: si tuviera código de AdSense no aparecía en el sitio, y mi primer instinto fue pensar que si lo tuviera, tendría que copiar el header.php del padre al hijo para «recuperarlo».

Aquí está el matiz importante: WordPress hereda automáticamente los archivos de plantilla que el hijo no tiene. Si el tema hijo no incluye su propio header.php, WordPress usa sin más el header.php del tema padre, con todo su contenido, incluyendo cualquier código insertado directamente en él. Así que, en teoría, no debería haber ninguna pérdida solo por activar el hijo.

Antes de tocar nada, conviene descartar por orden:

  1. Caché activa. Con un plugin de caché como WP Fastest Cache, es fácil estar viendo una versión antigua de la página. Vaciar la caché y probar en incógnito resuelve muchos falsos problemas de este tipo
  2. Que el tema activo sea realmente el hijo
  3. Ver el código fuente de la página (Ctrl+U) para comprobar si el fragmento está presente en el HTML aunque no se vea (podría ser un bloqueador de anuncios del propio navegador, no un problema de plantilla)

En este caso concreto, el sitio todavía estaba en fase de revisión y por eso no se mostraban anuncios: no era un problema del tema hijo en absoluto.

¿Qué pasa si actualizo el tema padre?

Esta es probablemente la pregunta más importante de todo el proceso, y la respuesta no es igual para todos los archivos:

  • functions.php del tema hijo: totalmente a salvo. Es un archivo propio, en su propia carpeta, y una actualización del tema padre jamás lo toca.
  • header.php / footer.php editados directamente en el tema padre: aquí está el riesgo real. Si el código de AdSense (o cualquier otra personalización) se editó directamente en el header.php de Twenty Seventeen, una actualización del tema sustituye ese archivo por el original del repositorio, y esos cambios se pierden.

La solución es sencilla: copiar el header.php (y cualquier otro archivo modificado directamente en el padre) a la carpeta del tema hijo, manteniendo el mismo nombre. A partir de ese momento, la herencia de plantillas hace que WordPress use la versión del hijo en lugar de la del padre, y esos archivos quedan protegidos frente a futuras actualizaciones.

El detalle estético: la miniatura en blanco

Un último detalle menor pero visible: al crear el tema hijo desde cero, la miniatura que aparece en Apariencia → Temas queda en blanco. Esto es simplemente porque falta el archivo screenshot.png en la raíz del tema; WordPress no lo genera automáticamente.

Basta con subir una imagen (idealmente en proporción 4:3, por ejemplo 1200×900 px) con ese nombre exacto a la raíz del tema hijo. No requiere ninguna declaración adicional en style.css ni en functions.php; WordPress la detecta solo por estar ahí.

Así es como queda el mío:

child-theme-indaga

Resumen del proceso

  1. Crear style.css y functions.php en wp-content/themes/tema-hijo/ (en mi caso wp-content/themes/indaga/ al haber llamado así al tema hijo o child theme.
  2. Activar el tema hijo desde el escritorio de WordPress.
  3. Antes de dar por buena cualquier «desaparición» de contenido, descartar caché y confirmar el tema activo.
  4. Copiar a la carpeta del hijo cualquier archivo de plantilla (header.php, footer.php, etc.) que se haya editado directamente en el tema padre, para blindarlo frente a actualizaciones.
  5. Añadir un screenshot.png para que la miniatura del tema deje de aparecer en blanco.

Con estos pasos, el sitio queda preparado para recibir actualizaciones de Twenty Seventeen sin sobresaltos, manteniendo intactas todas las personalizaciones (que son bastantes…).

Una actualización de «Record of Consent Extension for Complianz» provoca un error crítico en WordPress

Valencia, 11/08/2026, G.B.
Una actualización reciente del plugin Record of Consent Extension for Complianz, el complemento gratuito que añade registro de consentimientos al plugin Complianz, ha dejado inaccesibles varios paneles de administración de WordPress tras instalarse. El fallo se ha detectado en varios sitios, incluidos algunos que gestiono, donde el escritorio de WordPress quedó bloqueado por un error crítico inmediatamente después de la actualización automática del plugin, mientras que la parte pública de las webs siguió funcionando con normalidad.

Cómo se detectó el problema

El síntoma es el clásico «error crítico» de WordPress, pero limitado al escritorio: el acceso a wp-admin se interrumpía por completo, sin más detalle visible para el usuario salvo que ha ocurrido un problema técnico, mientras que la web pública seguía cargando sin incidencias. Al revisar por SFTP la carpeta wp-content/plugins, el plugin con la fecha de modificación más reciente —coincidiendo con el día anterior a la incidencia— resultó ser precisamente esta extensión de Complianz. Renombrar su carpeta (lo que equivale a desactivarlo a la fuerza, ya que WordPress no puede cargar un plugin cuya ruta ha cambiado) restableció el acceso al instante, confirmando que el origen del fallo estaba ahí. Tras verificarlo, se optó por eliminar el plugin directamente en lugar de reactivarlo.

Qué dice el registro de cambios oficial

El historial de versiones publicado en el repositorio de WordPress.org confirma que este no es el primer episodio de errores fatales en el plugin: versiones anteriores tuvieron que corregir expresamente una llamada a un método inexistente que provocaba un error fatal en el almacenamiento de consentimientos, así como un fallo por el que la tabla de base de datos no se creaba durante el asistente de configuración inicial, lo que impedía guardar los registros de consentimiento. Es decir, se trata de un complemento con antecedentes de regresiones críticas entre versiones, algo a tener en cuenta por quienes lo usan en producción.

En el momento de escribir estas líneas, el repositorio oficial de WordPress.org señala la versión 2.1 como la más reciente publicada, sin que se haya localizado en foros o canales públicos un reporte específico que documente esta incidencia concreta con fecha de ayer; es posible que se trate de un problema de compatibilidad puntual con la configuración de PHP, caché o el propio Complianz en los servidores afectados, y no de un fallo generalizado reportado aún por la comunidad.

Qué hacer si os ha pasado lo mismo

Si una web deja de responder justo después de que WordPress actualice automáticamente un plugin, el primer paso es siempre identificar por SFTP o FTP qué carpeta de wp-content/plugins tiene la fecha de modificación más reciente y renombrarla temporalmente (añadiendo, por ejemplo, _OLD al nombre de la carpeta); esto basta para que WordPress lo desactive sin poder acceder al panel, y suele restaurar el acceso en segundos si el plugin es efectivamente el causante. Conviene además revisar los logs de error de PHP del hosting (error_log o el panel de errores que ofrezca el proveedor) para confirmar la causa exacta antes de decidir si se reinstala una versión anterior, se contacta con el soporte del desarrollador o, como en este caso, se opta por eliminarlo y buscar una alternativa.

Import Excel to Table: un plugin de WordPress sin dependencias para convertir un Excel (o una hoja de cálculo) en una tabla con shortcode

NOTA: De los 3 sitios en los que he probado este plugin, solo en Indaga.net (aquí) se recarga la página del plugin después de la importación. No obstante, funciona en todos. Puede que sea un conflicto entre plugins o que los otros sitios utilizan Gutenberg e Indaga,net no; lo veré más adelante…

Lo actualizo a la versión 1.4.1. Ahora también está la opción de mostrar todos los registros.

Valencia, 10/08/2026, G.B.
Hay una necesidad que se repite mucho en sitios WordPress pequeños y medianos: alguien tiene un listado en Excel o en LibreOffice Calc (un directorio de contactos, un catálogo, una lista de recursos) y quiere que aparezca como una tabla navegable en una página web, sin tener que copiar y pegar HTML cada vez que cambian los datos. Para cubrir ese caso he desarrollado Import Excel to Table, un plugin de WordPress que importa archivos .xlsx o .ods a una tabla propia de la base de datos y los muestra mediante shortcode, con ordenación por columna, paginación y enlaces automáticos.

Un ejemplo

TítuloAutorEditorialURL reseña
¡Guardias! ¡Guardias!Terry PratchettRandom House Mondadori, 2008.http://unlibrojuntoalfuego.blogspot.com/2016/01/guardias-guardias-mundodisco-pratchett.html
¡Voto a Bríos! (Jingo)Terry Pratchetthttps://mundodisco.fandom.com/es/wiki/Voto_a_bros!
A la sombra del granado .Tariq Alí.Círculo de lectores
A Stroke of the Pen. The lost StoriesTerry Pratchetthttps://en.wikipedia.org/wiki/A_Stroke_of_the_Pen:_The_Lost_Stories
Abdul Bashur, soñador de navíosÁlvaro Mutis.Círculo de Lectores.https://a7side.com/book/abdul-bashur-sonador-de-navios/
África lloraAlberto Vázquez-Figueroa.Círculo de lectoreshttps://www.casadellibro.com/libro-africa-llora/9788497931700/943432
Al oeste de BabiloniaEduardo Garrigues.Círculo de lectores.https://www.casadellibro.com/libro-al-oeste-de-babilonia/9788401327506/639724
Alexandros I: El hijo del sueño .Valerio Massimo Manfredi.(ebook).https://www.casadellibro.com/libro-alexandros-i3a-el-hijo-del-sueno/9788497594400/884139
Alexandros II: Las Arenas de Amón .Valerio Massimo Manfredi.(ebook).https://www.casadellibro.com/libro-alexandros-ii-las-arenas-de-amon/9788497594417/884141
Alexandros III: Los Confines del Mundo .Valerio Massimo Manfredi.(ebook).https://www.casadellibro.com/libro-alexandros-iii-el-confin-del-mundo/9788497594394/884142
Alí en el país de las maravillasAlberto Vázquez-Figueroa.Plaza & Janéshttps://www.lecturalia.com/libro/5348/ali-en-el-pais-de-las-maravillas
Alice in Wonderland and Through the Looking-Glass and What alice Found thereLewis Carrollhttps://www.goodreads.com/work/quotes/2375385-alice-s-adventures-in-wonderland-through-the-looking-glass-and-what-a
AzazelIsaac Asimov.Cículo de lectores.http://www.lecturalia.com/libro/67454/azazel
Bella y oscuraRosa Monterohttps://www.lecturalia.com/libro/4527/bella-y-oscura
BrujeríasTerry Pratchett.Ver reseña:https://www.casadellibro.com/libro-brujerias-mundodisco-6--las-brujas-2/9788497593182/873695
Buenos días, pereza (Estrategias para sobrevivir en el trabajo )Corinne Maier.Círculo de lectores.http://www.lecturalia.com/libro/49083/buenos-dias-pereza
Cachito (Un asunto de honor)Arturo Pérez-Reverte.Alfaguara de bolsillohttps://www.perezreverte.com/libro/51/un-asunto-de-honor-cachito/
Caperucita en ManhattanCarmen Martín Gaite.Siruela.https://www.actualidadliteratura.com/caperucita-en-manhattan/
Carpe Diem: confesiones de un pollo de barraAlfonso Ussía.S.A. Ediciones B Castellanohttps://www.casadellibro.com/libro-carpe-diem-confesiones-de-un-pollo-de-barra/9788466609753/831217
Carpe Diem: Confesiones de un pollo de barraAlfonso Usía.Círculo de lectoreshttps://www.casadellibro.com/libro-carpe-diem-confesiones-de-un-pollo-de-barra/9788466609753/831217
Carta del fin del mundo - Jose Manuel Fajardo - Ediciones B - 1996.http://www.lecturalia.com/libro/30952/carta-del-fin-del-mundo
CavadoresTerry Pratchett.ebooks#3
CienfuegosAlberto Vázquez-Figueroa.(ver)https://www.casadellibro.com/libro-cienfuegosvol-i/9788497595766/901015
Cienfuegos 2Alberto Vázquez-Figueroa.Círculo de Lectoreshttps://www.casadellibro.com/libro-cienfuegos-2--caribes/mkt0006157410/12058110
Creative Personal BrandingJulen Salenbacherhttps://www.casadellibro.com/libro-creative-personal-branding-la-estrategia-de-marcar-tendencia/9788416583874/5228635

Total de registros: 234

El problema de partida: nada de dependencias externas

La primera versión se apoyaba en PhpSpreadsheet, la librería PHP de referencia para leer hojas de cálculo. Funciona muy bien, pero arrastra una carpeta vendor/ de varios megabytes y miles de archivos pequeños, que hay que generar con Composer e instalar en el servidor. En un hosting compartido con límite de número de archivos —como suele pasar cuando alojas varias webs en el mismo plan— eso puede ser un problema real, y además complica el despliegue si solo tienes acceso por SFTP, sin terminal.

La solución fue reescribir el lector de hojas de cálculo desde cero, apoyándome únicamente en extensiones que ya vienen integradas en PHP: ZipArchive, SimpleXML y DOM. Un archivo .xlsx o .ods no es más que un ZIP con XML dentro, así que se puede leer directamente sin ninguna librería externa. El resultado: cero dependencias, ninguna carpeta que subir aparte del propio plugin, y una copia por SFTP es suficiente para desplegarlo.

Qué hace

  • Importa .xlsx y .ods desde el panel de administración, usando la primera fila del archivo como encabezados de columna.
  • Admite varias importaciones independientes, cada una con su propio identificador. Un directorio de contactos, un catálogo de productos y una lista de recursos pueden convivir en el mismo sitio sin pisarse: reimportar uno de ellos no afecta a los demás.
  • Sustituye los datos de forma transaccional: si la importación falla a mitad de proceso, no se pierden ni los datos antiguos ni se queda la tabla a medias.
  • Muestra cada importación con su propio shortcode, indicando su identificador:

    No hay datos para mostrar (identificador: contactos).

    ,

    No hay datos para mostrar (identificador: catalogo).

    , etc. Pueden convivir varios en la misma página, cada uno con su propio control de orden y paginación, sin interferir entre sí. Con estas funciones:
    • Ordenación por columna (ascendente/descendente).
    • Paginación (25 registros por página por defecto, configurable).
    • Enlaces automáticos: si una celda contiene un correo o una URL —ya sea porque LibreOffice/Excel la convirtió en hipervínculo al escribirla, o simplemente porque el texto tiene forma de email o dirección web—, se muestra como un enlace clicable.
    • Fechas y horas con formato español (DD/MM/AAAA, HH:MM), en lugar del formato ISO interno que usan estos archivos por dentro.
  • Panel de administración con listado de importaciones: identificador, número de registros, fecha de la última importación, el shortcode ya escrito para copiar, vista previa de los datos y borrado individual (o de todas a la vez).
  • Control de acceso opcional: si los datos son sensibles, se puede restringir la visualización a usuarios con sesión iniciada.

Seguridad

Al ser un plugin que acepta subida de archivos y muestra datos en el frontend, se ha cuidado especialmente:

  • Solo usuarios con capacidad manage_options pueden importar o borrar datos, con verificación de nonce (CSRF) en cada acción.
  • El archivo subido se valida por extensión y por tipo MIME real (no basta con renombrar un archivo a .xlsx), con un límite de tamaño de 5 MB.
  • Todo el HTML de salida se escapa correctamente, y tanto los parámetros de ordenación como el identificador de cada importación se validan contra listas seguras antes de usarse en ninguna consulta.
  • Cada registro guardado lleva un hash de integridad que se comprueba al leerlo, como salvaguarda frente a manipulaciones directas de la base de datos.

Compatibilidad

  • WordPress: declarado a partir de la versión 5.0, aunque en la práctica solo usa funciones muy estables de la API ($wpdb, dbDelta(), wp_nonce_field(), add_shortcode()…) disponibles desde mucho antes. Funciona igual con el editor de bloques o con Classic Editor, ya que no depende de Gutenberg.
  • PHP: declarado a partir de 7.4, pero el código en sí no usa ninguna sintaxis exclusiva de PHP 8.x (nada de match(), propiedades readonly, operador nullsafe…), así que en la práctica sería compatible desde PHP 7.0. Probado sin avisos de deprecación hasta PHP 8.3.
  • Extensiones PHP necesarias: zip, SimpleXML, DOM y fileinfo — las cuatro vienen activadas por defecto en la gran mayoría de hostings. Si alguna faltara, el plugin lo detecta y avisa en el panel de administración en vez de fallar en silencio.
  • Actualización sin fricción: si ya tenías datos importados con una versión anterior del plugin (de cuando solo existía una tabla), al actualizar por SFTP se conservan automáticamente bajo el identificador default, y el shortcode

    No hay datos para mostrar (identificador: default).

    sin atributo sigue funcionando exactamente igual que antes.

Plugins similares en el repositorio

Antes de escribir el plugin conviene mirar qué hay ya disponible. En el ecosistema de WordPress existen varias alternativas con un planteamiento parecido, aunque ninguna comparte exactamente el mismo enfoque:

  • wpDataTables — el más completo y establecido del mercado. Importa .xls, .ods y .xlsx y genera tablas totalmente personalizables, con filtros avanzados, gráficos y edición tipo Excel en el frontend. Es mucho más potente que Import Excel to Table, pero también mucho más pesado: es de pago (el plan gratuito es limitado) y no está pensado para minimizar dependencias.
  • WP Convert Excel Data To Table And DB — es el que más se parece en planteamiento: importa el Excel a la base de datos de WordPress, gestiona los registros desde un menú propio y permite editarlos manualmente. No es posible comprobar cómo está construido por dentro, pero conceptualmente es el competidor más cercano.
  • Excel Tables (de WP Missing) — más sencillo: se sube el archivo a la biblioteca de medios, se convierte automáticamente en tabla y se inserta con shortcode. Gratuito y minimalista, pero sin ordenación ni paginación configurables.
  • WP Table Manager — apuesta por sincronizar la tabla de forma continua con el archivo Excel de origen, en vez de hacer una importación puntual.

Ninguno de ellos presume de estar construido sin dependencias externas: lo habitual es que usen PhpSpreadsheet u otra librería similar por debajo. Esa es la principal diferencia de Import Excel to Table frente a las alternativas: mismo resultado funcional que herramientas mucho más grandes, pero sin carpeta vendor/ que instalar, pensado explícitamente para hostings con límite de archivos y despliegue solo por SFTP.

Limitaciones a tener en cuenta

Por ser un lector escrito a mano en lugar de una librería completa, hay algunos casos que no cubre: solo lee la primera hoja del libro, no evalúa fórmulas (toma el último valor calculado guardado en el archivo), y no procesa celdas combinadas ni archivos .xls del formato binario antiguo (hay que convertirlos antes a .xlsx). Para el caso de uso habitual —una o varias tablas de datos simples que se actualizan de vez en cuando— no supone ningún problema.

Un ejemplo insertando el shortcode

TítuloAutorEditorialURL reseña
¡Guardias! ¡Guardias!Terry PratchettRandom House Mondadori, 2008.http://unlibrojuntoalfuego.blogspot.com/2016/01/guardias-guardias-mundodisco-pratchett.html
¡Voto a Bríos! (Jingo)Terry Pratchetthttps://mundodisco.fandom.com/es/wiki/Voto_a_bros!
A la sombra del granado .Tariq Alí.Círculo de lectores
A Stroke of the Pen. The lost StoriesTerry Pratchetthttps://en.wikipedia.org/wiki/A_Stroke_of_the_Pen:_The_Lost_Stories
Abdul Bashur, soñador de navíosÁlvaro Mutis.Círculo de Lectores.https://a7side.com/book/abdul-bashur-sonador-de-navios/
África lloraAlberto Vázquez-Figueroa.Círculo de lectoreshttps://www.casadellibro.com/libro-africa-llora/9788497931700/943432
Al oeste de BabiloniaEduardo Garrigues.Círculo de lectores.https://www.casadellibro.com/libro-al-oeste-de-babilonia/9788401327506/639724
Alexandros I: El hijo del sueño .Valerio Massimo Manfredi.(ebook).https://www.casadellibro.com/libro-alexandros-i3a-el-hijo-del-sueno/9788497594400/884139
Alexandros II: Las Arenas de Amón .Valerio Massimo Manfredi.(ebook).https://www.casadellibro.com/libro-alexandros-ii-las-arenas-de-amon/9788497594417/884141
Alexandros III: Los Confines del Mundo .Valerio Massimo Manfredi.(ebook).https://www.casadellibro.com/libro-alexandros-iii-el-confin-del-mundo/9788497594394/884142
Alí en el país de las maravillasAlberto Vázquez-Figueroa.Plaza & Janéshttps://www.lecturalia.com/libro/5348/ali-en-el-pais-de-las-maravillas
Alice in Wonderland and Through the Looking-Glass and What alice Found thereLewis Carrollhttps://www.goodreads.com/work/quotes/2375385-alice-s-adventures-in-wonderland-through-the-looking-glass-and-what-a
AzazelIsaac Asimov.Cículo de lectores.http://www.lecturalia.com/libro/67454/azazel
Bella y oscuraRosa Monterohttps://www.lecturalia.com/libro/4527/bella-y-oscura
BrujeríasTerry Pratchett.Ver reseña:https://www.casadellibro.com/libro-brujerias-mundodisco-6--las-brujas-2/9788497593182/873695
Buenos días, pereza (Estrategias para sobrevivir en el trabajo )Corinne Maier.Círculo de lectores.http://www.lecturalia.com/libro/49083/buenos-dias-pereza
Cachito (Un asunto de honor)Arturo Pérez-Reverte.Alfaguara de bolsillohttps://www.perezreverte.com/libro/51/un-asunto-de-honor-cachito/
Caperucita en ManhattanCarmen Martín Gaite.Siruela.https://www.actualidadliteratura.com/caperucita-en-manhattan/
Carpe Diem: confesiones de un pollo de barraAlfonso Ussía.S.A. Ediciones B Castellanohttps://www.casadellibro.com/libro-carpe-diem-confesiones-de-un-pollo-de-barra/9788466609753/831217
Carpe Diem: Confesiones de un pollo de barraAlfonso Usía.Círculo de lectoreshttps://www.casadellibro.com/libro-carpe-diem-confesiones-de-un-pollo-de-barra/9788466609753/831217
Carta del fin del mundo - Jose Manuel Fajardo - Ediciones B - 1996.http://www.lecturalia.com/libro/30952/carta-del-fin-del-mundo
CavadoresTerry Pratchett.ebooks#3
CienfuegosAlberto Vázquez-Figueroa.(ver)https://www.casadellibro.com/libro-cienfuegosvol-i/9788497595766/901015
Cienfuegos 2Alberto Vázquez-Figueroa.Círculo de Lectoreshttps://www.casadellibro.com/libro-cienfuegos-2--caribes/mkt0006157410/12058110
Creative Personal BrandingJulen Salenbacherhttps://www.casadellibro.com/libro-creative-personal-branding-la-estrategia-de-marcar-tendencia/9788416583874/5228635

Total de registros: 234

NOTA: Import Excel to Table nació como una prueba en este mismo sitio, indaga.net, antes de valorar su uso en otros proyectos con necesidades de datos tabulares más específicas.

Descargar archivo .zip que he subido y compartido en mi cuenta de pCloud. Aunque pCloud es seguro, comprueba siempre que los archivos que descargues estén limpios de virus: import-excel-to-table.zip

Plugin de WordPress Comet Cache: lo borro

Una nota rápida…

Valencia, 03/08/2026
Parece ser que el plugin Comet Cache lleva desde 2017 sin actualizarse realmente, aunque sigue en el repositorio de plugins de WordPress (situación realmente extraña. ..). Veamos:

  • Última actualización real: 2017 (versión 170220). La ficha muestra «actualizado hace 1 año» porque WordPress.org a veces refresca metadatos aunque el código no cambie, pero el changelog no miente: ocho años sin tocar el core del plugin.
  • Las reseñas más recientes (incluida una de diciembre de 2025) lo describen literalmente como un «zombie» que aparece como «actualizado recientemente» en el listado de plugins pero cuya última versión real sigue siendo la de 2017. wordpress
  • El «Tested up to 6.9.5» que aparece en la ficha es automático/cosmético, no significa que alguien lo haya probado de verdad contra esa versión de WP.
  • Un plugin de caché sin mantenimiento es un riesgo de seguridad mayor que uno normal, porque toca puntos sensibles: wp-config.php, advanced-cache.php, reglas de .htaccess, interceptación de requests antes de que cargue WordPress. Si aparece una vulnerabilidad ahí, nadie la va a parchear.

Por eso y por lo que acabo de leer lo he desinstalado,  tanto aquí como en Puntocomunica.com,. Mantengo Autoptimize e instala el plugin WP Fastest Cache.

Creo que es una buena elección. Ya veremos…

🔥🧱Qué es un cortafuegos para tu web y por qué Wordfence te lo pone fácil (en WordPress)

Imagina que tu web de WordPress es una tienda física. Tiene una puerta de entrada por la que pasan clientes todos los días: algunos vienen a comprar, a leer, a contactarte. Pero también hay quien se acerca con malas intenciones: intentar forzar la caja registradora, colarse por la trastienda o hacerse pasar por un empleado.

Un firewall de aplicaciones web, o WAF por sus siglas en inglés, es básicamente el portero de tu tienda. Revisa a todo el que entra antes de dejarlo pasar, y si detecta que alguien viene con herramientas para hacer daño, lo frena en seco.

¿De qué te protege exactamente?

Sin entrar en tecnicismos, los ataques más habituales que sufren las webs de WordPress son estos: Continuar leyendo «🔥🧱Qué es un cortafuegos para tu web y por qué Wordfence te lo pone fácil (en WordPress)»

Cómo proteger tu sitio de WordPress: configuraciones esenciales en el archivo .htaccess

El archivo .htaccess es una herramienta poderosa para gestionar la configuración de tu sitio web en un servidor Apache. En el caso de WordPress, puedes utilizarlo para mejorar la seguridad, optimizar el rendimiento y proteger tu contenido.

Vamos a ver cómo puedes configurar tu archivo .htaccess para proteger tu sitio de WordPress, incluyendo la redirección a HTTPS, la eliminación de hotlinking, el bloqueo de acceso a archivos de configuración y la prohibición de IPs maliciosas.
Continuar leyendo «Cómo proteger tu sitio de WordPress: configuraciones esenciales en el archivo .htaccess»

Cómo detectar modificaciones en WordPress y evitar la desactivación de actualizaciones

wordpress

 

WordPress se ha consolidado como una de las plataformas más populares para la creación de sitios web. Hoy por hoy es el sistema de gestión de contenidos o CMS (Content Management System) de código abierto más utilizado en el mundo. Cierto que ha cambiado bastante desde que empecé utilizarlo, allá por el 2008…

La popularidad de este gestor de contenidos también lo ha convertido en un blanco frecuente para los atacantes, lo que inevitablemente nos obliga a tomar medidas de seguridad adecuadas.

Una de las tácticas que pueden emplear ‘los malos’ es modificar el código de WordPress para desactivar las actualizaciones automáticas, con el claro objetivo de dejar tu sitio vulnerable a amenazas de seguridad. Vamos a ver cómo detectar si se han realizado modificaciones en tu instalación de WordPress y cómo asegurarte de que las actualizaciones se mantengan activas. Continuar leyendo «Cómo detectar modificaciones en WordPress y evitar la desactivación de actualizaciones»

Aprende WordPress (Learn WordPress)

learn wordpress

Cursos multimedia para ayudarte a convertirte en un mejor desarrollador, diseñador, usuario y contribuidor de WordPress. «Ya seas un bloguero novato o un desarrollador experimentado, siempre hay algo más que aprender. De los miembros de la comunidad de todo el mundo, estos grandes recursos te ayudarán a aprender más sobre WordPress y a compartirlo con otros«…

Aprender WordPress

Ya seas un bloguero novato o un desarrollador experimentado, siempre hay algo más que aprender. De los miembros de la comunidad de todo el mundo, estos grandes recursos te ayudarán a aprender más sobre WordPress y a compartirlo con otros.