Joomla! Discussion Forums



It is currently Tue Nov 24, 2009 12:59 pm (All times are UTC )

 





Post new topic Reply to topic  [ 12 posts ] 
Author Message
Posted: Sun May 18, 2008 10:18 pm 
Joomla! Apprentice
Joomla! Apprentice
Offline

Joined: Sun Apr 20, 2008 9:44 pm
Posts: 39
Hola a todos.

Como otros muchos soy nuevo con J! 1.5 y teniendo que desarrollar un componente me encontré con el problema de que la documentación existente explicaba el modelo MVC a base de ejemplos en los que se mostraban los ficheros necesarios para pintar la famosa frasecilla 'Hola Mundo!'. Sin embargo ninguno de los documentos que encontré explicaba cómo funciona por dentro J! por lo que en cuanto me salía un poco de los ejemplos empezaba a tener problemas.

Al final me las arreglé para aprender por qué J! hace lo que hace y aprovecho este foro para ofrecerlo a quien esté en la misma situación. Este mini tutorial no pretende explicar exhaustivamente como se construye un componente completo con instalador y todo (de eso ya hay muchos tutoriales), sino contar las cosas que el entorno (framework) de J! espera encontrar en su camino hacia la presentación de una página dada.

Se entra en el entorno de J! efectuando llamadas a index.php. Joomla! ha sido diseñado principalmente para entregar los datos devueltos por los componentes. Cuando introducimos una URL como index.php?option=com_<nombre> Joomla! busca la carpeta 'components/com_<nombre>' e intenta cargar el fichero 'nombre.php' de dondequiera que se haya instalado Joomla!. Así que, si tu componente es 'com_viajes' debieras tener una carpeta 'com_viajes' dentro del directorio 'components' y un fichero llamado 'viajes.php' en su interior. Voy a llamar a este fichero (viajes.php) el 'fichero base' y, será en el en donde tendremos que realizar nuestra primera decisión acerca de si devolver el contenido HTML deseado según el viejo modelo plano o ir hacia el nuevo modelo 'Model-View-Controller' o MVC.

El modelo MVC se apoya sobre dos patas: un fichero y una clase. El entorno de Joomla! usualmente buscará un fichero determinado y, dentro de el, esperará encontrar una clase que registrar. Si alguno de los dos falta la llamada fallará.

Ponemos en marcha el modelo MVC incluyendo el controlador en nuestro fichero base. El fichero del controlador puede llamarse como deseemos pero, por convenio, parece que suele llamarse 'controller.php'. Así que en nuestro fichero base (viajes.php), escribiríamos algo como esto:

Code:
require_once(JPATH_COMPONENT.DS.'controller.php');


Ahora, para ser coherente, hemos de crear un nuevo fichero y llamarlo 'controller.php'. Este fichero puede ser creado donde deseemos ya que lo vamos a incluir por ruta en el fichero base pero, si has usado la línea propuesta anteriormente debe ser creado en la misma carpeta donde se encuentra el fichero base ya que JPATH_COMPONENT contiene la ruta donde se encuentra nuestro componente y DS representa el separador de directorios correcto según el sistema operativo bajo el que se está ejecutando el código, sea este windows o linux.

Así que creamos 'controller.php' y realizamos una referencia dentro de éste a la librería del controlador importándola con:

Code:
jimport('joomla.application.component.controller');


Ya tenemos la primera pata (el fichero) por lo que ahora necesitamos la otra, la clase. Para ello tenemos que definir una clase que extienda la funcionalidad de la clase base del controlador 'JController'. En esta clase es en donde toda la acción va a transcurrir. Puedes llamar a la clase derivada como quieras pero parece ser que por acuerdo el nombre se deriva del nombre del componente así que nuestra clase será:

Code:
class ViajesController extends JController
{
}


En esta etapa ya tenemos nuestros dos primeros ficheros. El fichero base carga el controlador y el fichero del controlador define una clase que extiende la clase base. Hasta aquí fácil. Nuestro siguiente paso será crear un objeto de de esta clase y ponerlo a currar. Así que añadimos las siguientes líneas a nuestro fichero base:

Code:
// Incluir el fichero del controlador
require_once(JPATH_COMPONENT.DS.'controller.php'); // Esta ya estaba

// Crear el controlador
$controller = new ViajesController();  o el  nombre que le hayas dado a tu clase de controlador

// realizar la tarea solicitada
$controller->execute(JRequest::getCmd('task'));


A partir de ahora las cosas empiezan a ocurrir solitas. Hasta hora podíamos dar a nuestros ficheros (exceptuando el fichero base) el nombre que queríamos, podíamos ponerlos donde nos diera la gana y podíamos dar a nuestras clases el nombre que quisiéramos porque estábamos incluyendo los ficheros por ruta y estábamos llamando a las clases directamente (bueno, realmente sólo un fichero y sólo una clase pero teníamos la posibilidad de hacerlo). Pero a partir de ahora será el entorno de Joomla! el que empiece a cargar nuestros ficheros y a llamar a nuestras clases automáticamente por lo que debemos ser sumamente cuidadosos acerca de dónde ponemos nuestros archivos, cómo los llamamos y qué clases contienen porque una simple letra de diferencia y Joomla! fallará.

De dónde saca el entorno de Joomla! los datos para funcionar?. Bueno, la respuesta es sencilla: de la petición de página sea ésta una petición tipo GET o una petición tipo POST. Pero, yo no he escrito en mi petición nada más que option=com_viajes. De dónde viene el parámetro 'task' que pasamos en la llamada al controlador?. Realmente tenemos una variable 'task' con un valor correcto?

Si, y este el 'problema': Tanto si realizas como si no realizas una petición completa el entorno de Joomla! usará sus valores por defecto para completar la llamada haciendo el sistema muy cómodo pero también muy complejo de reparar si nos equivocamos en determinados sitios.

La llamada 'controller->execute()' hará que el entorno de Joomla! intente realizar el trabajo solicitado que, en este caso, será la tarea por defecto 'display', simplemente porque no le hemos indicado ninguna otra.

Code:
class ViajesController extends JController
{
   function display()
   {
      echo 'Viajando';
   }
}


De tal modo que si nuestra petición hubiese contenido el parámetro 'task=saltar' el controlador hubiese intentado ejecutar una función llamada saltar en nuestra clase controladora:

Code:
class ViajesController extends JController
{
   function saltar()
   {
      echo 'saltando';
   }
}


Si has sido observador el nombre de nuestro componente ha sido 'capitalizado' al usarlo como nombre de la clase derivada. Esta es una constante en el entorno y, aunque aquí hubiésemos podido poner otra cosa en esta primera clase no será así en las demás por lo que conviene acostumbrarse lo antes posible para evitar tirones de pelo.

Por el momento hemos jugado con la parte 'Controller' del modelo MVC. Llegamos aquí a un nuevo punto de decisión. Podemos parar aquí o seguir adelante y entrar en la parte 'View' del modelo.

Como se puede ver el modelo MVC puede ser usado por partes según lo que nos interese algo que no he visto que nadie diga en ningún sitio. Parar aquí, al menos, simplifica nuestro fichero base. Hasta ahora teníamos normalmente una sentencia switch que, según la tarea solicitada por una variable dada llamaba a una función escrita más abajo en ese mismo fichero y le pasaba varios argumentos. Esa función era la que devolvía el código HTML deseado.

Ahora el switch ha desaparecido y las diferentes tareas a realizar son funciones en nuestro fichero 'controller.php '. La capacidad de pasar argumentos ha desaparecido pero todas las variables necesarias están disponibles en el entorno así que las podemos recuperar fácilmente.

No hay nada que nos obligue a usar la variable 'task' para controlar el flujo de ejecución ya que podríamos parar cualquier otra variable en la llamada pero para ajustarnos a reglas no escritas (o no encontradas por mi) se suele usar 'task' ya que, además, el entorno la trata de manera especial porque es la escogida por los desarrolladores para realizar este trabajo, así que es buena idea usarla también nosotros.

Para disparar las vistas sólo tenemos que llamar a la función display() de la clase base JController. Hacemos esto insertanto en nuestra función una llamada a parent::display() como última línea. Así, como mínimo, nuestro fichero controller debiera contener lo siguiente:

Code:
jimport('joomla.application.component.controller');

class ViajesController extends JController
{
   function display()
   {
      parent::display();
   }
}


Pero, qué es una vista? Una vista es un subconjunto de datos. Es el mismo concepto de vista del lenguaje SQL. Presentamos diferentes partes de nuestros datos con diferentes vistas. Así que podemos tener una vista detallada y una vista resumida, esta última presentando un subconjunto de datos de los presentados en la primera.

Como podemos tener diferentes vistas en nuestro componente, Joomla! usa la carpeta 'views' dentro del directorio base del componente para mantener las cosas ordenadas. Esta carpeta es sólo un almacén para tus vistas.

Dentro de la carpeta 'views' tendrás que tener una carpeta por cada vista que desees. Qué hace el entorno de Joomla! con todo esto?. Pues intentar leer un fichero llamado 'view.html.php' que debiera existir en la carpeta de tu vista. Un poco lioso? A ver si me explico...

Cuando realizamos nuestra petición de página incluimos un parámetro llamado, adivinas?... Si, 'view' que contenía la vista dentro del modelo MVC que deseábamos obtener. O que debiste incluir ya que lo que se que no existe es algo así como una vista por defecto. Así que nuestro URL era algo como:

Code:
http://mi.sitio.com/index.php?option=com_viajes&view=<mivista>[&task=<mitarea>]


La parte correspondiente a la tarea puede obviarse. Recuerda que si no la incluimos la tarea por defecto es display. Con esta URL Joomla! va a buscar e importar un fichero localizado en la carpeta <raíz del sitio>/components/com_viajes/views/<mivista>/view.html.php. Si este fichero o la ruta no existen entonces Joomla! generará un error. Por el simple mecanismo de cambiar el nombre de la vista asociada a la variable 'view' podemos acceder a diferentes vistas casi sin esfuerzo. Genial, eh?

Cada petición de vista requiere también que especifiquemos el formato en el que vamos a servir los datos de la misma. Existen varios formatos bien conocidos como html (el formato por defecto si no especificamos ninguno), feed(rss), raw, etc, pero podemos usar formatos propios. Si no se especifica el formato en la URL mediante el parámetro 'format=<miformat>'el valor por defecto de 'html' es usado.

El formato 'html' hace que el entorno de Joomla! envuelva nuestra respuesta en la plantilla asignada a la página de tal forma que obtenemos una página HTML completa. De esta forma, con muy podo esfuerzo por nuestra parte, obtenemos como respuesta una página completamente cargada con la salida de los módulos y todo lo que hayamos configurado en ella además de nuestros datos en el centro de la misma como contenido.

El formato específico que estamos usando es lo que hemos puesto en el centro del nombre del archivo de la vista que hemos colocado en nuestra carpeta de vista (el fichero 'view.html.php'). Si usamos un formato diferente como 'raw' nuestro fichero debiera llamarse igualmente 'view.raw.php'.

Hay bastante más que decir sobre este tema pero para este primer post voy a dejarlo aquí que ya parece suficientes información.

Será la respuesta y el interés de los posibles lectores el que establecerá si hay segundas partes o este intento se queda en un simple experimento.

Un saludo a todos.


Top
  E-mail  
 
Posted: Wed Sep 03, 2008 3:14 am 
Joomla! Apprentice
Joomla! Apprentice
Offline

Joined: Sun Aug 03, 2008 5:09 pm
Posts: 18
Hola,

Muy interesante tu artículo. Quería preguntarte si sabías cómo hacer para modificar un método de uno de los componentes, en particular de com_menus.

Esto es porque deseo que ciertos menús solo puedan ser modificados por el Super Admin.


Gracias,

siranm


Top
  E-mail  
 
Posted: Fri Sep 05, 2008 12:20 pm 
Joomla! Apprentice
Joomla! Apprentice
Offline

Joined: Sun Apr 20, 2008 9:44 pm
Posts: 39
Buenas Siranm.

Lo que deseas hacer, independientemente de que no es trivial, representa una modificación del sistema base que luego va a ser difícil de mantener conforme salgan nuevas versiones de J! por lo que no te recomiendo que hagas ningún cambio.

Si aún así deseas cambiar el codigo base vas a tener que tocar en multitud de sitios ya que los items de menú se pueden copiar, mover, editar, etc. y vas a tener que validar la seguridad en cada uno de estos puntos. No es sólo modificar un método sino muchos en varios sitios diferentes (por ejemplo, en el listado de menús debieras deshabiliar la posibilidad de copiar, editar, etc. un menu si el usuario no tiene el nivel deseado. Pero eso mismo lo tienes que hacer en el resto de puntos de entrada por que si no se saltarán la seguridad que pongas usando directamente el url).

Según tengo entendido ya está en desarrollo un sistema completo de gestión de derechos mucho más avanzado que el que actualmente tiene la versión 1.5 que es posible que te permita hacer lo que deseas sin tener que tocar nada, pero no se cuando estará disponible.

Saludos.


Top
  E-mail  
 
Posted: Wed Sep 10, 2008 3:02 am 
Joomla! Apprentice
Joomla! Apprentice
Offline

Joined: Sun Aug 03, 2008 5:09 pm
Posts: 18
Hola,

Lo que quería es hacer una especie de "extensión" o similar, que me permitiera que un usuario no pueda borrar determinado elemento del menú. No me importa si lo copia luego, o si lo borra, etc... solo que mi entrada original sea imborrable.

Gracias por tus comentarios,

siran


Top
  E-mail  
 
Posted: Wed Nov 05, 2008 5:41 pm 
Joomla! Fledgling
Joomla! Fledgling
Offline

Joined: Thu Oct 30, 2008 9:53 pm
Posts: 2
Buen día!

Antes que nada te agradezco por haber incluido este mini tutorial, realmente es claro y útil. Mi problema es que no he logrado encontrar la forma de llamar desde mi controlador a un modelo diferente - del mismo componente -. Me explico un poco mas:

Estoy desarrollando un componente que almacene información en dos tablas diferentes, una de ellas se llama igual que el componente y en esta todo funciona ok con las siguientes líneas (generadas en un 80% por EasyCreator un componente excepcional para desarrollar rápidamente los primeros ficheros y comenzar a trabajar):

class challengeController extends JController
{
function display()
{
parent::display();
}// function

...
function saveChallengeData()
{
$game_id = JRequest::getInt('game_id');
$ammount = JRequest::getFloat('ammount');
$rules = JRequest::getString('rules');

$model =& $this->getModel('challenge');
$row =& $model->getTable();

$auxArray = array();
$auxArray['game_id']=$game_id;
$auxArray['ammount']=$ammount;
$auxArray['rules']=$rules;

if(!$row->bind($auxArray,'id')){//not to bind the primary key
$msg = JText::_($row->getError());
}

if(!$row->store()){
$msg = JText::_($row->getError());
}

$this->saveRelation();//we need to pass an id here

//don't change below this line
$msg = JText::_( 'Challenge Creation Success' );
$this->setRedirect( 'index.php?option=com_juego', $msg );
}

Pero a partir de este punto no he logrado dar con el chiste, me refiero a que tengo la siguiente funcion en este mismo archivo (controller.php):

function saveRelation(){ //Just a Test
global $option;

$row =& JTable::getInstance('TableRelation');
print_r($row);

die('grande Dolina!');
}

y nunca obtengo nada diferente al parámetro del Die. Lo intenté antes con el getModel pero el resultado era exactamente el mismo. No se si me he explicado o quedé peor que antes, pero cualquier sugerencia que puedan darme para llamar desde un controlador varios modelos y acceder a sus métodos me haría inmensamente feliz.

Happy hacking, (JAMS)


Top
  E-mail  
 
Posted: Wed Nov 05, 2008 8:24 pm 
Joomla! Fledgling
Joomla! Fledgling
Offline

Joined: Thu Oct 30, 2008 9:53 pm
Posts: 2
Era mi error, lo siento. Después de muchas horas invertidas encontré que a pesar de haber creado la clase para el segundo modelo y su tabla me había olvidado de incluir el nombre (y la ruta) del archivo donde se define la clase del modelo y la clase de la tabla en el archivo .xml


Top
  E-mail  
 
Posted: Sat Mar 07, 2009 10:15 am 
User avatar
Joomla! Apprentice
Joomla! Apprentice
Offline

Joined: Mon Mar 06, 2006 10:26 pm
Posts: 22
Location: Rosario
Gracias amigo, muy buena explicacion, la misma esta en ingles y realmente tendria que haber una seccion development en español

http://docs.joomla.org/How_Joomla_pieces_work_together


Top
   
 
Posted: Mon Apr 20, 2009 11:48 am 
Joomla! Fledgling
Joomla! Fledgling
Offline

Joined: Mon Apr 20, 2009 11:43 am
Posts: 1
Gracias por el tutorial!!!!!

Una pregunta, por si alguien ha dado con el caso:

Estoy construyendo una web con Joomla! y uno de los componentes tiene que generar una salida xml, en vez de html, que será llamado exteriormente (no existe ningún menú que lo direccione dentro de nuestro sitio). He visto en el tutorial que se cambian ciertas extensiones en los archivos, pero ¿cómo soy capaz de que el código de salida sea sólo xml (el xml que creo se me "mete" dentro del html de la plantilla y aparece como texto en la página)?

Muchas gracias por adelantado!!!


Top
  E-mail  
 
Posted: Mon Apr 20, 2009 1:47 pm 
Joomla! Apprentice
Joomla! Apprentice
Offline

Joined: Sun Apr 20, 2008 9:44 pm
Posts: 39
Buenas agudelgado.

El framework de joomla integra nuestra respuesta (lo que generamos en nuestra vista por ejemplo, o en el controlador si no llegamos a tener vistas, o directamente si no usamos el modelo MVC) con la plantilla definida para el sitio si el formato de la solicitud es uno de los reconocidos (html, rss, etc) o no se usa el modelo MVC.

En caso contrario devuelve sólo lo que nosostros enviamos, como por ejemplo en las solicitudes ajax (si respondemos con una estructura JSON sería muy malo que el framework lo encapsulara en una página html completa). Siguiendo este mismo modelo debieramos poder recibir sólo el texto xml si el formato solicitado es raw (un formato predefinido del entorno Joomla! con el que podemos evitar la fusión con la plantilla. Joomla! no fusionará la respuesta con la plantilla si usamos este formato) y, en general, uno de los no reconocidos. Su llamada debiera definir un formato explícitamente porque en caso contrario el formato html será el considerado por defecto y el sistema nos envolverá la respuesta en la plantilla definida.

No se el formato que esta usando en la URL de llamada pero para conseguir este efecto hay que incluir explicitamente el parámetro 'format=' (format=xml sería adecuado por ejemplo si no deseamos usar raw) en la petición. De esta forma Joomla! Intentaría incluir un fichero miVista.xml.php y no debiera envolver la respuesta en la plantilla obteniendose el código xml exclusivamente.

No he verificado en vivo lo comentado en esta respuesta sino que me atengo a la teoría del modelo del entorno de Joomla! por lo que me interesa conocer cómo ha resultado la prueba en caso de que la realice.

Un cordial saludo.


Top
  E-mail  
 
Posted: Mon Apr 20, 2009 2:01 pm 
Joomla! Apprentice
Joomla! Apprentice
Offline

Joined: Sun Apr 20, 2008 9:44 pm
Posts: 39
allado wrote:
Gracias amigo, muy buena explicacion, la misma esta en ingles y realmente tendria que haber una seccion development en español

http://docs.joomla.org/How_Joomla_pieces_work_together


De hecho ese documento también lo escribí yo antes de darme cuenta que existía un foro exclusivo en español. El escrito inicial fue enviado al foro correspondiente sólamente asi que no puedo imaginarme cómo ha acabado en la sección de documentación 'oficial' del sitio de Joomla! ya que a mi nadie me ha solicitado autorización para ello ni me ha informado de haberlo hecho, por eso no sabía de su existencia hasta leer este mensaje.

En cualquier caso entiendo que al remitirlo a los foros se convierte en un documento público así que no estoy expresando ninguna queja.

Ambos documentos debieran estar 'sincronizados' ya que el que está en inglés es la traducción más o menos exacta del que redacté en castellano así que en este caso el foro en español no está en desventaja con respecto de la página 'oficial'.


Top
  E-mail  
 
Posted: Thu Jun 04, 2009 3:12 am 
Joomla! Apprentice
Joomla! Apprentice
Offline

Joined: Sat May 19, 2007 11:33 am
Posts: 12
Location: Madrid
Buenísimo, jejeje

Por fin he encontrado un buen tutorial en español de cómo funciona Joomla! :P

Para cuándo la 2º parte? ^_^

Saludos!

_________________
JoniJnm.es


Top
   
 
Posted: Thu Jun 04, 2009 8:12 am 
Joomla! Apprentice
Joomla! Apprentice
Offline

Joined: Sun Apr 20, 2008 9:44 pm
Posts: 39
No es que sea una segunda parte sino más bien completar la primera pero si alguien se ha quedado con ganas de más chicha este miniTuto se completa en este otro tópico viewtopic.php?f=93&t=394077.

Quería incorporarlo en este hilo pero me equivoqué de botón y no me di cuenta de ello hasta que era tarde. Desgraciadamente mis peticiones a los moderadores para que fusionaran ambos hilos no tuvieron ningún éxito así que siguen cada uno por su lado. Puede que así sea mejor, no se.


Top
  E-mail  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 12 posts ] 

Quick reply

 



Who is online

Users browsing this forum: No registered users and 5 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group