Bases de datos en Joomla!

Siguiendo con nuestro último tutorial en el que vimos cómo desarrollar módulos para Joomla veremos ahora cómo trabajar con bases de datos al programar para este CMS, bien utilizando sentencias SQL, a través de la clase JDatabase, o bien mediante la clase JTable, haciendo uso de una especie de pequeño ORM (mapeo objeto-relacional) basado en el patrón active record.

JDatabase

Lo primero que debemos hacer a la hora de usar JDatabase, la clase que representa una conexión a la base de datos en Joomla, es obtener una instancia de la clase. Para ello haremos uso de JFactory, una clase que ofrece varios métodos estáticos para obtener instancias de distintos singleton del framework, como pueden ser el objeto sesión (getSession), el objeto usuario (getUser) o el propio objeto JDatabase (getDBO).

$db =& JFactory::getDBO();

Para preparar una consulta se utiliza setQuery. Algo a tener en cuenta a la hora de escribir nuestras consultas es que debemos sustituir el prefijo de las tablas de Joomla (jos_ normalmente) por #__. De esta forma el usuario podrá utilizar el prefijo que prefiera para las tablas de Joomla, ya que el framework se encargará de sustituir este prefijo por el adecuado antes de ejecutar la consulta.

$query = 'CREATE TABLE #__empleado(id INT NOT NULL AUTO_INCREMENT, nombre VARCHAR(20), departamento VARCHAR(20), PRIMARY KEY(id))';
$db->setQuery($query);

Para ejecutar la consulta se utiliza el método query()

$db =& JFactory::getDBO();
$query = 'CREATE TABLE #__empleado(id INT NOT NULL AUTO_INCREMENT, nombre VARCHAR(20), departamento VARCHAR(20), PRIMARY KEY(id))';
$db->setQuery($query);
$db->query();

Si la consulta que vamos a ejecutar es un SELECT, podemos sustituir el método query por uno de los siguientes métodos, dependiendo del tipo de resultado que necesitemos obtener:

  • loadResult: un único valor
    $db =& JFactory::getDBO();
    $query = 'SELECT nombre FROM #__empleado LIMIT 1';
    $db->setQuery($query);
    $nombre = $db->loadResult();
    echo $nombre;
  • loadResultArray: un array con los valores de las distintas tuplas para un cierto campo
    $db =& JFactory::getDBO();
    $query = 'SELECT nombre FROM #__empleado';
    $db->setQuery($query);
    $nombres = $db->loadResultArray();
    
    foreach($nombres as $nombre)
      echo $nombre, '<br/>';
  • loadAssoc: un array asociativo en el que las claves son los campos de la tupla
    $db =& JFactory::getDBO();
    $query = 'SELECT * FROM #__empleado';
    $db->setQuery($query);
    $empleado = $db->loadAssoc();
    
    foreach($empleado as $campo => $valor)
      echo $campo, ': ', $valor, '<br/>';
  • loadAssocList: una lista con un array asociativo para cada tupla
    $db =& JFactory::getDBO();
    $query = 'SELECT * FROM #__empleado';
    $db->setQuery($query);
    $empleados = $db->loadAssocList();
    
    foreach($empleados as $empleado) {
      foreach($empleado as $campo => $valor)
        echo $campo, ': ', $valor, '<br/>';
      echo '<hr/>';
    }
  • loadObject: un objeto en el que las propiedades son los atributos de la tupla
    $db =& JFactory::getDBO();
    $query = 'SELECT * FROM #__empleado LIMIT 1';
    $db->setQuery($query);
    $empleado = $db->loadObject();
    
    echo 'Nombre: ', $empleado->nombre, '<br/>';
    echo 'Departamento: ', $empleado->departamento, '<br/>';
  • loadObjectList: una lista de objetos, uno por cada tupla
    $db =& JFactory::getDBO();
    $query = 'SELECT * FROM #__empleado';
    $db->setQuery($query);
    $empleados = $db->loadObjectList();
    
    foreach($empleados as $empleado) {
      echo 'Nombre: ', $empleado->nombre, '<br/>';
      echo 'Departamento: ', $empleado->departamento, '<br/>';
      echo '<hr/>';
    }
  • loadRow: devuelve un array con todos los campos de una tupla
    $db =& JFactory::getDBO();
    $query = 'SELECT * FROM #__empleado LIMIT 1';
    $db->setQuery($query);
    print_r($db->loadRow());
  • loadRowList: devuelve una lista en la que cada posición es un array con todos los campos de una tupla
    $db =& JFactory::getDBO();
    $query = 'SELECT * FROM #__empleado';
    $db->setQuery($query);
    print_r($db->loadRowList());

Por último para tratar los errores podemos hacer uso de los métodos getErrorNum y getErrorMsg. Supongamos que nos hubieramos equivocado al escribir el SELECT, por ejemplo:

$db =& JFactory::getDBO();
$query = 'SELEC * FROM #__empleado';
$db->setQuery($query);
$empleados = $db->loadAssocList();

if ($db->getErrorNum()) {
	echo $db->getErrorMsg();
	return;
}

JTable

Para cada tabla para la que queramos utilizar JTable para llevar a cabo las operaciones de creación, lectura, actualización o borrado tendremos que crear un archivo que contenga una clase que extienda JTable, con un atributo por cada columna de la tabla y un constructor que llamará al de la clase padre pasando como argumentos el nombre de la tabla, la clave primaria y el objeto que representa la conexión con la BBDD. El nombre de la nueva clase será, por convención, Table seguido del nombre de la entidad (TableUsuario, TableEdificio, etc) y el nombre del archivo, el mismo nombre sin el prefijo Table (usuario.php, edificio.php, etc).

<?php
defined('_JEXEC') or die('Restricted access');

class TableEmpleado extends JTable {
	var $id = null;
	var $nombre = null;
	var $departamento = null;
	
	function __construct(&$db) {
		parent::__construct('#__empleado', 'id', $db);
	}
}

?>

Una vez creada esta clase podemos instanciarla a partir de JTable. Primero le indicaremos dónde buscar las clases de las tablas (en este ejemplo utilizamos las constantes JPATH_BASE, el directorio en el que se instaló Joomla, y DS, el separador de directorios en este sistema operativo) y luego qué clase instanciar:

JTable::addIncludePath(JPATH_BASE.DS.'modules'.DS.'mod_ejemplo'.DS.'tables');
$empleado =& JTable::getInstance('empleado', 'Table');

Una vez hecho esto ya podremos utilizar los métodos de nuestro nuevo objeto. Para traer una tupla de la base de datos usaríamos el método load, al que se le pasa la clave a buscar:

$empleado->load(1);
echo $empleado->nombre, ': ', $empleado->departamento;

Para crear una nueva tupla en la base de datos establecemos los valores para los campos con set, comprobamos que sean válidos con check y los almacenamos con store.

$empleado->set('nombre', 'Samuel');
$empleado->set('departamento', 'Recursos humanos');

if (!$empleado->check() or !$empleado->store()) {
  echo 'Ocurrio un error: ', $empleado->getError();
}

También podemos establecer los valores para los campos mediante un array, con el método bind:

$datos = array('nombre' => 'Carlos', 'departamento' => 'Finanzas');

$empleado->bind($datos);

if (!$empleado->check() or !$empleado->store()) {
  echo 'Ocurrio un error: ', $empleado->getError();
}

O usar el método save, que llama a su vez a bind, check y store

$datos = array('nombre' => 'Juan', 'departamento' => 'Mantenimiento');

if (!$empleado->save($datos)) {
  echo 'Ocurrio un error: ', $empleado->getError();
}

Para actualizar una tupla podemos hacer uso de una combinación de load y store

$empleado->load(1);

$empleado->set('departamento', 'Finanzas');

if (!$empleado->check() or !$empleado->store()) {
  echo 'Ocurrio un error: ', $empleado->getError();
}

Por último, para borrar una tupla utilizaremos el método delete, al que se le pasa el identificador de la tupla que queremos eliminar:

$empleado->delete(1);

Comentarios
  1. y el tutorial de Drupal viene después?

    para mi no hay color entre drupal y joomla. joomla es una chapuzilla

    Responder

    • amigo

      Yo pensaba que joomla es la evolución de drupal 🙂

      Responder

    • Bueno, cada cuál tiene sus puntos fuertes.

      Joomla es más conocido, pero Drupal está creciendo bastante últimamente, y lo utilizan webs como la de Ubuntu o la de la Casa Blanca.

      Drupal ofrece un framework bastante interesante, pero la usabilidad de la interfaz deja mucho que desear (aunque en Drupal 7 parece que han solucionado muchos de los problemas).

      En cuestión de plantillas, por ejemplo, Joomla gana por goleada. Pero para CCK, por otro lado, Joomla necesita de alguna extensión como K2, y está muy lejos de lo que se puede hacer con Drupal.

      Responder

    • lrcvrino

      Por desgracia y pereza hablo desde la ignorancia en cuanto a DRUPAL, pero ya hablaremos cuando salga joomla 1.6 (si es que sale…)

      Responder

  2. Me ha encantado lo de “loadObject” y “loadObjectList”, muy buena/útil abstracción 😀

    Responder

  3. Joomla ha mejorado mucho, Joomla 1.6 va a ser una evolución con sus nuevas ACL. Para CCK, Joomla dispone de componentes como K2, Flexicontent y algunos más que pueden hacer cosas similares a lo que hace CCK en Drupal.

    Eso de que Joomla es una chapucilla estaba justificado en Joomla 1.0 que tenía bastante código espagueti por ahí suelto, pero desde ya hace casi 4 años que salio Joomla 1.5 y de chapucilla nada, solo hace falta ver el API, como en este nos muetsra Zootropo, el uso de patrones está muy bien implementado dando como resultado un código muy ordenado.

    Un saludo a todos.

    Responder

  4. […] Joomla!: nacido de un forking del entonces popular Mambo, Joomla! lleva años siendo uno de los CMS libres más utilizados del mercado. En Mundo geek he publicado varios artículos sobre desarrollo para este CMS, como Creación de módulos en Joomla!, Tipos de parámetros para las extensiones de Joomla! y Bases de datos en Joomla!. […]

    Responder

  5. Muy buena la guía, sólo me queda ponerme a probarlo, la última vez que pelee con joomla para hacer un portal de vídeo online, me resulto algo complicado, espero tener más suerte.

    Responder

  6. alan

    que tal?
    estuve tratando de ejecutar una query en un nuevo archivo tal como lo explican aca, pero me aparecen errores, hay que hacer un include ?
    les agradezco !
    saludos

    Responder

  7. Problemas con la base de datos

    Hola:

    Estoy buscando la manera de crear un boton que permita borrar articulos a los usuarios con derechos para hacerlo.

    El codigo lo he insertado en default_item.php

    Codigo original:
    ************************************************** *****************

    item, $this->item->params, $this->access); ?>

    ************************************************** *****************
    Codigo añadido
    ************************************************** *****************

    <a
    title="Elimina el articulo" onclick="return removeContent('item->id; ?>’)”
    target=”_blank”
    class=”fb_share_link”>

    ************************************************** *******************

    Como se puede observar el boton solo le aparecera a los usuarios que tienen permisos de edicion del articulo .

    El boton me aparece bien y solo en los usuarios que deberia pero soy incapaz de hacer que la siguiente funcion se ejecute.

    function removeContent( id ) {
    $db = &JFactory::getDBO();
    query = “DELETE FROM jos_content where id='”+id+”‘”;
    $db->setQuery(query);
    $db->query();
    return true;
    }

    La query es correcta y el parametro le llega bien a la funcion, la he comprobado dejandola asi:

    function removeContent( id ) {
    query = “DELETE FROM jos_content where id='”+id+”‘”;
    window.open(“http://”+query);
    }
    y me aparece en la barra del explorador la query tal y como deberia ser enviada a la base de datos asi que el problema esta en obtener el descriptor de la base de datos o en ejecutar la query.

    ¿Alguna idea?

    Responder

    • hola,,, ya solucionastes este codigo??? estoy buscando hacer algo similar a esto pero con un sistema de votacion, que me permita solo dar permiso y aparecer en el perfil de los autorizados. si ya solventastes algo sobre este tema, te es posible ofrecerme el codigo de esto para adaptarlo a otro componente de votacion que ya tengo? ojala me ayudes y si lo tienes documentacion y explicativo, mucho mejor, ya que estoy iniciando en esto de la programacion web y me vendria de mucha ayuda. Cuenta con un amigo mas y quedo agradecido de antemano a la atencion prestada. MIL gracias. RODOLFO

      Responder

  8. Albert

    Hola,

    No sé si es que no estoy viendo bien el código, pero creo que el problema está en que la función “removeContent” es de javascript, y estás intentando que esa función ejecute código php. No sé si la idea es que los usuarios puedan eliminar artículos de Joomla desde el frontent, pero Joomla permite a los usuarios con los permisos necesarios editar contenido desde el frontend, no sé si también permite eliminar, pero en todo caso, no podrás ejecutar código php desde javascript así, deberías cambiar el destino del link a algún script php que se encarge de eliminar el artículo, o hacerlo a través de ajax.
    Espero te haya servido de algo la explicación.

    Saludos,

    Albert

    Responder

  9. Estela

    Me gustaria saber como hacer un select WHERE donde id de la tabla users sea igual a id que se guardó en otra tabla.

    Responder

  10. […] Joomla!: nacido de un forking del entonces popular Mambo, Joomla! lleva años siendo uno de los CMS libres más utilizados del mercado. En Mundo geek he publicado varios artículos sobre desarrollo para este CMS, como Creación de módulos en Joomla!, Tipos de parámetros para las extensiones de Joomla! y Bases de datos en Joomla!. […]

    Responder

  11. GUSTAVO

    Amigo donde me puedo descargar la base de datos de joomla o la de una web de tipo carrito de compras

    Responder

    • MATI

      descarga el componente virtuemart

      Responder

  12. otra opcion para crear bases de datos

    Responder

  13. Nestor

    como se define la extensión con primary key compuesta

    Responder

  14. Gracias por el minitutorial. Muy didactico. 😉

    Responder

  15. […] Joomla!: nacido de un forking del entonces popular Mambo, Joomla! lleva años siendo uno de los CMS libres más utilizados del mercado. En Mundo geek he publicado varios artículos sobre desarrollo para este CMS, como Creación de módulos en Joomla!, Tipos de parámetros para las extensiones de Joomla! y Bases de datos en Joomla!. […]

    Responder

  16. Una pregunta: Cómo yo puedo insertar datos desde un sitio joomla a otro sitio joomla, hay alguna clase donde yo pueda definir el nombre de la base de datos???

    Responder

  17. Ayuda con mi consulta de suma a id

    buenas gente, tengo el siguiente problema:

    Tengo un componente el cual tengo que hacer que el numero de referido sea el mismo que el id del contenido. Hasta ahí muy bién, pues he aplicado un poco lo que han comentado aquí que por cierto esta muy bueno, pero no he tenido exito. He hecho lo siguiente:

    if (empty($this->mls_id)) {
    $db =& JFactory::getDBO();
    $query = “SELECT MAX(id) FROM __tabla”;
    $db->setQuery($query);
    $result = $db->loadObjectList();
    $nuevo_id = $result + 1;

    $this->mls_id = ‘TGL-0′. $nuevo_id;

    } else {

    $this->mls_id = substr().’TGL-0’. $this->id;

    }

    Ok lo que necesito es que me tome el último id de la tabla y le sume 1 que será el nuevo id del nuevo contenido, pero no he podido llegarle, no se en que estoy fallando.

    Gracias de antemano por la ayuda.

    Responder

  18. tucuta

    Buenas mi gente, vuelvo por ultima vez a ver si todavía hay alguien que quiera ayudar por aca.

    De antemano muuuchas gracias a la gente que me pueda hechar un cable.

    Les cuento:

    Necesito realizar una consulta al ultimo id de un campo autoincrement.

    Hasta el momento tengo lo siguiente:

    $db = JFactory::getDbo();
    $query= ‘(SELECT MAX(id)+1 FROM #__users)’;
    $db->setQuery($query);
    $result=$db->loadResult();
    return $result;

    Lo que hago con esto es que leo cual es el último id del campo ‘id’ y le sumo uno. Hasta ahí todo bién.

    Por ejemplo tengo los siguiente id:

    1, 2, 3, 4, 5

    Si borro el id 5 el siguiente id en la tabla sería el 6 porque el campo es autoincrementable. Con el código que puse arriba solo puedo tomar el ultimo id en el campo no de la tabla, de manera que si borro el id 5 el codigo me pone nuevamente el 5, cuado en realidad el número que sigue es el 6.

    No se que estoy haciendo mal y de verdad espero que alguien me pueda hechar un cablecito y de una que quede para lo que tengan la misma duda.

    Muchas gracias mi gente.

    Responder

  19. mark

    Pregunta de como consultar y reempalzar un dato en una campo de una tabla:
    Yo uso este en joomla, par aobtener el ID:
    $user = JFactory::getUser();
    return $user->get(‘id’);

    Para el caso, empleo un formulario de RSForm Pro
    En el quiero declarar asi:
    $usergrupo = JFactory::getUser_Group_Map();
    return $usergrupo->get(‘id’);
    ….
    Es correcto uar el mismo para poder obteerlo… la cuesion es ocmo reempalzar su valor actual, digamos tiene el ID= 23, y se lo quiero cambiar al ID=45

    En rs form pro, podes declarar un campo oculto, con un valor predetermiando, pero este no me resulta al asignarlo a la tabla, pq solo le agrega el nuevo ID del USER mas el nuevo ID de GRUPO, hacieno asi un total de 2 grupos asignados a este usuario logueado.

    Responder

  20. Buenas tardes, solo paso para felicitarlos por este post, me ha ayuda en más de una ocasión. este post se encuentra en mis favoritos de Joomla y MySql.

    Responder

  21. jeisson

    hola amigos,estoy haciendo un componente, tengo una consulta urgente y les agradecería si me la pueden resolver.

    quiero hacer un formulario pero no se como hacer el codigo de:el modelo,el controlador y la vista para que me haga las consultas

    hice un formulario en la vista:

    view/report/tmpl/default.php

    su nombre:

    Tel:

    direccion:

    la base de datos en mysql se llama “pruebas”, la tabla se llama “amigos” y las columnas son: id, nombre, dirección y telefono

    como sería el código para el modelo y para el controlador para que el formulario me funcione?

    Responder

  22. jeisson

    q pena no se como escribirles el código html del formulario como comentario
    pero pues es un formulario q pide nombre telefono y direccion y quiero q los muestre cuando yo le de enviar

    Responder

Deja un comentario