PROMPT:
Acabo de conseguir leer los albumes al ejecutar /coppermine/test. Ahora quiero que me muestre las categorías y los albumes dentro de cada categoría.

ChatGPT Plus

¡Excelente! 🎉 Ya leer los álbumes desde Coppermine es un gran paso, ¡muy bien hecho!

Ahora vamos a mostrar las categorías y los álbumes que pertenecen a cada una, usando las tablas de Coppermine.


📚 Tablas relevantes de Coppermine

En una instalación típica de Coppermine:

  • Las categorías están en la tabla: cpg_categories

    • Campo clave: cid

    • Campo de nombre: name

  • Los álbumes están en la tabla: cpg_albums

    • Campo de categoría: category

    • Campo de título: title

Entonces la relación es:

📁 cpg_categories.cid → cpg_albums.category


🎯 Objetivo

Mostrar en /coppermine/test algo como:

markdown
📂 Naturaleza - Animales salvajes - Paisajes de montaña 📂 Eventos - Cumpleaños - Bodas

🧩 Código actualizado para AlbumController::test()

php
public function test() { try { // Conexión a la base de datos Coppermine $connection = Database::getConnection('default', 'coppermine'); // Obtener categorías (ignoramos la categoría con cid = 0 que suele ser "Sin categoría") $categories = $connection->select('cpg_categories', 'c') ->fields('c', ['cid', 'name']) ->condition('cid', 0, '>') ->orderBy('name') ->execute() ->fetchAllKeyed(); // [cid => name] // Obtener álbumes agrupados por categoría $albums_query = $connection->select('cpg_albums', 'a') ->fields('a', ['aid', 'title', 'category']) ->orderBy('title'); $albums = $albums_query->execute()->fetchAll(); // Organizar álbumes por categoría $output = []; foreach ($categories as $cid => $cat_name) { $output[$cat_name] = []; } foreach ($albums as $album) { $category_name = $categories[$album->category] ?? 'Sin categoría'; $output[$category_name][] = $album->title; } // Convertir a render array $render = [ '#title' => $this->t('Categorías y álbumes desde Coppermine'), '#markup' => '', ]; foreach ($output as $category => $album_titles) { $render['#markup'] .= "<h2>$category</h2><ul>"; foreach ($album_titles as $title) { $render['#markup'] .= "<li>$title</li>"; } $render['#markup'] .= "</ul>"; } $render['#markup'] = ['#markup' => $render['#markup'], '#allowed_tags' => ['h2', 'ul', 'li']]; return $render; } catch (\Exception $e) { return [ '#markup' => $this->t('Error al conectar con Coppermine: @msg', ['@msg' => $e->getMessage()]), ]; } }

✅ Resultado

Cuando entres a /coppermine/test, deberías ver:

  • Una lista de categorías (<h2>)

  • Con sus álbumes debajo (<ul><li>)


¿Quieres que cada álbum tenga un enlace a un visor? ¿O añadir imágenes del álbum en esta misma vista? Puedo ayudarte paso a paso con eso también.

Tú dijiste:
me sale el error: The website encountered an unexpected error. Try again later. TypeError: strlen(): Argument #1 ($string) must be of type string, array given in strlen() (line 395 of core/lib/Drupal/Component/Utility/Unicode.php).
ChatGPT Plus

¡Gracias por compartir el error! Ese mensaje:

TypeError: strlen(): Argument #1 ($string) must be of type string, array given...

...indica que en algún lugar Drupal espera una cadena (string), pero está recibiendo un array.


🔍 Causa exacta

El problema está en esta línea del código que te pasé:

php
$render['#markup'] = ['#markup' => $render['#markup'], '#allowed_tags' => ['h2', 'ul', 'li']];

Ahí accidentalmente estamos asignando un array a #markup, pero #markup solo acepta cadenas de texto.


✅ Solución rápida

Cambia esa línea:

php
$render['#markup'] = ['#markup' => $render['#markup'], '#allowed_tags' => ['h2', 'ul', 'li']];

por esta otra forma correcta:

php
$render = [ '#type' => 'inline_template', '#template' => '{{ content|raw }}', '#context' => [ 'content' => $render['#markup'], ], ];

💡 ¿Por qué funciona esto?

  • #markup acepta solo texto plano y renderiza escapando etiquetas HTML.

  • #type => inline_template con |raw nos permite usar HTML personalizado con seguridad controlada.

  • Es la forma recomendada en Drupal 10 cuando quieres meter HTML personalizado directamente.


🧪 Versión final corregida de test()

php
public function test() { try { $connection = Database::getConnection('default', 'coppermine'); $categories = $connection->select('cpg_categories', 'c') ->fields('c', ['cid', 'name']) ->condition('cid', 0, '>') ->orderBy('name') ->execute() ->fetchAllKeyed(); $albums_query = $connection->select('cpg_albums', 'a') ->fields('a', ['aid', 'title', 'category']) ->orderBy('title'); $albums = $albums_query->execute()->fetchAll(); $output = []; foreach ($categories as $cid => $cat_name) { $output[$cat_name] = []; } foreach ($albums as $album) { $category_name = $categories[$album->category] ?? 'Sin categoría'; $output[$category_name][] = $album->title; } // Construir HTML manualmente $html = ''; foreach ($output as $category => $album_titles) { $html .= "<h2>$category</h2><ul>"; foreach ($album_titles as $title) { $html .= "<li>$title</li>"; } $html .= '</ul>'; } return [ '#type' => 'inline_template', '#template' => '{{ content|raw }}', '#context' => [ 'content' => $html, ], ]; } catch (\Exception $e) { return [ '#markup' => $this->t('Error al conectar con Coppermine: @msg', ['@msg' => $e->getMessage()]), ]; } }

CODIGO FINAL OPERATIVO:
<?php

namespace Drupal\coppermine_test1\Controller;

use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\DataBase\DataBase;

class AlbumController extends ControllerBase {
public function test() {
try {
// Conexión a la base de datos Coppermine
$connection = Database::getConnection('default', 'coppermine');
// Obtener categorías (ignoramos la categoría con cid = 0 que suele ser "Sin categoría")
$categories = $connection->select('categories', 'c')
->fields('c', ['cid', 'name'])
->condition('cid', 0, '>')
->orderBy('name')
->execute()
->fetchAllKeyed(); // [cid => name]
// Obtener álbumes agrupados por categoría
$albums_query = $connection->select('albums', 'a')
->fields('a', ['aid', 'title', 'category'])
->orderBy('title');
$albums = $albums_query->execute()->fetchAll();
// Organizar álbumes por categoría
$output = [];
foreach ($categories as $cid => $cat_name) {
$output[$cat_name] = [];
}
foreach ($albums as $album) {
$category_name = $categories[$album->category] ?? 'Sin categoría';
$output[$category_name][] = $album->title;
}
// Convertir a render array
$render = [
'#title' => $this->t('Categorías y álbumes desde Coppermine'),
'#markup' => '',
];
foreach ($output as $category => $album_titles) {
$render['#markup'] .= "<h2>$category</h2><ul>";
foreach ($album_titles as $title) {
$render['#markup'] .= "<li>$title</li>";
}
$render['#markup'] .= "</ul>";
}
$render = [
'#type' => 'inline_template',
'#template' => '{{ content|raw }}',
'#context' => [
'content' => $render['#markup'],
],
];
return $render;
}
catch (\Exception $e) {
return [
'#markup' => $this->t('Error al conectar con Coppermine: @msg', ['@msg' => $e->getMessage()]),
];
}
}
}

Última modificación: venres, 4 de abril de 2025, 10:23 AM