Como crear un plugin completo que te permitirá crear Custom Post Types desde el panel de administración, con sus propias categorías y páginas automáticas
He creado un plugin completo que te permitirá crear Custom Post Types desde el panel de administración, con sus propias categorías y páginas automáticas.. Aquí te explico cómo usarlo:
📦 Instalación:
- Crea una carpeta llamada
custom-post-type-creatoren/wp-content/plugins/ - Guarda el código en un archivo llamado
custom-post-type-creator.phpdentro de esa carpeta, https://gist.github.com/ximosa/85ec824c2a9d57cf4981638978bdb0bb
- Activa el plugin desde el panel de WordPress (Plugins → Plugins instalados)
✨ Características principales:
- Crear Post Types personalizados desde el admin con un formulario simple
- Categorías automáticas para cada Post Type creado
- URLs automáticas (ej:
tudominio.com/portafolio) - Plantilla visual incluida para mostrar los posts en grid
- Gestión completa desde el panel de administración
🚀 Cómo usar:
- Ve a CPT Creator en el menú lateral del admin
- Rellena el formulario:
- Slug:
portafolio(minúsculas, sin espacios) - Nombre Plural:
Portafolios - Nombre Singular:
Portafolio - Icono:
dashicons-portfolio(opcional)
- Slug:
- Haz clic en Crear Post Type
- ¡Importante! Ve a Ajustes → Enlaces permanentes y haz clic en "Guardar" para actualizar las URLs
- Aparecerá un nuevo menú "Portafolios" en tu admin
- Crea tus posts y categorías desde ahí
- Visita
tudominio.com/portafoliopara ver todos los posts publicados
El plugin incluye una tabla donde verás:
- La URL donde se mostrarán los posts
- Enlaces directos para administrar posts y categorías
- Opción para eliminar Post Types
Puedes crear todos los Post Types que necesites, sin límite.
Cada vez que uses el formulario, se creará un nuevo Post Type completamente independiente:
Ejemplos de lo que podrías crear:
- Portafolio →
tudominio.com/portafolio - Productos →
tudominio.com/productos - Servicios →
tudominio.com/servicios - Testimonios →
tudominio.com/testimonios - Equipo →
tudominio.com/equipo - Eventos →
tudominio.com/eventos
Cada uno tendrá:
- ✅ Su propio menú en el admin
- ✅ Sus propias categorías independientes
- ✅ Su propia URL de archivo
- ✅ Su propia gestión de posts
En la tabla del plugin verás todos listados:
Slug | Nombre | URL
------------|-------------|-------------------------
portafolio | Portafolios | tudominio.com/portafolio
productos | Productos | tudominio.com/productos
servicios | Servicios | tudominio.com/servicios
Y cada uno con sus botones para:
- Administrar (crear/editar posts)
- Ver Categorías (crear categorías propias)
- Eliminar (si ya no lo necesitas)
Todos quedan guardados en la base de datos y se cargan automáticamente cada vez que WordPress inicia.
Te voy a explicar cómo modificar el código para añadir campos personalizados. Te daré un ejemplo práctico y luego te enseño cómo replicarlo para otros campos.
📚 Conceptos básicos:
En WordPress, los campos personalizados se llaman "meta fields" y se guardan con funciones como add_meta_box() y update_post_meta().
🎯 Ejemplo práctico: Añadir campo "Precio" a un Post Type
Te voy a mostrar el código que debes añadir y dónde exactamente colocarlo:
Guía: Cómo Añadir Campos Personalizados al Plugin
📍 PASO 1: Ubicar dónde añadir el código
Abre tu archivo custom-post-type-creator.php y busca esta línea (está cerca del inicio):
add_action('template_redirect', array($this, 'custom_post_type_template'));
Justo debajo de esa línea, añade estos nuevos hooks:
add_action('add_meta_boxes', array($this, 'add_custom_meta_boxes'));
add_action('save_post', array($this, 'save_custom_meta_boxes'));
📍 PASO 2: Añadir las funciones al final del archivo
Busca el final de la clase (antes del último } y antes de new Custom_Post_Type_Creator();).
Ahí añade estas dos funciones:
Función 1: Crear el Meta Box (el formulario en el admin)
// Añadir Meta Boxes personalizados
public function add_custom_meta_boxes() {
global $wpdb;
// Obtener todos los Post Types creados
$custom_post_types = $wpdb->get_results("SELECT * FROM {$this->table_name}");
foreach ($custom_post_types as $cpt) {
// Añadir meta box para cada Post Type
add_meta_box(
$cpt->post_type_slug . '_custom_fields', // ID único
'Campos Personalizados', // Título del box
array($this, 'render_meta_box'), // Función que dibuja el formulario
$cpt->post_type_slug, // En qué Post Type aparece
'normal', // Posición (normal, side, advanced)
'high' // Prioridad
);
}
}
// Dibujar el formulario del Meta Box
public function render_meta_box($post) {
// Nonce para seguridad
wp_nonce_field('save_custom_fields', 'custom_fields_nonce');
// Obtener valores guardados
$precio = get_post_meta($post->ID, '_precio', true);
$ubicacion = get_post_meta($post->ID, '_ubicacion', true);
$fecha_evento = get_post_meta($post->ID, '_fecha_evento', true);
$destacado = get_post_meta($post->ID, '_destacado', true);
?>
<table class="form-table">
<tr>
<th><label for="precio">Precio</label></th>
<td>
<input type="text"
id="precio"
name="precio"
value="<?php echo esc_attr($precio); ?>"
class="regular-text">
<p class="description">Ejemplo: $99.00</p>
</td>
</tr>
<tr>
<th><label for="ubicacion">Ubicación</label></th>
<td>
<input type="text"
id="ubicacion"
name="ubicacion"
value="<?php echo esc_attr($ubicacion); ?>"
class="regular-text">
<p class="description">Ciudad, País</p>
</td>
</tr>
<tr>
<th><label for="fecha_evento">Fecha del Evento</label></th>
<td>
<input type="date"
id="fecha_evento"
name="fecha_evento"
value="<?php echo esc_attr($fecha_evento); ?>">
</td>
</tr>
<tr>
<th><label for="destacado">¿Destacado?</label></th>
<td>
<input type="checkbox"
id="destacado"
name="destacado"
value="1"
<?php checked($destacado, '1'); ?>>
<label for="destacado">Marcar como destacado</label>
</td>
</tr>
</table>
<?php
}
Función 2: Guardar los valores
// Guardar los valores de los campos personalizados
public function save_custom_meta_boxes($post_id) {
// Verificar nonce
if (!isset($_POST['custom_fields_nonce']) ||
!wp_verify_nonce($_POST['custom_fields_nonce'], 'save_custom_fields')) {
return;
}
// Verificar autoguardado
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
return;
}
// Verificar permisos
if (!current_user_can('edit_post', $post_id)) {
return;
}
// Guardar cada campo
if (isset($_POST['precio'])) {
update_post_meta($post_id, '_precio', sanitize_text_field($_POST['precio']));
}
if (isset($_POST['ubicacion'])) {
update_post_meta($post_id, '_ubicacion', sanitize_text_field($_POST['ubicacion']));
}
if (isset($_POST['fecha_evento'])) {
update_post_meta($post_id, '_fecha_evento', sanitize_text_field($_POST['fecha_evento']));
}
// Checkbox (si no está marcado, no viene en $_POST)
$destacado = isset($_POST['destacado']) ? '1' : '0';
update_post_meta($post_id, '_destacado', $destacado);
}
📍 PASO 3: Mostrar los campos en el frontend
Busca esta parte en la función custom_post_type_template():
<div class="cpt-excerpt" style="color: #666; margin-bottom: 15px;">
<?php the_excerpt(); ?>
</div>
Justo debajo, añade:
<?php
// Mostrar campos personalizados
$precio = get_post_meta(get_the_ID(), '_precio', true);
$ubicacion = get_post_meta(get_the_ID(), '_ubicacion', true);
$fecha_evento = get_post_meta(get_the_ID(), '_fecha_evento', true);
$destacado = get_post_meta(get_the_ID(), '_destacado', true);
?>
<?php if ($destacado == '1'): ?>
<span style="background: #ff6b6b; color: white; padding: 4px 10px; border-radius: 3px; font-size: 0.85em; font-weight: bold; margin-bottom: 10px; display: inline-block;">
⭐ DESTACADO
</span>
<?php endif; ?>
<div class="cpt-custom-fields" style="margin-bottom: 15px; font-size: 0.95em;">
<?php if ($precio): ?>
<p style="margin: 5px 0;"><strong>💰 Precio:</strong> <?php echo esc_html($precio); ?></p>
<?php endif; ?>
<?php if ($ubicacion): ?>
<p style="margin: 5px 0;"><strong>📍 Ubicación:</strong> <?php echo esc_html($ubicacion); ?></p>
<?php endif; ?>
<?php if ($fecha_evento): ?>
<p style="margin: 5px 0;"><strong>📅 Fecha:</strong> <?php echo date('d/m/Y', strtotime($fecha_evento)); ?></p>
<?php endif; ?>
</div>
🎨 TIPOS DE CAMPOS QUE PUEDES AÑADIR
Campo de Texto
<input type="text" name="nombre_campo" value="<?php echo esc_attr($valor); ?>">
Área de Texto (Textarea)
<textarea name="descripcion" rows="5" class="large-text"><?php echo esc_textarea($valor); ?></textarea>
Select (Lista desplegable)
<select name="estado">
<option value="activo" <?php selected($valor, 'activo'); ?>>Activo</option>
<option value="inactivo" <?php selected($valor, 'inactivo'); ?>>Inactivo</option>
</select>
Checkbox
<input type="checkbox" name="visible" value="1" <?php checked($valor, '1'); ?>>
Campo de Número
<input type="number" name="cantidad" value="<?php echo esc_attr($valor); ?>" min="0" step="1">
Campo de URL
<input type="url" name="sitio_web" value="<?php echo esc_url($valor); ?>" class="regular-text">
Campo de Email
<input type="email" name="correo" value="<?php echo esc_attr($valor); ?>" class="regular-text">
Campo de Fecha
<input type="date" name="fecha" value="<?php echo esc_attr($valor); ?>">
Campo de Color
<input type="color" name="color_fondo" value="<?php echo esc_attr($valor); ?>">
🔄 PLANTILLA PARA AÑADIR UN NUEVO CAMPO
Cada vez que quieras añadir un campo nuevo, sigue estos pasos:
1️⃣ Añadir en render_meta_box():
<tr>
<th><label for="NOMBRE_CAMPO">Etiqueta del Campo</label></th>
<td>
<input type="text"
id="NOMBRE_CAMPO"
name="NOMBRE_CAMPO"
value="<?php echo esc_attr(get_post_meta($post->ID, '_NOMBRE_CAMPO', true)); ?>"
class="regular-text">
<p class="description">Descripción de ayuda</p>
</td>
</tr>
2️⃣ Añadir en save_custom_meta_boxes():
if (isset($_POST['NOMBRE_CAMPO'])) {
update_post_meta($post_id, '_NOMBRE_CAMPO', sanitize_text_field($_POST['NOMBRE_CAMPO']));
}
3️⃣ Mostrar en el frontend:
<?php
$nombre_campo = get_post_meta(get_the_ID(), '_NOMBRE_CAMPO', true);
if ($nombre_campo):
?>
<p><strong>Etiqueta:</strong> <?php echo esc_html($nombre_campo); ?></p>
<?php endif; ?>
⚠️ IMPORTANTE: Funciones de sanitización
Según el tipo de dato, usa la función correcta:
- Texto general:
sanitize_text_field() - Textarea:
sanitize_textarea_field() - Email:
sanitize_email() - URL:
esc_url_raw() - Número:
intval()ofloatval() - HTML:
wp_kses_post()(permite HTML seguro)
📦 EJEMPLO COMPLETO: Añadir campo "Galería de Imágenes"
Si quieres un campo más avanzado como una galería:
// En render_meta_box()
$galeria = get_post_meta($post->ID, '_galeria', true);
?>
<tr>
<th><label>Galería de Imágenes</label></th>
<td>
<input type="hidden" id="galeria" name="galeria" value="<?php echo esc_attr($galeria); ?>">
<button type="button" class="button" id="upload_galeria">Subir Imágenes</button>
<div id="galeria_preview"></div>
<script>
jQuery(document).ready(function($){
$('#upload_galeria').click(function(e) {
e.preventDefault();
var image = wp.media({
title: 'Seleccionar Imágenes',
multiple: true
}).open()
.on('select', function(e){
var uploaded_images = image.state().get('selection');
var ids = [];
uploaded_images.each(function(img) {
ids.push(img.id);
});
$('#galeria').val(ids.join(','));
});
});
});
</script>
</td>
</tr>
✅ RESUMEN RÁPIDO
- Añade los hooks al inicio de
__construct() - Copia las dos funciones al final de la clase
- Personaliza los campos que necesites
- Muestra los valores en el frontend
- Guarda el archivo y recarga WordPress
¿Necesitas ayuda con algún campo específico? 😊
Categorías
¿Tienes un proyecto en mente?
Hagámoslo realidad juntos.
Si necesitas ayuda con tu próximo desarrollo web o simplemente quieres saludar, estaré encantado de escucharte.
Sobre el Autor
Joaquín Sáez
Desarrollador Full Stack especializado en tecnologías web modernas. Me apasiona crear soluciones innovadoras y compartir conocimiento con la comunidad de desarrolladores.
Artículos Relacionados

Guía Definitiva de la Abilities API: Transformando WordPress para la Era de la Inteligencia Artificial
La Abilities API representa un cambio de paradigma en el ecosistema de WordPress, permitiendo que el software no solo se ...

Automattic para Agencias y freelancers: Escalar tu Negocio WordPress
El modelo de negocio de las agencias digitales está cambiando. La era de "construir y abandonar" ha terminado; el futuro ...

La Guía Definitiva de Optimización de Velocidad WordPress en 2026: Plugins, Core Web Vitals y Estrategias Avanzadas
Descubre los mejores plugins de caché de 2026, cómo superar las Core Web Vitals (INP, LCP, CLS), comparativas entre Flyi ...

Guía Maestra de E-commerce: De la Suscripción y Pagos con Redsys a la Ciberseguridad y PSD3
Descubre cómo montar un negocio de suscripción exitoso, integrar la pasarela Redsys paso a paso, gestionar inventario en ...