Qué aprenderás en este tutorial
En este artículo aprenderás, paso a paso y desde cero, a:
- Crear un bloque en Moodle 4.5 siguiendo la arquitectura oficial de plugins.
- Entender cómo funciona el sistema de bloques en Moodle 4.x y su Block Drawer.
- Usar correctamente el sistema de internacionalización (lang strings).
- Renderizar contenido HTML seguro y compatible con el core de Moodle.
- Instalar y probar tu primer plugin de bloque sin errores comunes.
Este tutorial está pensado para desarrolladores que empiezan con Moodle, pero quieren hacerlo bien desde el principio.
Introducción: el problema de la experiencia de usuario en Moodle
Si gestionas una plataforma de formación (LMS), es muy probable que te hayas encontrado con este escenario: diseñas un curso con contenidos excelentes, actividades bien estructuradas y evaluaciones precisas. Sin embargo, a los pocos días de iniciar el curso, tu bandeja de entrada se llena de correos de estudiantes perdidos.
“No encuentro dónde subir la tarea”, “¿A quién pregunto si el PDF no carga?”, “Me he perdido en la navegación”.
La realidad es que Moodle es una herramienta extremadamente potente; sin embargo, su interfaz por defecto puede resultar abrumadora para usuarios no tecnológicos. La información de soporte suele quedar enterrada en menús genéricos, en el pie de página o en un PDF de “Guía del Alumno” que, seamos sinceros, casi nadie lee.
La solución: un bloque de soporte contextual en Moodle
Entonces, ¿y si pudiéramos colocar un pequeño “salvavidas” justo donde el alumno lo necesita?
Una de las mejores formas de mejorar la experiencia de usuario (UX) en Moodle 4.5 es mediante bloques personalizados.
En esta serie de tres artículos vamos a construir una solución real: un Bloque de Soporte Técnico para cursos Moodle, que:
- Estará siempre visible en el lateral del curso.
- Mostrará un mensaje de bienvenida claro y accesible.
- Proporcionará un correo de contacto directo.
- Incluirá un botón de acceso rápido a las Preguntas Frecuentes (FAQ).
En esta Parte 1 construiremos la estructura fundamental del plugin y haremos que el bloque funcione correctamente.
⚠️ ¿Desarrollo in‑house o externalizado?
Por un lado, seguir este tutorial es perfecto para aprender los fundamentos de la arquitectura de Moodle. Sin embargo, llevar código a un entorno de producción con miles de alumnos conlleva responsabilidades reales: seguridad, compatibilidad con futuras versiones y rendimiento.
Si tu institución necesita funcionalidades críticas que no pueden fallar, es clave contar con especialistas en desarrollo Moodle. Un bloque sencillo mal implementado puede convertirse en un problema serio a medio plazo.
Conceptos teóricos: qué es realmente un bloque en Moodle
El ecosistema Moodle y el rol del desarrollador
Antes de entrar en materia, conviene tener claros algunos conceptos básicos del ecosistema Moodle. Si estás empezando a desarrollar o quieres consolidar una base sólida, es recomendable adquirir primero una visión global del rol del desarrollador Moodle, como se explica en el artículo 10 habilidades clave para desarrollar en Moodle (https://www.andresmartinezsoto.eu/10-habilidades-para-desarrollar-moodle/), donde se repasan competencias esenciales más allá de escribir código.
Moodle es un sistema modular, pensado para crecer y adaptarse a las necesidades de cada institución. El núcleo (core) proporciona la funcionalidad básica, pero casi todo lo que ves e interactúas en una plataforma real se implementa mediante plugins: actividades, temas, métodos de matriculación, informes… y también bloques.
Qué son los bloques en Moodle y para qué sirven
En este contexto, los bloques son un tipo específico de plugin diseñado para mostrar información auxiliar y contextual. No sustituyen a las actividades ni a los contenidos del curso, sino que los complementan, mejorando la experiencia de usuario y reduciendo la fricción habitual en la navegación.
Este tipo de extensiones son especialmente útiles cuando queremos ofrecer ayuda contextual, accesos rápidos o información relevante sin sobrecargar la página principal del curso.
Moodle en entornos reales: mantenimiento y automatización
Además, a medida que una plataforma Moodle crece, entran en juego otros aspectos clave como el mantenimiento, la automatización y las actualizaciones. Por ejemplo, muchas tareas internas de Moodle dependen del cron, algo que se aborda en profundidad en el artículo Automatización avanzada en Moodle: cron y tareas programadas (https://www.andresmartinezsoto.eu/automatizacion-avanzada-moodle-tareas-programadas-cron/). Entender estos mecanismos te ayudará a desarrollar bloques y plugins que encajen bien en entornos reales de producción.
Del mismo modo, mantener Moodle actualizado de forma segura es fundamental para garantizar compatibilidad y estabilidad a largo plazo. Si este es un tema que te preocupa, el artículo Mantén tu Moodle al día: guía profesional para una actualización con éxito (https://www.andresmartinezsoto.eu/manten-tu-moodle-al-dia-guia-profesional-para-una-actualizacion-con-exito/) ofrece una visión práctica orientada a entornos profesionales.
Integraciones y conexión con sistemas externos
Por último, muchos desarrollos en Moodle no viven aislados, sino que se integran con sistemas externos. Aunque en este tutorial nos centramos en un bloque sencillo, es interesante saber que Moodle dispone de una potente API REST, explicada paso a paso en API REST de Moodle: guía práctica para automatizar tu LMS (https://www.andresmartinezsoto.eu/api-rest-moodle-automatizacion/), que permite automatizar procesos y conectar Moodle con otras aplicaciones.
Con este contexto claro, estamos listos para empezar a construir nuestro primer bloque.
Antes de escribir una sola línea de código, es importante entender qué estamos creando.
Moodle es un sistema modular. El núcleo (core) proporciona la funcionalidad básica, pero casi todo lo que ves e interactúas son plugins: actividades, temas, métodos de matriculación, informes y, por supuesto, bloques.
Los bloques son un tipo específico de plugin diseñado para mostrar información auxiliar y contextual.
Bloques en Moodle 4.x
En Moodle 3.x y versiones anteriores, los bloques vivían permanentemente en columnas laterales. Desde Moodle 4.0, la interfaz se ha simplificado notablemente.
Ahora los bloques residen principalmente en el Cajón de Bloques (Block Drawer), un panel lateral derecho que el usuario puede abrir o cerrar.

Esto tiene una implicación importante para nosotros como desarrolladores:
El contenido del bloque debe aportar valor real para que el usuario quiera mantener abierto el cajón de bloques.
Requisitos previos
Para seguir esta guía necesitarás:
- Acceso a los archivos del servidor (FTP, SFTP, cPanel o entorno local con Docker/XAMPP).
- Un editor de código profesional (Visual Studio Code, PhpStorm o Sublime Text).
- Permisos de Administrador en Moodle.
- Moodle 4.5 o superior con PHP 8.1+.
No es posible crear plugins únicamente desde la interfaz web de Moodle.

Paso 1: arquitectura de carpetas del bloque
Llegados a este punto, Moodle utiliza una estructura de directorios estricta para localizar automáticamente los plugins.
Todos los bloques deben residir en:
/blocks/Dentro de esa carpeta, crea un nuevo directorio llamado:
soporte_cursoRegla crítica: el nombre debe estar en minúsculas, sin espacios ni guiones medios. Este nombre será el identificador interno del plugin.
Paso 2: el manifiesto del plugin (version.php)
Referencia oficial: version.php (Common files)
Todo plugin en Moodle debe incluir un archivo version.php. Sin él, Moodle ignorará completamente el plugin.
Crea el archivo blocks/soporte_curso/version.php:
<?php
defined('MOODLE_INTERNAL') || die();
$plugin->component = 'block_soporte_curso';
$plugin->version = 2024010400;
$plugin->requires = 2022112800; // Moodle 4.1+
$plugin->maturity = MATURITY_STABLE;
$plugin->release = 'v1.0';Cómo funciona el versionado
En Moodle, cada plugin debe declarar una versión numérica única en su archivo version.php. Este número no es arbitrario: sigue un estándar interno muy específico que Moodle usa para:
- Detectar si el plugin está instalado.
- Determinar si hay una actualización pendiente.
- Ejecutar procesos de actualización (como scripts en
db/upgrade.php).
📅 Formato: YYYYMMDDXX
YYYY: Año (4 dígitos).MM: Mes (2 dígitos, con ceros a la izquierda si es necesario).DD: Día del mes (2 dígitos).XX: Número secuencial de revisión en ese día (empieza en00, luego01,02, etc.).
✅ Ejemplo:
2024010400→ 4 de enero de 2024, primera versión ese día.- Si ese mismo día haces un segundo cambio que requiere actualización:
2024010401.
⚠️ ¿Cuándo debo incrementar la versión?
Solo cuando haya cambios que Moodle deba “procesar”, como:
- Nuevas capacidades (
db/access.php). - Cambios en la base de datos (
db/install.xmlodb/upgrade.php). - Nuevos archivos de idioma o modificación de la estructura del plugin.
- Cambios en dependencias o en los archivos del plugin que afecten su funcionamiento.
❌ No es necesario incrementar la versión si solo cambias:
- Textos en archivos de idioma (una vez instalado, Moodle los recarga si purgas caché).
- Estilos CSS menores.
- Lógica de renderizado que no afecte la estructura del plugin.
🔄 Relación con db/upgrade.php
Si incrementas la versión y hay cambios estructurales (por ejemplo, añadir una tabla o campo en la BD), debes acompañar el cambio con un script de actualización en blocks/soporte_curso/db/upgrade.php. Moodle ejecutará ese script automáticamente al detectar que la versión instalada es menor que la nueva.
function xmldb_block_soporte_curso_upgrade($oldversion) {
global $DB;
if ($oldversion < 2024010401) {
// Ejemplo: añadir un nuevo campo de configuración
// $table = new xmldb_table('block_soporte_curso');
// ...
upgrade_block_savepoint(true, 2024010401, 'soporte_curso');
}
return true;
}🔒 Coherencia con maturity y release
maturity: Indica el estado del código (estable, beta, etc.). En entornos de producción, siempre debes usarMATURITY_STABLE.release: Es solo un label para humanos (comov1.0,v1.1-rc1). No afecta al funcionamiento técnico, pero ayuda en la gestión de versiones.
✅ Recomendaciones para tu flujo de trabajo
- Usa la fecha real de lanzamiento como base de la versión.
- Mantén un changelog interno (aunque sea en comentarios) para saber qué cambió en cada
XX. - Nunca retrocedas la versión: Moodle no permite “downgrades” automáticos.
- Prueba siempre la actualización en un entorno de staging antes de subir a producción.
Paso 3: Preparando tu bloque para un entorno real
Hasta ahora, nuestro bloque funciona. Moodle lo detecta, se instala correctamente y muestra información dentro del curso. Sin embargo, en desarrollo profesional hay una regla que conviene interiorizar cuanto antes: que algo funcione no significa que esté listo para producción.
En este paso vamos a dar un salto importante. Pasamos de un bloque “de prueba” a un bloque preparado para usarse en un entorno real, siguiendo los estándares del ecosistema Moodle. Aquí entran en juego dos aspectos que no siempre se ven a simple vista, pero que marcan una diferencia enorme a medio y largo plazo: los idiomas y los permisos.
Por un lado, aprenderás a preparar tu bloque para que pueda mostrarse en distintos idiomas y adaptarse a diferentes instituciones sin tocar el código. Por otro, definirás quién puede añadir el bloque y en qué contextos, evitando avisos del sistema y comportamientos inesperados en cursos reales.
Este paso no añade nuevas funcionalidades visibles para el usuario final, pero sí algo mucho más importante: robustez, mantenibilidad y tranquilidad futura. Es el tipo de trabajo que no luce en una demo, pero que distingue un desarrollo serio de uno que acabará dando problemas.
3.1 Internacionalización (i18n) y cadenas de idioma
Antes de seguir escribiendo código, necesitamos parar un momento y hablar de idiomas.
La internacionalización, abreviada habitualmente como i18n (por las 18 letras que hay entre la “i” y la “n” de internationalization), consiste en diseñar el software de forma que pueda adaptarse fácilmente a distintos idiomas y contextos sin modificar el código fuente.
En Moodle —y en cualquier sistema serio de código abierto— esto no es opcional. Es una exigencia técnica y de calidad.
La regla fundamental es muy clara:
Nunca escribas textos visibles directamente en el código PHP.
Moodle dispone de un sistema robusto de cadenas de idioma que permite traducir textos, personalizarlos desde la interfaz de administración y mantener el código limpio y escalable. Ignorar este sistema se considera un antipatrón en el desarrollo Moodle.
Esto cobra especial importancia si tenemos en cuenta que Moodle se utiliza en cientos de países y está traducido a más de cien idiomas. Además, cada usuario puede tener configurado su idioma de forma individual. En una misma plataforma pueden convivir docentes y alumnado con idiomas distintos.
Por ese motivo, en lugar de escribir textos como “Ayuda”, “Contactar” o una dirección de correo directamente en el código, se utilizan claves abstractas que Moodle resuelve automáticamente en tiempo de ejecución según el idioma activo del usuario.
Gracias a este enfoque:
- El bloque puede traducirse a otros idiomas sin tocar la lógica.
- Los textos pueden personalizarse desde la administración de Moodle.
- Se cumplen los estándares oficiales del ecosistema Moodle.
- Cambiar un texto no requiere volver a desplegar el plugin.
Cómo se implementa en Moodle
La internacionalización en Moodle se basa en algo muy sencillo: archivos de idioma.
Cada plugin tiene una carpeta lang, y dentro de ella un subdirectorio por idioma. En nuestro bloque, la estructura mínima es esta:
blocks/soporte_curso/lang/en/block_soporte_curso.php
blocks/soporte_curso/lang/es/block_soporte_curso.phpEl idioma inglés (en) es obligatorio en cualquier plugin Moodle. El castellano (es) es una traducción adicional.
En estos archivos se definen las cadenas de texto usando claves lógicas. Por ejemplo:
$string['block_title'] = '¿Necesitas ayuda?';En el código PHP del bloque nunca escribimos el texto directamente. En su lugar, usamos la función get_string():
echo get_string('block_title', 'block_soporte_curso');Moodle se encarga de mostrar el texto correcto según el idioma del usuario.
La regla de oro es simple:
Si ves texto visible en un archivo .php de un plugin Moodle fuera de la carpeta lang, ese código no está listo para producción.
Gracias a esta estructura, un centro educativo en España puede usar el bloque en castellano, una universidad en Francia puede traducirlo simplemente añadiendo su archivo de idioma, y un administrador puede ajustar textos sin tocar el código fuente.
La internacionalización no es “para traducir”, es para crear software flexible, mantenible y profesional.
🌍 Idioma base (obligatorio): Inglés
📄 blocks/soporte_curso/lang/en/block_soporte_curso.php
<?php
defined('MOODLE_INTERNAL') || die();
// Plugin name
$string['pluginname'] = 'Course Support Block';
// Capabilities
$string['soporte_curso:addinstance'] = 'Add a new course support block';
$string['soporte_curso:myaddinstance'] = 'Add a new course support block to the Dashboard';
// Block strings
$string['block_title'] = 'Need help?';
$string['help_text'] = 'If you have technical issues or questions about the course content, we are here to help you.';
$string['contact_email'] = 'support@yourinstitution.com';
$string['btn_text'] = 'Go to Frequently Asked Questions';
🇪🇸 Castellano (España)
📄 blocks/soporte_curso/lang/es/block_soporte_curso.php
<?php
defined('MOODLE_INTERNAL') || die();
// Nombre del plugin
$string['pluginname'] = 'Bloque de soporte del curso';
// Capacidades
$string['soporte_curso:addinstance'] = 'Añadir un bloque de soporte del curso';
$string['soporte_curso:myaddinstance'] = 'Añadir un bloque de soporte del curso al Escritorio';
// Contenido del bloque
$string['block_title'] = '¿Necesitas ayuda?';
$string['help_text'] = 'Si tienes problemas técnicos o dudas sobre el contenido del curso, estamos aquí para ayudarte.';
$string['contact_email'] = 'soporte@miuniversidad.com';
$string['btn_text'] = 'Ir a Preguntas Frecuentes';
🧠 Recordatorios importantes
- El archivo
lang/enes obligatorio para cualquier plugin Moodle. - Las claves deben coincidir exactamente en todos los idiomas.
- No pongas nunca textos visibles directamente en el código PHP del bloque.
- Estos textos pueden personalizarse después desde
Administración del sitio → Idioma → Personalización de idioma, sin tocar código.
3.2 Capacidades y control de permisos (db/access.php)
Hasta aquí ya hemos resuelto un punto clave: que el bloque sea traducible y adaptable a distintos contextos. El siguiente paso para que sea realmente “usable en producción” es definir quién puede añadirlo y dónde.
En Moodle, esto se gestiona con el sistema de capacidades (capabilities). Dicho de forma sencilla: una capacidad es un “permiso con nombre” que Moodle asigna a roles como Gestor, Profesor editor o Usuario, dependiendo del contexto (curso, sistema, bloque, etc.).
¿Por qué es importante?
Si no defines capacidades en un bloque, es habitual encontrarse con problemas como:
- Avisos del sistema del tipo “does not define the standard capability …:addinstance”.
- Que ciertos roles no puedan añadir el bloque aunque tengan permisos para editar el curso.
- Comportamientos inconsistentes entre cursos y otras zonas como el Escritorio.
Definir capacidades desde el principio hace que tu plugin se comporte de forma predecible, respete el modelo de roles de Moodle y sea fácil de gobernar en instituciones reales.
Capacidades estándar que vamos a incluir
En la mayoría de bloques se definen al menos dos capacidades:
block/soporte_curso:addinstance
Permite añadir el bloque dentro de un curso u otras páginas donde se gestionan bloques.block/soporte_curso:myaddinstance
Permite añadir el bloque en el Escritorio / Área personal del usuario (Dashboard), si tu institución lo utiliza.
Archivo db/access.php
Las capacidades se declaran en un archivo específico del plugin. Crea esta ruta:
blocks/soporte_curso/db/access.phpY añade el siguiente código:
<?php
defined('MOODLE_INTERNAL') || die();
$capabilities = [
'block/soporte_curso:addinstance' => [
'riskbitmask' => RISK_SPAM | RISK_XSS,
'captype' => 'write',
'contextlevel' => CONTEXT_BLOCK,
'archetypes' => [
'editingteacher' => CAP_ALLOW,
'manager' => CAP_ALLOW,
],
'clonepermissionsfrom' => 'moodle/site:manageblocks',
],
'block/soporte_curso:myaddinstance' => [
'riskbitmask' => RISK_SPAM | RISK_XSS,
'captype' => 'write',
'contextlevel' => CONTEXT_SYSTEM,
'archetypes' => [
'user' => CAP_ALLOW,
],
'clonepermissionsfrom' => 'moodle/my:manageblocks',
],
];
Qué significa esto (sin complicarnos)
archetypesindica qué roles reciben el permiso por defecto. Luego cada institución puede ajustarlo desde administración.contextlevelmarca dónde aplica el permiso (en un bloque dentro de un curso o a nivel del sistema).clonepermissionsfromhace que Moodle copie el comportamiento estándar desde capacidades del core, para que tu bloque sea consistente con el resto de Moodle.riskbitmaskno significa que tu bloque sea inseguro; simplemente indica que, como cualquier bloque, podría mostrar contenido que implique riesgos si se implementa mal, y Moodle lo etiqueta para revisiones.
No olvides las cadenas de idioma
Para que Moodle muestre correctamente estos permisos en la pantalla de roles, las capacidades deben existir también como cadenas en los archivos de idioma.
En inglés (obligatorio) en lang/en/block_soporte_curso.php:
$string['soporte_curso:addinstance'] = 'Add a new course support block';
$string['soporte_curso:myaddinstance'] = 'Add a new course support block to the Dashboard';
Y en castellano en lang/es/block_soporte_curso.php:
$string['soporte_curso:addinstance'] = 'Añadir un bloque de soporte del curso';
$string['soporte_curso:myaddinstance'] = 'Añadir un bloque de soporte del curso al Escritorio';
Cómo aplicar el cambio
Una vez creado db/access.php, Moodle debe “enterarse” de que el plugin ha cambiado:
- Incrementa el número
$plugin->versionenversion.php. - Ve a Administración del sitio → Notificaciones para aplicar cambios.
- Si no ves el resultado, purga cachés en Administración del sitio → Desarrollo → Purgar todas las cachés.
Paso 4: Lógica del bloque y renderizado del contenido
En los pasos anteriores hemos dejado nuestro plugin bien estructurado, con su versión, sus idiomas y sus permisos definidos. Ahora llega el momento clave: decidir qué muestra el bloque y cómo lo muestra Moodle en pantalla.
Todo esto se gestiona desde un único archivo: block_soporte_curso.php.
Este archivo contiene la clase principal del bloque y es el punto de entrada que Moodle utiliza cada vez que necesita renderizarlo dentro de un curso.
Antes de escribir código, conviene entender una idea importante en Moodle 4.x:
El bloque no “imprime HTML”. El bloque prepara datos y Moodle se encarga del renderizado.
Por ese motivo, en lugar de construir el HTML concatenando cadenas en PHP, vamos a utilizar plantillas Mustache, que es el sistema de plantillas oficial de Moodle.
Por qué usar plantillas Mustache en un bloque
Podríamos escribir todo el HTML directamente en PHP, y funcionaría. Sin embargo, esa aproximación tiene varios problemas cuando el proyecto crece:
- El código se vuelve difícil de leer.
- Mezclamos lógica con presentación.
- Cada cambio visual obliga a tocar PHP.
- Es más complicado mantenerlo a largo plazo.
Las plantillas Mustache resuelven esto separando responsabilidades:
- El archivo PHP prepara los datos (textos, URLs, permisos).
- La plantilla define cómo se muestran esos datos en pantalla.
Este enfoque es el que utilizan los plugins profesionales del ecosistema Moodle y es especialmente recomendable en Moodle 4.x.
Estructura necesaria para usar Mustache
Para usar plantillas Mustache en un bloque, solo necesitas una carpeta adicional dentro del plugin. La estructura queda así:
blocks/soporte_curso/
├─ block_soporte_curso.php
└─ templates/
└─ block_soporte_curso.mustache
La carpeta templates contendrá los archivos .mustache, que son plantillas HTML con marcadores de posición.
La plantilla del bloque
La plantilla define la estructura visual del bloque: el mensaje de ayuda, el correo de contacto y el botón de acceso a las FAQ. No contiene lógica PHP ni llamadas a Moodle; solo muestra los datos que recibe.
Crea el archivo:
blocks/soporte_curso/templates/block_soporte_curso.mustacheY añade el siguiente contenido:
<div class="p-3 text-center">
<h5 class="mb-3">{{block_title}}</h5>
<p class="mb-3 text-muted">{{help_text}}</p>
<div class="mb-3">
<i class="fa fa-envelope me-2" aria-hidden="true"></i>
<a href="mailto:{{contact_email}}" class="fw-bold">{{contact_email}}</a>
</div>
<a href="{{faq_url}}" class="btn btn-primary w-100">{{btn_text}}</a>
</div>
Aquí no hay PHP, solo placeholders como {{help_text}} o {{faq_url}}. Moodle sustituirá estos valores cuando renderice el bloque.
La lógica del bloque en block_soporte_curso.php
Ahora vamos al archivo principal del bloque, que se encarga de preparar los datos y renderizar la plantilla.
Crea (o reemplaza) el archivo:
blocks/soporte_curso/block_soporte_curso.phpCon este contenido:
<?php
defined('MOODLE_INTERNAL') || die();
class block_soporte_curso extends block_base {
/**
* Define el título del bloque.
* Este título aparece en el marco del bloque.
*/
public function init(): void {
$this->title = get_string('pluginname', 'block_soporte_curso');
}
/**
* Moodle llama a este método cuando necesita dibujar el bloque en pantalla.
*/
public function get_content(): ?stdClass {
global $OUTPUT;
// Evitamos recalcular el contenido varias veces en la misma carga de página.
if ($this->content !== null) {
return $this->content;
}
$this->content = new stdClass();
// Recuperamos los textos desde los archivos de idioma.
$blocktitle = get_string('block_title', 'block_soporte_curso');
$helptext = get_string('help_text', 'block_soporte_curso');
$contactemail = get_string('contact_email', 'block_soporte_curso');
$btntext = get_string('btn_text', 'block_soporte_curso');
// Construimos la URL interna correctamente.
$faqurl = new moodle_url('/faq');
// Datos que se enviarán a la plantilla Mustache.
$context = [
'block_title' => format_string($blocktitle),
'help_text' => format_string($helptext),
'contact_email' => s($contactemail),
'btn_text' => format_string($btntext),
'faq_url' => $faqurl->out(false),
];
// Renderizamos la plantilla templates/block_soporte_curso.mustache
$this->content->text = $OUTPUT->render_from_template(
'block_soporte_curso/block_soporte_curso',
$context
);
$this->content->footer = '';
return $this->content;
}
/**
* Permitimos que el bloque se pueda añadir más de una vez en un curso.
*/
public function instance_allow_multiple(): bool {
return true;
}
}
Qué está pasando realmente aquí
Aunque el código pueda parecer largo, la idea es sencilla:
- Moodle llama a
get_content(). - Recuperamos los textos desde el sistema de idiomas.
- Construimos la URL del botón de forma segura.
- Preparamos un array con los datos.
- Moodle renderiza la plantilla Mustache con esos datos.
El bloque no “pinta HTML a mano”, sino que describe qué quiere mostrar y deja que Moodle se encargue del resto.
Por qué este enfoque es el correcto
Con esta estructura, tu bloque:
- Es más fácil de mantener.
- Se adapta mejor a distintos temas visuales.
- Está preparado para crecer en la Parte 2 (configuración).
- Sigue las buenas prácticas oficiales de Moodle 4.x.
A partir de aquí, el bloque ya no es solo funcional: es un bloque bien diseñado, listo para un entorno real y alineado con el ecosistema Moodle.
Paso 5: instalación y pruebas
Una vez completados los pasos anteriores, llega el momento de comprobar que Moodle detecta e instala correctamente el bloque y que todo funciona como esperamos en un entorno real.
Si has seguido el tutorial paso a paso, ya tendrás la estructura del plugin creada en tu instalación de Moodle. No obstante, para facilitar las pruebas —o si prefieres partir de una base ya preparada— puedes descargar el bloque completo en formato ZIP , listo para copiar en el directorio /blocks/ y comenzar directamente con la instalación.
A partir de aquí, vamos a revisar el proceso completo: desde cómo Moodle detecta el nuevo bloque hasta cómo verificar que se muestra correctamente dentro de un curso.
5.1 Detección automática del plugin
- Inicia sesión en Moodle con una cuenta con permisos de Administrador.
- Accede a:
Administración del sitio → Notificaciones
Moodle escaneará automáticamente el sistema de archivos y detectará que existe un nuevo plugin en la carpeta /blocks/soporte_curso.
Si todo es correcto, verás una pantalla indicando que hay un nuevo plugin pendiente de instalación.

5.2 Instalación del bloque
- Pulsa en Actualizar base de datos Moodle ahora.
- Moodle ejecutará las comprobaciones necesarias (versionado, requisitos, capacidades).
- Si no hay errores, aparecerá un mensaje en verde indicando que la instalación se ha completado con éxito.
En este punto, el bloque ya está instalado en el sistema, pero todavía no es visible en ningún curso.
5.3 Añadir el bloque a un curso
- Entra en cualquier curso de tu plataforma.
- Activa el modo de edición (interruptor superior derecho en Moodle 4.5).
- Abre el cajón de bloques (icono de flecha en el lateral derecho).
- Haz clic en Agregar un bloque.
- Busca Course Support Block en la lista y selecciónalo.

El bloque aparecerá inmediatamente en el cajón de bloques del curso, mostrando el mensaje, el correo de contacto y el botón de FAQ.

5.4 Purgar la caché (paso clave)
Siempre que desarrolles plugins en Moodle —y especialmente cuando trabajas con cadenas de idioma— es fundamental purgar la caché.
Para hacerlo:
- Ve a Administración del sitio → Desarrollo → Purgar todas las cachés.
- Pulsa el botón Purgar cachés.
Este paso obliga a Moodle a recargar:
- Los archivos de idioma (
lang). - La información de plugins instalados.
- Plantillas y configuraciones internas.
Si no purgas la caché, es habitual que los cambios no se reflejen, aunque el código sea correcto.
Problemas comunes
No obstante, incluso siguiendo el tutorial paso a paso, es normal encontrarse con pequeños problemas, sobre todo si es tu primer plugin en Moodle. Aquí tienes los más habituales y cómo solucionarlos.
Pantalla en blanco (White Screen of Death)
Suele indicar un error de sintaxis en PHP (por ejemplo, un punto y coma ; olvidado o una llave mal cerrada).
Qué hacer:
- Activa la depuración en: Administración del sitio → Desarrollo → Depuración.
- Selecciona DESARROLLADOR y guarda los cambios.
- Recarga la página para ver el mensaje de error real.
Aparecen textos como [[pluginname]] o [[block_title]]
Esto significa que Moodle no encuentra las cadenas de idioma.
Comprueba:
- Que el archivo
lang/en/block_soporte_curso.phpexiste. - Que el nombre del archivo coincide exactamente con el componente.
- Que has purgado la caché después de añadir o modificar las cadenas.
El bloque no aparece en la lista de “Agregar un bloque”
Las causas más comunes son:
- El nombre de la carpeta no coincide con
$plugin->component. - El archivo
version.phptiene un error. - No existen las capacidades en
db/access.php. - No has visitado Administración del sitio → Notificaciones tras copiar los archivos.
Solución:
- Revisa los nombres con cuidado.
- Purga la caché.
- Vuelve a cargar la página de notificaciones.
Cambios que no se reflejan
Muy habitual cuando se empieza a desarrollar en Moodle.
Antes de asumir que algo está mal:
- Purga siempre la caché.
- Recarga la página forzando el navegador (Ctrl + F5).
- Asegúrate de no tener errores PHP ocultos.
Con estos pasos se resuelve la mayoría de incidencias iniciales.
Limitaciones y próximos pasos
Nuestro bloque ya es funcional, está bien estructurado y cumple con los estándares básicos de Moodle. Sin embargo, aún arrastra una limitación importante desde el punto de vista de la escalabilidad y la gestión en entornos reales:
Actualmente, el correo de soporte y la URL de las preguntas frecuentes están definidos en los archivos de idioma. Aunque esta solución es válida a nivel técnico, no es la más adecuada cuando el bloque se utiliza en múltiples cursos, facultades o instituciones con necesidades distintas.
En un entorno real, es habitual que:
- Cada curso tenga un correo de soporte diferente.
- Distintas facultades utilicen páginas de ayuda propias.
- Los responsables del curso necesiten ajustar estos valores sin depender de un desarrollador.
En la Parte 2 de esta serie, daremos el siguiente paso lógico: aprenderás a crear un formulario de configuración integrado en Moodle, accesible desde la interfaz de administración del bloque. De este modo, cualquier profesor o gestor con permisos podrá personalizar el contenido del bloque sin tocar una sola línea de código.
Este es el punto en el que un bloque deja de ser un ejemplo técnico y pasa a convertirse en una herramienta realmente útil y reutilizable dentro de una plataforma Moodle.
Conclusión
Has dado un primer paso muy importante: ya sabes crear un bloque funcional en Moodle 4.5 desde cero, siguiendo la estructura oficial del core, respetando las buenas prácticas y entendiendo qué hace cada archivo.
Más allá del código, este tutorial te ha permitido comprender algo clave en el desarrollo Moodle:
Pequeñas mejoras bien pensadas pueden tener un impacto enorme en la experiencia del alumnado y del profesorado.
Un bloque como este, sencillo pero bien integrado, puede reducir incidencias, mejorar la usabilidad del curso y ahorrar muchas horas de soporte técnico.
Este es solo el comienzo. A partir de aquí puedes seguir profundizando en el desarrollo de plugins, la personalización de la interfaz y la automatización de tareas dentro de Moodle.
🚀 ¿Listo para llevar tu plataforma Moodle al siguiente nivel?
En Entornos de Formación llevamos más de una década ayudando a universidades, centros educativos y organizaciones a optimizar y escalar sus entornos Moodle de forma segura y sostenible.

Nos especializamos en:
- Automatización de procesos en Moodle.
- Desarrollo de plugins a medida.
- Integraciones avanzadas con sistemas externos.
- Configuración, mantenimiento y evolución de plataformas Moodle 4.x y Moodle 5.
Desde consultoría estratégica hasta soporte técnico continuo, trabajamos contigo para que tu LMS funcione de manera fluida, eficiente y alineada con tus objetivos formativos.
📅 Habla con nosotros hoy mismo y diseñemos juntos soluciones a medida para tu plataforma Moodle.
👉 Entornos de Formación – edTech Solutions
🌐 https://edf.global






