DESARROLLO MOODLE · PARTE 1
Un estudiante entra en el curso, necesita ayuda y no sabe dónde buscarla. Un correo escondido en un PDF o una página de soporte a tres clics de distancia no resuelve el problema. En este tutorial aprenderás a crear tu primer bloque en Moodle 4.5 desde cero: un pequeño punto de ayuda contextual, visible dentro del curso y preparado para crecer.
No vamos a construir un ejemplo desechable. Crearemos block_soporte_curso siguiendo la estructura oficial de plugins de Moodle, con cadenas de idioma, capacidades, una plantilla Mustache y un proceso de instalación que puedas comprobar paso a paso.

Qué aprenderás en esta Parte 1
- Cómo crear un bloque en Moodle 4.5 siguiendo su arquitectura oficial.
- Qué archivos son obligatorios y qué responsabilidad tiene cada uno.
- Cómo declarar la versión mínima compatible, los idiomas y los permisos.
- Cómo separar la lógica PHP de la presentación con Mustache.
- Cómo instalar, añadir y probar el bloque con distintos roles.
Al terminar tendrás un bloque funcional. En la Parte 2 añadiremos configuración por instancia para que cada curso pueda definir su propio mensaje, correo y enlace de ayuda.
El problema: la ayuda existe, pero llega tarde
Puedes tener contenidos excelentes, actividades bien organizadas y evaluaciones precisas. Aun así, basta con que el alumnado no encuentre dónde preguntar para que la experiencia se deteriore: aumentan los correos, se repiten las mismas incidencias y el equipo docente acaba actuando como primera línea de soporte.
«No encuentro dónde subir la tarea», «el PDF no se abre» o «¿con quién contacto?» no suelen ser problemas pedagógicos. Son problemas de contexto y acceso a la ayuda.
Un bloque personalizado no sustituye una buena arquitectura de información, pero puede actuar como un pequeño salvavidas: coloca el canal de soporte justo en la pantalla donde surge la duda.
Qué vamos a construir
El resultado será un bloque de soporte para cursos Moodle con cuatro elementos:
01 · CONTEXTO
Un título reconocible
«¿Necesitas ayuda?» permite identificar la función del bloque sin leer todo su contenido.
02 · ORIENTACIÓN
Una explicación breve
Un mensaje indica cuándo utilizar el canal y evita convertirlo en un acceso ambiguo.
03 · CONTACTO
Un correo directo
El enlace mailto: elimina pasos y lleva al estudiante al canal correcto.
04 · AUTOSERVICIO
Un acceso a la FAQ
El botón conduce a las preguntas frecuentes antes de abrir una nueva incidencia.
En Moodle 4.5, con el tema Boost, los bloques del curso se muestran normalmente en el cajón de bloques del lateral derecho. El usuario puede abrirlo o cerrarlo, de modo que el contenido debe ser breve, reconocible y útil; no podemos asumir que permanecerá siempre desplegado.

Una nota antes de empezar
Esta guía está pensada para aprender y trabajar en un entorno local o de pruebas. Instalar código propio en producción implica revisar seguridad, privacidad, accesibilidad, copias de seguridad, compatibilidad y un plan de reversión. Haz primero el recorrido completo en desarrollo o staging.
Qué es realmente un bloque en Moodle
Antes de crear un bloque en Moodle 4.5 conviene entender dónde encaja. Moodle es un sistema modular: el núcleo proporciona las capacidades comunes y los plugins amplían su comportamiento mediante actividades, formatos de curso, métodos de matriculación, informes, temas y bloques, entre otros.
Un bloque es un plugin orientado a mostrar información o funciones complementarias en diferentes páginas. No es la opción adecuada para crear una actividad evaluable —para eso existe el tipo mod—, pero encaja muy bien para accesos rápidos, resúmenes, avisos, indicadores o ayuda contextual.
| Necesidad | Tipo de solución más habitual |
|---|---|
| Actividad con entregas, intentos o calificación | Plugin de actividad mod |
| Información auxiliar en el lateral del curso | Plugin de bloque block |
| Funcionalidad transversal o integración interna | Plugin local local |
| Cambiar la presentación global | Tema theme |
La documentación oficial de plugins de bloque para Moodle 4.5 define la estructura y los métodos que utilizaremos. Si quieres ampliar primero la visión general, también puedes consultar 10 habilidades clave para desarrollar en Moodle.
Requisitos previos
- Una instalación de Moodle 4.5 para desarrollo o pruebas.
- PHP 8.1 o superior. Moodle 4.5 admite PHP 8.1, 8.2 y 8.3.
- Acceso al código fuente del servidor mediante un entorno local, SFTP, SSH o el mecanismo de despliegue de tu organización.
- Una cuenta administradora para completar la instalación del plugin.
- Un editor como Visual Studio Code o PhpStorm.
Para crear un bloque en Moodle 4.5 no necesitas modificar el core. De hecho, no debes hacerlo: desarrolla el componente dentro de /blocks, utiliza Git y no trabajes directamente sobre el servidor de producción.
⚠️ Advertencia — prepara un entorno desechable. La instalación de un plugin ejecuta el proceso de actualización de Moodle. Trabaja sobre una copia local o de staging, confirma que puedes restaurarla y guarda el código en Git antes de acceder a Administración del sitio → Notificaciones.
Paso 1: crear la estructura del bloque
El primer paso para crear un bloque en Moodle 4.5 es respetar su convención de nombres. Todos los plugins de este tipo viven dentro de /blocks. El nombre corto será soporte_curso, por lo que su componente completo —el nombre Frankenstyle que Moodle usa internamente— será block_soporte_curso.
blocks/soporte_curso/
├── block_soporte_curso.php
├── version.php
├── db/
│ └── access.php
├── lang/
│ ├── en/
│ │ └── block_soporte_curso.php
│ └── es/
│ └── block_soporte_curso.php
└── templates/
└── content.mustache| Archivo | Responsabilidad | En esta guía |
|---|---|---|
version.php | Identidad, versión y compatibilidad | Obligatorio |
block_soporte_curso.php | Clase principal y contenido del bloque | Obligatorio |
db/access.php | Capacidades para añadir instancias | Obligatorio |
lang/en/... | Idioma base y nombre del plugin | Obligatorio |
lang/es/... | Traducción al castellano | Recomendado |
templates/content.mustache | Presentación HTML | Recomendado |
⚠️ Advertencia — el nombre no admite aproximaciones. Utiliza minúsculas, guion bajo y ningún espacio en soporte_curso. La carpeta, el componente, la clase principal y los archivos de idioma deben mantener exactamente la misma identidad.
💡 Consejo — comprueba la estructura antes de seguir. Desde la raíz de Moodle debe existir exactamente blocks/soporte_curso/version.php. Si has descargado un ZIP, evita que aparezca una segunda carpeta soporte_curso dentro de la primera.

Paso 2: declarar el plugin en version.php
version.php es el manifiesto del plugin. Moodle lo utiliza durante la instalación y las actualizaciones para comprobar la identidad del componente, su versión y la versión mínima del core que necesita.
Crea blocks/soporte_curso/version.php:
<?php
defined('MOODLE_INTERNAL') || die();
$plugin->component = 'block_soporte_curso';
$plugin->version = 2026081100;
$plugin->requires = 2024100700; // Moodle 4.5.
$plugin->maturity = MATURITY_STABLE;
$plugin->release = '1.0.0';La propiedad component debe coincidir con la ubicación blocks/soporte_curso. En requires declaramos la primera versión de Moodle 4.5: de esta forma Moodle impedirá instalar el bloque en un core anterior.
Cómo leer 2026081100
El formato habitual es YYYYMMDDXX: año, mes, día y un contador de dos dígitos. 2026081100 representa la primera versión publicada el 11 de agosto de 2026. Si generas otra revisión ese mismo día, utilizarías 2026081101.
⚠️ Advertencia — no confundas dos conceptos. $plugin->version controla las actualizaciones que Moodle debe ejecutar; $plugin->release es una etiqueta legible para personas. Nunca reduzcas version en una instalación ya actualizada.
En desarrollo local puedes cambiar una plantilla o una cadena y purgar cachés. Para cada paquete o despliegue formal, incrementa la versión. Si en el futuro modificas la base de datos, además necesitarás db/upgrade.php y su correspondiente savepoint.
Puedes consultar todas las propiedades disponibles en la referencia oficial de version.php para Moodle 4.5.
Paso 3: añadir las cadenas de idioma
Los textos visibles no deben quedar repartidos por la lógica PHP. Moodle resuelve las cadenas mediante get_string() y el idioma activo de cada usuario. Todo plugin debe proporcionar, como mínimo, el archivo en inglés.
Idioma base: inglés
Crea lang/en/block_soporte_curso.php:
<?php
defined('MOODLE_INTERNAL') || die();
$string['pluginname'] = 'Course support';
$string['soporte_curso:addinstance'] = 'Add a new course support block';
$string['soporte_curso:myaddinstance'] = 'Add a new course support block to the Dashboard';
$string['block_title'] = 'Need help?';
$string['help_text'] = 'If you have technical issues or questions about the course, we are here to help.';
$string['contact_email'] = 'support@example.edu';
$string['btn_text'] = 'View frequently asked questions';
$string['faq_url'] = 'https://example.edu/help';Traducción al castellano
Crea lang/es/block_soporte_curso.php con las mismas claves:
<?php
defined('MOODLE_INTERNAL') || die();
$string['pluginname'] = 'Soporte del curso';
$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 Área personal';
$string['block_title'] = '¿Necesitas ayuda?';
$string['help_text'] = 'Si tienes problemas técnicos o dudas sobre el curso, estamos aquí para ayudarte.';
$string['contact_email'] = 'soporte@example.edu';
$string['btn_text'] = 'Consultar preguntas frecuentes';
$string['faq_url'] = 'https://example.edu/ayuda';💡 Consejo — sustituye los datos de ejemplo antes de probar. Cambia example.edu por direcciones reales de tu institución. En esta Parte 1 utilizamos cadenas de idioma para mantener el ejemplo pequeño. En la Parte 2 estos valores dejarán de estar fijos y se convertirán en configuración editable por curso.
🧭 Nota técnica — el inglés es el idioma de respaldo. Aunque tu plataforma funcione solo en castellano, conserva lang/en/block_soporte_curso.php y define allí pluginname. Moodle utiliza el paquete inglés cuando una traducción no existe en el idioma activo.
Las claves deben ser idénticas en todos los idiomas. Si Moodle no encuentra una cadena, mostrará algo parecido a [[block_title]]; suele ser una señal de nombre incorrecto o caché pendiente de purgar.
Paso 4: definir quién puede añadir el bloque
Las capacidades conectan el plugin con el sistema de roles y permisos de Moodle. No determinan quién puede ver el contenido público del bloque, sino quién puede crear una instancia en un curso o en su Área personal.
Crea db/access.php:
<?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' => [
'captype' => 'write',
'contextlevel' => CONTEXT_SYSTEM,
'archetypes' => [
'user' => CAP_ALLOW,
],
'clonepermissionsfrom' => 'moodle/my:manageblocks',
],
];addinstance permite que profesorado con edición y gestores añadan el bloque. myaddinstance es la capacidad estándar para el Área personal. En la clase principal limitaremos el bloque a las vistas de curso, de modo que esta segunda capacidad queda preparada, pero el bloque no aparecerá todavía en el Área personal.
⚠️ Advertencia — los arquetipos no son una migración de permisos. Cambiar los arquetipos de una capacidad en access.php no reescribe automáticamente los permisos que un administrador ya haya personalizado en una instalación existente. Comprueba los roles reales después de actualizar.
Paso 5: separar la presentación con Mustache
Podríamos concatenar HTML dentro de get_content(), pero mezclar lógica, datos y marcado produce un bloque difícil de mantener. Moodle utiliza Mustache como sistema de plantillas: PHP prepara un contexto de datos y la plantilla decide cómo representarlo.
Crea templates/content.mustache:
{{!
@template block_soporte_curso/content
Example context (json):
{
"block_title": "Need help?",
"help_text": "We are here to help.",
"contact_email": "support@example.edu",
"btn_text": "View frequently asked questions",
"faq_url": "https://example.edu/help"
}
}}
<div class="p-3 text-center">
<p class="h5 mb-3">{{block_title}}</p>
<p class="mb-3 text-muted">{{help_text}}</p>
<p class="mb-3">
<a href="mailto:{{contact_email}}"><strong>{{contact_email}}</strong></a>
</p>
<a href="{{faq_url}}" class="btn btn-primary w-100">{{btn_text}}</a>
</div>Las expresiones dobles {{variable}} escapan el contenido antes de insertarlo en el HTML. Esto es importante: no cambies a llaves triples salvo que el dato ya sea HTML seguro, filtrado y quieras renderizarlo deliberadamente como marcado.
⚠️ Advertencia de seguridad — evita {{{variable}}}. Las llaves triples desactivan el escape de Mustache. Si el valor procede de un formulario, una API o contenido editable, podrías introducir HTML no confiable y abrir la puerta a XSS. Mantén las llaves dobles y valida los datos antes de construir el contexto.
Paso 6: programar la clase principal
Ahora conectaremos las cadenas de idioma con la plantilla. Crea block_soporte_curso.php en la raíz del plugin:
<?php
defined('MOODLE_INTERNAL') || die();
class block_soporte_curso extends block_base {
/**
* Initialises the block title.
*/
public function init(): void {
$this->title = get_string('pluginname', 'block_soporte_curso');
}
/**
* Builds the block content.
*/
public function get_content(): ?stdClass {
global $OUTPUT;
if ($this->content !== null) {
return $this->content;
}
$faqurl = new moodle_url(
get_string('faq_url', 'block_soporte_curso')
);
$data = [
'block_title' => get_string('block_title', 'block_soporte_curso'),
'help_text' => get_string('help_text', 'block_soporte_curso'),
'contact_email' => get_string('contact_email', 'block_soporte_curso'),
'btn_text' => get_string('btn_text', 'block_soporte_curso'),
'faq_url' => $faqurl->out(false),
];
$this->content = new stdClass();
$this->content->text = $OUTPUT->render_from_template(
'block_soporte_curso/content',
$data
);
$this->content->footer = '';
return $this->content;
}
/**
* Restricts the block to course pages.
*/
public function applicable_formats(): array {
return [
'all' => false,
'course-view' => true,
];
}
/**
* Prevents duplicate support blocks in the same course.
*/
public function instance_allow_multiple(): bool {
return false;
}
}Qué ocurre en cada carga de página
- Moodle instancia
block_soporte_cursoy ejecutainit(). - Cuando necesita el contenido, llama a
get_content(). - El plugin recupera las cadenas correspondientes al idioma del usuario.
moodle_urlvalida y representa la URL del botón.- El contexto
$datapasa atemplates/content.mustache. - Mustache genera el HTML y escapa las variables insertadas con llaves dobles.

La comprobación de $this->content !== null evita preparar el mismo contenido más de una vez durante la carga. applicable_formats() impide que el bloque se ofrezca fuera de las páginas de curso y instance_allow_multiple() evita duplicados idénticos.
💡 Consejo para publicar el plugin. Añade a cada archivo PHP la cabecera GPL y los bloques PHPDoc exigidos por las normas de código de Moodle. Los fragmentos del tutorial se han mantenido compactos para que la arquitectura sea legible, pero el paquete que distribuyas debe superar las comprobaciones de estilo y Plugin Check.
Paso 7: instalar el bloque en Moodle 4.5
Comprueba primero que la carpeta final sea blocks/soporte_curso. Un error habitual es introducir un nivel adicional al descomprimir el ZIP, por ejemplo blocks/soporte_curso/soporte_curso/version.php; Moodle no detectará esa estructura.
Instalación desde la interfaz web
- Copia la carpeta
soporte_cursodentro de/blocks. - Accede como administrador a Administración del sitio → Notificaciones.
- Verifica que Moodle muestre el componente
block_soporte_cursosin errores de dependencia. - Pulsa Actualizar base de datos Moodle ahora y espera el mensaje de confirmación.

Alternativa por línea de comandos
En despliegues automatizados es preferible ejecutar la actualización desde la raíz de Moodle:
php admin/cli/upgrade.php --non-interactiveEjecuta el comando con el usuario correcto del sistema y dentro de tu procedimiento habitual de mantenimiento, copia de seguridad y reversión.
⚠️ Advertencia — instalar no es copiar archivos. La copia deja el código disponible, pero la instalación no termina hasta que Moodle ejecuta la actualización. No interrumpas upgrade.php, revisa su código de salida y conserva un mecanismo de reversión coherente entre archivos, base de datos y cachés.
Paso 8: añadir y probar el bloque
- Entra en un curso con un usuario que tenga permisos de edición.
- Activa el modo de edición.
- Abre el cajón lateral y pulsa Agregar un bloque.
- Busca Soporte del curso si utilizas castellano o Course support si utilizas inglés.
- Selecciona el bloque y comprueba que aparece en el cajón.

pluginname y cambia con el idioma del usuario.
Prueba mínima antes de darlo por terminado
- Profesor con edición: puede añadir el bloque y no puede crear una segunda copia.
- Estudiante: puede verlo y usar sus enlaces, pero no añadirlo ni configurarlo.
- Idiomas: el nombre y los textos cambian al alternar entre inglés y castellano.
- Enlaces: el correo abre el cliente de email y el botón conduce a la URL real de ayuda.
- Responsive: el texto y el botón caben en el cajón sin desbordarse.
- Ámbito: el bloque se ofrece en cursos, no en páginas para las que no fue diseñado.
✅ Comprobación superada. Si un profesor puede añadir una única instancia, un estudiante la ve sin opciones de edición, los textos cambian de idioma y ambos enlaces funcionan, ya tienes completa la primera versión funcional del bloque.
Cuándo purgar las cachés de Moodle
Durante el desarrollo, Moodle puede conservar cadenas, plantillas y metadatos del plugin. Si un cambio correcto no aparece, ve a Administración del sitio → Desarrollo → Purgar todas las cachés o ejecuta:
php admin/cli/purge_caches.phpPurgar cachés es una comprobación útil, no una solución universal. Si el error persiste al crear un bloque en Moodle 4.5, revisa el registro de PHP, la depuración de Moodle, los nombres de componente y los permisos de archivos.
💡 Consejo de diagnóstico — purga una vez y observa. Si el cambio sigue sin aparecer después de purgar, no repitas el comando a ciegas. Comprueba qué archivo se está cargando, revisa los logs y confirma que el navegador apunta a la misma instalación que estás editando.
Errores comunes al crear un bloque en Moodle 4.5
| Síntoma | Causa probable | Qué comprobar |
|---|---|---|
| Pantalla en blanco o error 500 | Error de sintaxis o excepción PHP | Ejecuta php -l, consulta los logs y activa depuración solo en desarrollo |
[[pluginname]] | Cadena de idioma no encontrada | Ruta, nombre del archivo, clave y purgado de caché |
| El plugin no se detecta | Estructura o version.php incorrectos | Que exista blocks/soporte_curso/version.php sin un directorio intermedio |
| No aparece en «Agregar un bloque» | Capacidad, ámbito o instalación incompletos | db/access.php, applicable_formats() y Notificaciones |
| El botón abre una página inexistente | Se dejó la URL de ejemplo | Sustituye example.edu en los dos idiomas |
| Los cambios no se reflejan | Caché de idioma o plantilla | Purga cachés y confirma que estás editando la instalación correcta |
⚠️ Advertencia — no muestres errores detallados en producción. La depuración con nivel DEVELOPER puede exponer rutas, consultas y datos internos. Utilízala en un entorno controlado y desactívala al terminar.
Qué falta antes de considerarlo un plugin de producción
El bloque ya funciona, pero «funciona en mi curso» no equivale a «está listo para distribuir». Antes de instalarlo en una plataforma real, revisa:
- Cabeceras GPL, PHPDoc y cumplimiento de las normas de código de Moodle.
- Icono propio en
pix/icon.svg, README, licencia y registro de cambios. - Declaración correcta en la Privacy API, aunque el plugin no almacene datos personales.
- Pruebas automatizadas y comprobaciones con Moodle Plugin CI o Plugin Check.
- Pruebas con el tema real de la institución, roles personalizados e idiomas utilizados.
- Procedimiento de despliegue, copia de seguridad, monitorización y reversión.
Este trabajo no añade una función llamativa a la demo, pero evita que un plugin pequeño se convierta en deuda técnica cuando llegue a decenas de cursos.
✅ Criterio práctico de salida. No promociones el bloque solo porque se renderice. Hazlo cuando puedas instalarlo desde cero, actualizarlo, probarlo con los roles reales y retirarlo mediante un procedimiento conocido sin dejar la plataforma en un estado inconsistente.
La limitación actual y lo que haremos en la Parte 2
Preguntas frecuentes
¿Puedo crear un bloque de Moodle solo desde la interfaz web?
No. Necesitas crear o desplegar los archivos del plugin en el servidor. La interfaz de administración completa la instalación, pero no sustituye el desarrollo del componente.
¿Es obligatorio crear el archivo de idioma inglés?
Sí. lang/en/block_soporte_curso.php es el idioma base obligatorio del plugin. Después puedes añadir es, ca, fr u otros paquetes con las mismas claves.
¿Por qué usamos Mustache en vez de concatenar HTML en PHP?
Porque separa los datos de la presentación, facilita que los temas sobrescriban la plantilla y aplica autoescapado a las variables normales. El resultado es más mantenible y menos propenso a errores.
¿El código funcionará en Moodle 5?
La API básica de bloques continúa existiendo, pero este tutorial fija Moodle 4.5 como versión mínima y objetivo de prueba. Antes de declarar compatibilidad con Moodle 5.x debes ejecutar el plugin en esa rama, revisar cambios de interfaz y completar tus pruebas.
¿Necesito una tabla de base de datos para este bloque?
No. Esta primera versión solo muestra cadenas y enlaces. La configuración estándar de una instancia de bloque tampoco obliga a crear una tabla propia: Moodle guarda los datos de instancia mediante su infraestructura.
Conclusión: ya tienes tu primer bloque en Moodle 4.5
Ahora ya sabes crear un bloque en Moodle 4.5 con una base mantenible. Moodle reconoce el componente, controla quién puede añadirlo, resuelve sus textos según el idioma y delega la presentación en una plantilla Mustache.
La lección importante no es cómo mostrar un correo en un lateral. Es cómo encajar una necesidad sencilla dentro de las convenciones de una plataforma grande sin crear una excepción difícil de mantener.
A partir de aquí puedes ampliar el bloque con configuración, permisos específicos, estilos propios, eventos o datos procedentes de otras APIs. Esa evolución será mucho más segura porque la base ya respeta la forma en la que Moodle espera que trabajen sus plugins.
DEL TUTORIAL A PRODUCCIÓN
Que el bloque aparezca es el principio. Que siga funcionando en producción es el trabajo.
El siguiente problema rara vez está en el HTML. Suele aparecer en una actualización, bajo carga o cuando los permisos reales no se parecen a los del entorno de pruebas. Si tu Moodle depende de plugins propios, en Entornos de Formación podemos revisar el desarrollo contigo antes de que una prueba superada se convierta en una incidencia.
- Compatibilidad: Moodle 4.5, evolución a 5.x y estrategia de actualización.
- Seguridad: capacidades, contextos, validación de entradas y exposición de datos.
- Rendimiento y mantenimiento: consultas, caché, arquitectura y deuda técnica.
¿Todavía estás aprendiendo? La Parte 2 continúa el mismo bloque con configuración, seguridad por contextos, caché MUC y una arquitectura preparada para crecer.

Deja una respuesta