<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Mundo Geek &#187; desarollo</title>
	<atom:link href="http://mundogeek.net/etiqueta/desarollo/feed/" rel="self" type="application/rss+xml" />
	<link>http://mundogeek.net</link>
	<description>Mundo geek, bitácora sobre todo lo geek: software, gadgets, tecnología, internet, ...</description>
	<lastBuildDate>Wed, 08 Feb 2012 16:09:25 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Documentación</title>
		<link>http://mundogeek.net/archivos/2011/01/30/documentacion/</link>
		<comments>http://mundogeek.net/archivos/2011/01/30/documentacion/#comments</comments>
		<pubDate>Sun, 30 Jan 2011 15:44:47 +0000</pubDate>
		<dc:creator>Zootropo</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[citas]]></category>
		<category><![CDATA[desarollo]]></category>
		<category><![CDATA[documentacion]]></category>
		<category><![CDATA[programacion]]></category>

		<guid isPermaLink="false">http://mundogeek.net/?p=6343</guid>
		<description><![CDATA[A menudo, la documentación del software consiste en grandes, pesados y amenazadores manuales que nadie nunca lee. De hecho, durante los últimos cinco años, la mayoría de los manuales que venían con productos software han sido en realidad copias de &#8220;La danza de la muerte&#8221; de Stephen King, con nuevas tapas pegadas. &#8211; Dave Barry]]></description>
			<content:encoded><![CDATA[<blockquote><p>A menudo, la documentación del software consiste en grandes, pesados y amenazadores manuales que nadie nunca lee. De hecho, durante los últimos cinco años, la mayoría de los manuales que venían con productos software han sido en realidad copias de &#8220;La danza de la muerte&#8221; de Stephen King, con nuevas tapas pegadas.</p>
<p>&#8211; Dave Barry</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://mundogeek.net/archivos/2011/01/30/documentacion/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Creación de componentes para Joomla</title>
		<link>http://mundogeek.net/archivos/2010/02/12/creacion-de-componentes-para-joomla/</link>
		<comments>http://mundogeek.net/archivos/2010/02/12/creacion-de-componentes-para-joomla/#comments</comments>
		<pubDate>Fri, 12 Feb 2010 09:50:30 +0000</pubDate>
		<dc:creator>Zootropo</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[componentes]]></category>
		<category><![CDATA[desarollo]]></category>
		<category><![CDATA[extensiones]]></category>
		<category><![CDATA[joomla]]></category>
		<category><![CDATA[programacion]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://mundogeek.net/?p=4936</guid>
		<description><![CDATA[Siguiendo con nuestra serie de tutoriales sobre Joomla, esta vez hablaremos sobre el desarrollo de componentes, otro de los tipos de extensiones disponibles para este CMS, junto con los plugins, los temas, las traducciones o los módulos. Componentes en Joomla Los componentes son extensiones más complejas que los módulos, y suelen contar con una parte [...]]]></description>
			<content:encoded><![CDATA[<p>Siguiendo con nuestra serie de <a href="http://mundogeek.net/etiqueta/joomla+tutorial/" title="Tutoriales sobre Joomla">tutoriales sobre Joomla</a>, esta vez hablaremos sobre el desarrollo de componentes, otro de los tipos de extensiones disponibles para este CMS, junto con los plugins, los temas, las traducciones o los <a href="http://mundogeek.net/archivos/2010/01/14/creacion-de-modulos-en-joomla/" title="Creación de módulos para Joomla">módulos</a>.<span id="more-4936"></span></p>
<h2>Componentes en Joomla</h2>
<p>Los componentes son extensiones más complejas que los módulos, y suelen contar con una parte pública o frontend y otra de administración o backend.</p>
<p>Sólo puede haber un componente activo por página, y este se determina mediante un argumento <code>option</code> en la petición HTTP, que contendrá el nombre del componente a cargar. Para un componente con nombre <code>com_componente</code>, por ejemplo, la URL para ejecutar el backend sería http://servidor.com/administrator/index.php?option=com_componente y la del frontend, http://servidor.com/index.php?option=com_componente.</p>
<p>Cuando Joomla! se encuentra con una URL de este tipo, con un parámetro <code>option</code> indicando el nombre de un cierto componente, el engine busca y ejecuta el archivo components/com_<em>nombre</em>/<em>nombre</em>.php si se trata del frontend y administrator/components/com_<em>nombre</em>/<em>nombre</em>.php si vamos a cargar el backend.</p>
<p>Aunque podríamos escribir todo el código del componente en estos dos archivos, es conveniente que nuestro código esté algo más estructurado.</p>
<p>De un tiempo a esta parte, afortunadamente, se está tendiendo a utilizar el patrón MVC a la hora de crear componentes para Joomla, por lo que el contenido de estos dos archivos suele consistir simplemente en la instanciación y ejecución de un controlador.</p>
<h3>El patrón MVC en los componentes Joomla</h3>
<p>¿Que qué es un controlador, o el patrón MVC, ya que estamos? MVC es un viejo conocido de los desarrolladores web que propone usar una arquitectura dividida en 3 capas diferenciadas, en pos de reducir el acoplamiento. Estas capas, cuyas siglas dan nombre al patrón son:</p>
<ul>
<li>Modelo: los datos que maneja la aplicación y las reglas de negocio que operan sobre ellos</li>
<li>Vista: genera la interfaz con la que la aplicación interacciona con el usuario</li>
<li>Controlador: comunica la vista y el modelo respondiendo a eventos generados por el usuario en la vista, invocando cambios en el modelo, y proporcionando a la vista la información del modelo necesaria para que pueda generar la respuesta adecuada para el usuario</li>
</ul>
<p>El patrón MVC se implementa en Joomla utilizando 3 clases distintas, una por cada componente del patrón: <code>JModel</code> para el modelo, <code>JView</code> para la vista y <code>JController</code> para el controlador.</p>
<p>Un controlador en Joomla es una clase que extiende <code>JController</code>, con un método para cada tarea con la que el controlador tenga que tratar: mostrar un elemento, crear un elemento, borrar un elemento, etc. En estos métodos el controlador analiza la entrada del usuario y lleva a cabo los pasos necesarios para generar la respuesta (seleccionar el modelo o modelos necesarios y la vista a utilizar y asociarlos, hacer una redirección, generar un error&#8230;)</p>
<p>Un modelo en Joomla es una clase que extiende <code>JModel</code>, con distintos métodos para realizar distintas acciones sobre los datos. No importa la forma que tomen estos datos o la forma en la que trabajemos con ellos: podríamos utilizar <code>JTable</code>, <code>JDatabase</code>, mysqli, las funciones para trabajar con ficheros&#8230;</p>
<p>Una vista en Joomla es una clase que extiende <code>JView</code>, con uno o más métodos para generarar la página HTML, el feed, el PDF, &#8230; que mostrar al usuario como respuesta. Cuando la respuesta es una página HTML, la vista suele hacer uso de plantillas.</p>
<h3>Punto de entrada al componente</h3>
<p>Ahora que ya hemos establecido en qué consiste el patrón MVC, veamos el aspecto que tendrá el archivo que actúa a modo de punto de entrada al componente, y que, como dijimos anteriormente, se ejecuta al cargar la URL http://servidor.com/index.php?option=com_nombre (vamos a centrarnos en este artículo en el frontend)</p>
<p>Recordaréis que este archivo debía instanciar el controlador y ejecutarlo. Eso es lo que hace este fragmento de código:</p>
<pre name="code" class="php">&lt;?php
defined('_JEXEC') or die('Restricted access');

$controller = JRequest::getWord('controller', 'default');
$path = JPATH_COMPONENT.DS.'controllers'.DS.$controller.'.php';

if(file_exists($path)) {
  require_once($path);
  $classname = 'EjemploController'.$controller;
  $controller = new $classname();

  $controller-&gt;execute($task);
  $controller-&gt;redirect();
}</pre>
<p>Es una práctica común el utilizar un controlador por cada tipo de entidad con el que vayamos a trabajar, y utilizar el parámetro <code>controller</code> para indicar el controlador a usar; ese es el motivo de que usemos <code>JRequest</code> para obtener su valor. En caso de que no se haya encontrado ningún parámetro <code>controller</code> en la petición, la variable <code>$controller</code> obtendrá como valor &#8216;<code>default</code>&#8216;.</p>
<p>Una vez sabemos qué controlador cargar (uno especificado en la URL, o <code>default</code>) comprobaremos si realmente existe un archivo PHP con ese nombre en la carpeta controllers de nuestro componente.</p>
<p>Si es el caso, cargaremos el código del componente, instanciaremos la clase, llamaremos a su método <code>execute</code> pasándole como argumento el valor del parámetro <code>task</code> de la URL (que se guarda automáticamente en <code>$task</code>), y llamaremos a su método <code>redirect</code>.</p>
<p>El método <code>execute</code> del controlador es el encargado de llamar a uno u otro de los métodos del controlador para tratar la petición. Normalmente se ejecutará el método que tenga el nombre pasado como parámetro a <code>execute</code>, aunque se puede modificar el mapeo utilizando el método <code>registerTask()</code> (por ejemplo para que el mismo método se encargue de la tarea de editar y crear un nuevo elemento). Si la URL no tiene ningún parámetro <code>task</code>, y por lo tanto se le pasa una cadena vacía a <code>execute</code>, o si el valor no se encuentra en el mapeo, se ejecutará por defecto el método de nombre <code>display</code>.</p>
<p>El método <code>redirect</code> sirve para redirigir el navegador en caso de que en el método ejecutado en el controlador se estableciera una redirección (mediante el método <code>setRedirect</code>).</p>
<h3>Controlador</h3>
<p>Un controlador muy sencillo, que no hace más que ejecutar la vista asociada podría tener este aspecto:</p>
<pre name="code" class="php">&lt;?php
defined('_JEXEC') or die('Restricted access');

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

class EjemploController extends JController {
  function display() {
    parent::display();
  }
}</pre>
<p>De hecho, como nuestro método <code>display</code>, que, como ya hemos comentado, es el que se ejecuta si no se pasa ningún argumento a <code>execute</code> en el punto de entrada, sólo llama al método <code>display</code> del objeto padre, no tendríamos si quiera por qué sobre escribirlo:</p>
<pre name="code" class="php">&lt;?php
defined('_JEXEC') or die('Restricted access');

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

class EjemploController extends JController {}</pre>
<p>Pero normalmente nuestros controladores no serán tan sencillos. Lo más habitual es encontrarse con 2 tipos de métodos: aquellos en los que sólo queremos mostrar una cierta información al usuario, y otros en los que realizaremos una acción sobre el modelo, y redirigiremos el navegador a otra URL para mostrar el resultado.</p>
<p>En el primer caso sólo tenemos que establecer la vista y la plantilla a utilizar, y ejecutarla.</p>
<pre name="code" class="php">function display() {
  JRequest::setVar('view', 'persona');
  JRequest::setVar('layout', 'default');

  parent::display();
}</pre>
<p>o bien</p>
<pre name="code" class="php">function display() {
  JRequest::setVar('view', 'persona');

  parent::display('default');
}</pre>
<p>dado que default es la plantilla que se carga por defecto, si sólo vamos a usar una plantilla, o bien, si vamos a utilizar la plantilla default, no será necesario indicarlo</p>
<pre name="code" class="php">function display() {
  JRequest::setVar('view', 'persona');

  parent::display();
}</pre>
<p>En el segundo caso tendríamos algo así</p>
<pre name="code" class="php">function guardar() {
  $modelo = $this-&gt;getModel('persona');
  if($modelo-&gt;guardarPersona())
    $this-&gt;setRedirect('index.php?option=com_nombre', 'Persona guardada con exito');
  else
    $this-&gt;setRedirect('index.php?option=com_nombre', 'Error al guardar', 'error');
}</pre>
<h3>Vista</h3>
<p>Como dijimos, las vistas consisten en clases que extienden <code>JView</code>. En estas clases nos interesará sobreescribir el método <code>display</code>, donde asignaremos las variables que la plantilla pueda necesitar con <code>assign</code> o <code>assignRef</code> (el primero asigna una copia del dato y el segundo una referencia) y llamaremos al método <code>display</code> de la clase padre para que renderice la plantilla.</p>
<pre name="code" class="php">class EjemploViewDefault extends JView {
  function display($tpl=null) {
    $this-&gt;assignRef('mensaje', 'Hola mundo');

    parent::display($tpl);
  }
}</pre>
<p>Para obtener datos del modelo en la vista se puede hacer lo siguiente</p>
<pre name="code" class="php">class EjemploViewDefault extends JView {
  function display($tpl=null) {
    $modelo =&#038; $this-&gt;getModel('MiModelo');
    $mensaje = $modelo-&gt;getMensaje();
    $this-&gt;assignRef('mensaje', $mensaje);

    parent::display($tpl);
  }
}</pre>
<p>Si el modelo tiene el mismo nombre que la vista, lo cuál suele ser habitual, porque es práctica común usar una vista y un modelo por entidad, de la misma forma que hacíamos con los controladores, el modelo estará asociado automaticamente con la vista, y bastará con hacer algo así:</p>
<pre name="code" class="php">class EjemploViewDefault extends JView {
  function display($tpl=null) {
    $mensaje =&#038; $this-&gt;get('Mensaje');
    $this-&gt;assignRef('mensaje', $mensaje);

    parent::display($tpl);
  }
}</pre>
<p>Al llamar al método <code>get</code> la vista buscará en el modelo asociado un método con nombre <code>get</code> seguido de la cadena pasada como parámetro (<code>getMensaje</code> en el ejemplo) y lo ejecutará.</p>
<p>Por último, como dijimos, si vamos a usar la plantilla por defecto, default.php, no necesitaremos pasar a <code>display</code> ningún parámetro:</p>
<pre name="code" class="php">class EjemploViewDefault extends JView {
  function display($tpl=null) {
    $mensaje =&#038; $this-&gt;get('Mensaje');
    $this-&gt;assignRef('mensaje', $mensaje);

    parent::display();
  }
}</pre>
<p>Las plantillas son archivos PHP en los que casi todo es HTML, y se usan pequeños snipets PHP para imprimir los valores necesarios en las posiciones adecuadas. Se podría crear el código HTML de la respuesta en la clase de la vista utilizando <code>echo</code>, por ejemplo, pero el uso de plantillas facilitará la vida a los diseñadores, o, si no hay diseñadores, a nosotros, cuando tengamos que reutilizar código o mantener el componente.</p>
<p>En la plantilla se accede a los datos que se han asignado con <code>assign</code> y <code>assignRef</code> usando <code>$this-&gt;dato</code></p>
<pre name="code" class="php">&lt;h1&gt;&lt;?php echo $this-&gt;dato; ?&gt;&lt;/h1&gt;</pre>
<p>En la plantilla también se puede usar <code>$this-&gt;loadTemplate('plantilla');</code> para cargar otra plantilla y tener así un diseño más modular. En el siguiente código se cargaría una plantilla default_cabecera.php, por ejemplo:</p>
<pre name="code" class="php">&lt;?php $this-&gt;loadTemplate('cabecera'); ?&lt;

&lt;h1&gt;&lt;?php echo $this-&gt;dato; ?&gt;&lt;/h1&gt;</pre>
<h3>Modelo</h3>
<p>Por último tenemos el modelo. Estas son las clases más sencillas. Basta extender <code>JModel</code> y crear tantos métodos como queramos, que realizarán las operaciones sobre los datos que necesitemos. Un ejemplo podría ser</p>
<pre name="code" class="php">&lt;?php
defined('_JEXEC') or die('Restricted access');
jimport('joomla.application.component.model');

class ModelEjemplo extends JModel {
  function getMensaje() {
    $db =&#038; JFactory::getDBO();
    $query = 'SELECT mensaje FROM #__mensajes ORDER BY RAND() LIMIT 1';
    $db-&gt;setQuery($query);
    return $db-&gt;loadResult();
  }
}</pre>
<h2>Crear un componente de ejemplo</h2>
<p>Para continuar, vamos a crear un pequeño componente de ejemplo, basado en el típico hola mundo, que mostrará un mensaje aleatorio de entre los almacenados en una tabla de la base de datos.</p>
<p>Lo primero que tenemos que hacer es crear una carpeta en nuestra máquina, com_ejemplo, digamos, en la que almacenaremos los archivos de nuestro nuevo componente. Dentro de esta carpeta crearemos un archivo ejemplo.xml con la información del componente e información de la instalación (puede tener un nombre cualquiera, pero lo habitual es utilizar el nombre del componente, o install.xml):</p>
<pre name="code" class="xml">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;install type="component" version="1.5"&gt;
  &lt;name&gt;Ejemplo&lt;/name&gt;
  &lt;author&gt;Raul Gonzalez&lt;/author&gt;
  &lt;creationDate&gt;Febrero 2010&lt;/creationDate&gt;
  &lt;copyright&gt;(C) Raul Gonzalez&lt;/copyright&gt;
  &lt;license&gt;GPL&lt;/license&gt;
  &lt;authorUrl&gt;http://mundogeek.net/&lt;/authorUrl&gt;
  &lt;authorEmail&gt;zootropo en gmail&lt;/authorEmail&gt;
  &lt;version&gt;0.1&lt;/version&gt;
  &lt;description&gt;Componente de ejemplo que muestra mensajes aleatorios escritos por los lectores&lt;/description&gt;
  &lt;install&gt;
    &lt;queries&gt;
      &lt;query&gt;CREATE TABLE IF NOT EXISTS jos_mensajes(
              id int NOT NULL auto_increment,
              mensaje varchar(300) NOT NULL, PRIMARY KEY(id));&lt;/query&gt;
      &lt;query&gt;INSERT INTO jos_mensajes(mensaje) VALUES
              ('At your command'),
              ('Hay 10 tipos de personas en el mundo: los que entienden binario y los que no'),
              ('Es mio, solo mio. Miii.... tessssssooooroo'),
              ('Hasta luego, y gracias por el pescado');&lt;/query&gt;
    &lt;/queries&gt;
  &lt;/install&gt;
  &lt;files&gt;
    &lt;file&gt;ejemplo.php&lt;/file&gt;
    &lt;file&gt;ejemplo.xml&lt;/file&gt;
    &lt;folder&gt;controllers&lt;/folder&gt;
    &lt;folder&gt;models&lt;/folder&gt;
    &lt;folder&gt;views&lt;/folder&gt;
  &lt;/files&gt;
  &lt;administration/&gt;
&lt;/install&gt;</pre>
<p>como véis no es muy distinto del archivo de instalación que utilizamos <a href="http://mundogeek.net/archivos/2010/01/14/creacion-de-modulos-en-joomla/" title="Creación de módulos en Joomla">al crear nuestro primer módulo</a>, a excepción de la sección <code>administration</code>, que en este ejemplo está vacía, pero normalmente listará los archivos de la parte de administración, y la sección <code>install</code>, que utilizamos en este caso para crear la tabla que usaremos para almacenar los mensajes, e introducir algunos mensajes iniciales.</p>
<p>El siguiente paso es crear el archivo que sirve de punto de entrada al componente, que, como ya comentamos, tendrá como nombre el mismo del componente sin el com_; es decir, en este caso, ejemplo.php. El contenido del mismo ya lo explicamos anteriormente:</p>
<pre name="code" class="php">&lt;?php
defined('_JEXEC') or die('Restricted access');

$controller = JRequest::getWord('controller', 'mensaje');
$path = JPATH_COMPONENT.DS.'controllers'.DS.$controller.'.php';

if(file_exists($path)) {
  require_once($path);
  $classname = 'EjemploController'.$controller;
  $controller = new $classname();

  $controller-&gt;execute($task);
  $controller-&gt;redirect();
}</pre>
<p>En este ejemplo, que es tan sencillo, no tiene mucho sentido tener más de un controlador, pero utilizaremos este código igualmente para que nuestro componente sea más fácil de extender y para que el ejemplo sea más instructivo.</p>
<p>Ahora tenemos que crear una carpeta controllers (fíjate en el valor de <code>$path</code> en el código anterior) en la que crearemos el archivo de nuestro controlador por defecto, que en este caso, como habréis supuesto por el segundo argumento de <code>JRequest::getWord</code>, será mensaje.php. Como dijimos, es habitual utilizar un controlador por entidad con la que vayamos a tratar, y el nombre del archivo suele ser el de la entidad. El nombre de la clase suele ser el nombre del componente, seguido de &#8216;<code>Controller</code>&#8216; y el nombre de la entidad (<code>EjemploControllerMensaje</code> en este caso).</p>
<p>En este ejemplo sólo necesitamos un método <code>display</code> (mostrar), que, como comentamos, es el que se ejecuta por defecto de no pasarse ningún otro valor al método <code>execute</code>.</p>
<pre name="code" class="php">&lt;?php
defined('_JEXEC') or die('Restricted access');

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

class EjemploControllerMensaje extends JController {
  function display() {
    JRequest::setVar('view', 'mensaje');
    parent::display();
  }
}</pre>
<p>Listo. Con algo tan simple ya tenemos nuestro primer controlador. Vayamos con la vista.</p>
<p>Creamos una carpeta views en el directorio del componente. En esta carpeta, para cada vista que vayamos a utilizar tendremos un directorio con el nombre de la vista, que contendrá a su vez un archivo view.html.php si vamos a generar una página HTML, view.feed.php si vamos a generar un feed, view.pdf.php si la salida será un PDF, o view.raw.php para cualquier otra cosa (el CMS sabe qué tipo de salida se debe mostrar al usuario gracias al parámetro <code>format</code> de la URL).</p>
<p>En nuestro ejemplo utilizaremos una vista para la única entidad con la que vamos a trabajar, aunque hay personas que prefieren tener una vista por cada página que vayamos a utilizar en el componente.</p>
<p>Crearemos, por lo tanto, una carpeta &#8216;mensaje&#8217; en views, y un archivo view.html.php en mensaje. El archivo view.html.php contendrá, como dijimos, una clase que extiende <code>JView</code>, y cuyo nombre estará compuesto por el nombre del componente, la palabra <code>View</code>, y el nombre de la vista (el nombre de la entidad). Como vamos a seguir las convenciones de nombres habituales, la vista tendrá asociado el modelo correspondiente, y sólo tenemos que llamar a <code>$this-&gt;get('Mensaje')</code> para que se busque y ejecute el método <code>getMensaje</code> en el modelo, y obtener de esta forma el mensaje a mostrar. Una vez hecho esto basta asignar este valor para que esté disponible para la plantilla.</p>
<pre name="code" class="php">&lt;?php
defined('_JEXEC') or die('Restricted access');

jimport('joomla.application.component.view');

class EjemploViewMensaje extends JView {
  function display($tpl=null) {
    $mensaje =&#038; $this-&gt;get('Mensaje');
    $this-&gt;assign('mensaje', $mensaje);

    parent::display();
  }
}</pre>
<p>Sigamos con la plantilla. En el mismo directorio en que se encuentra view.html.php crearemos una nueva carpeta tmpl para contener las plantillas o templates. Como sólo necesitaremos una plantilla, vamos a llamar a este archivo default.php, que es la plantilla que se carga por defecto de no indicarse otra cosa. Este archivo sólo tiene que hacer una cosa, y es mostrar el mensaje que se ha asignado en la clase de la vista.</p>
<pre name="code" class="php">&lt;h1 style="text-align:center;"&gt;&lt;?php echo $this-&gt;mensaje; ?&gt;&lt;/h1&gt;</pre>
<p>Por último veamos el modelo. Crearemos una nueva carpeta models en el directorio del componente, con un archivo mensaje.php que contendrá una clase cuyo nombre estará formado por el nombre del componente, la palabra &#8216;<code>Model</code>&#8216; y el nombre de la entidad. En este ejemplo sólo utilizamos un método <code>getMensaje</code> para obtener un mensaje aleatorio de la base de datos.</p>
<pre name="code" class="php">&lt;?php
defined('_JEXEC') or die('Restricted access');
jimport('joomla.application.component.model');

class EjemploModelMensaje extends JModel {
  function getMensaje() {
    $db =&#038; JFactory::getDBO();
    $query = 'SELECT mensaje FROM #__mensajes ORDER BY RAND() LIMIT 1';
    $db-&gt;setQuery($query);
    return $db-&gt;loadResult();
  }
}</pre>
<p>Con esto ya tendríamos preparado nuestro componente. Sólo resta comprimir los archivos que lo componen e instalarlo desde Extensiones -&gt; Instalar/Desinstalar. Para ver el resultado, tendremos que introducir en el navegador la URL http://servidor.com/index.php?option=com_ejemplo</p>
<h3>Complicando el componente</h3>
<p>Como puede que el ejemplo anterior os haya sabido a poco, vamos a añadir también la posibilidad de que los usuarios puedan introducir sus propios mensajes, para afianzar conceptos.</p>
<p>Lo primero que tenemos que hacer es editar el controlador, y crear un par de nuevos métodos que traten las nuevas tareas &#8216;<code>anyadir</code>&#8216;, que mostará un formulario con el que introducir el mensaje, y &#8216;<code>anyadido</code>&#8216;, que intentará guardar el mensaje y mostrará un texto u otro dependiendo del resultado.</p>
<pre name="code" class="php">&lt;?php
defined('_JEXEC') or die('Restricted access');

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

class EjemploControllerMensaje extends JController {
  function display() {
    JRequest::setVar('view', 'mensaje');
    parent::display();
  }

  function anyadir() {
    $vista = $this-&gt;getView('mensaje', 'html');

    $vista-&gt;anyadir('anyadir');
  }

  function anyadido() {
    $mensaje = JRequest::getVar('mensaje');
    $modelo = $this-&gt;getModel('mensaje');

    if($modelo-&gt;anyadirMensaje($mensaje))
      $this-&gt;setRedirect('index.php?option=com_ejemplo', 'Mensaje a&ntilde;adido con &eacute;xito');
    else
      $this-&gt;setRedirect('index.php?option=com_ejemplo', 'Se produjo un error al guardar el mensaje', 'error');
  }
}</pre>
<p>Lo único destacable respecto de la versión anterior es que ahora necesitamos obtener una instancia de la vista, con el método <code>getView(<em>vista</em>, <em>formato</em>)</code> del controlador, para poder ejecutar un método distinto de <code>display</code> en la vista. Otra alternativa habría sido tener una vista distinta por página.</p>
<p>Un apunte interesante es que con <code>JRequest::get('post')</code> podemos obtener todos los datos de una petición POST, de forma que podríamos haber hecho algo así para guardar todos los datos de un formulario en la base de datos usando <code>JTable</code>:</p>
<pre name="code" class="php">$persona =&#038; JTable::getInstance('persona', 'Table');
if ($persona-&gt;save(JRequest::get('post'))
  $mensaje = 'Guardado';
else
  $mensaje = 'Error: ', $empleado-&gt;getError();  

$this-&gt;setRedirect('index.php?option=com_componente', $mensaje);</pre>
<p>La nueva versión de la vista, con el nuevo método <code>anyadir</code>, tendrá el siguiente aspecto:</p>
<pre name="code" class="php">&lt;?php
defined('_JEXEC') or die('Restricted access');

jimport('joomla.application.component.view');

class EjemploViewMensaje extends JView {
  function display($tpl=null) {
    $mensaje =&#038; $this-&gt;get('Mensaje');
    $this-&gt;assign('mensaje', $mensaje);

    parent::display();
  }

  function anyadir($tpl) {
    parent::display($tpl);
  }
}</pre>
<p>Como vemos lo único que hace es mostrar la plantilla que indicó el controlador como parámetro. En este caso no necesitamos ningún dato del modelo, por lo que no se utiliza <code>assign</code> ni <code>assignRef</code>.</p>
<p>La nueva plantilla, default_anyadir.php, también es muy sencilla. Sólo muestra el formulario que el usuario utilizará para añadir el mensaje.</p>
<pre name="code" class="php">&lt;form action="index.php" method="post"&gt;
  &lt;input type="text" id="mensaje" name="mensaje"/&gt;

  &lt;input type="hidden" name="option" value="com_ejemplo" /&gt;
  &lt;input type="hidden" name="task" value="anyadido" /&gt;

  &lt;input type="submit" value="Registrar mensaje"/&gt;
&lt;/form&gt;</pre>
<p>Fíjate en que hacemos uso de un par de campos ocultos para establecer el valor del parámetro <code>option</code> y el parámetro <code>task</code>, y que la petición va a ser tratada, como siempre, por index.php</p>
<p>Por último sólo nos queda ver la nueva versión del modelo, con el método <code>anyadirMensaje</code> que guardará el mensaje introducido por el usuario</p>
<pre name="code" class="php">&lt;?php
defined('_JEXEC') or die('Restricted access');
jimport('joomla.application.component.model');

class EjemploModelMensaje extends JModel {
  function getMensaje() {
    $db =&#038; JFactory::getDBO();
    $query = 'SELECT mensaje FROM #__mensajes ORDER BY RAND() LIMIT 1';
    $db-&gt;setQuery($query);
    return $db-&gt;loadResult();
  }

  function anyadirMensaje($mensaje) {
    $db =&#038; JFactory::getDBO();
    $query = "INSERT INTO #__mensajes(mensaje) VALUES('{$mensaje}')";
    $db-&gt;setQuery($query);
    $db-&gt;query();

    if ($db-&gt;getErrorNum())
      return false;

      return true;
  }
}</pre>
<p>Desinstalamos la versión anterior del componente, comprimimos los archivos, e instalamos la nueva versión desde Extensiones -&gt; Instalar/Desinstalar. Y listo, hemos terminado de crear nuestro primer componente. En artículos posteriores veremos cómo añadir una interfaz de administración a nuestro componente.</p>
<link type="text/css" rel="stylesheet" href="http://mundogeek.net/sh/css/SyntaxHighlighter.css"></link><script language="javascript" src="http://mundogeek.net/sh/js/shCore.js"></script><script language="javascript" src="http://mundogeek.net/sh/js/shBrushPhp.js"></script><script language="javascript" src="http://mundogeek.net/sh/js/shBrushXml.js"></script><script language="javascript">dp.SyntaxHighlighter.ClipboardSwf = 'http://mundogeek.net/sh//flash/clipboard.swf';dp.SyntaxHighlighter.HighlightAll('code');</script><br />
]]></content:encoded>
			<wfw:commentRss>http://mundogeek.net/archivos/2010/02/12/creacion-de-componentes-para-joomla/feed/</wfw:commentRss>
		<slash:comments>31</slash:comments>
		</item>
		<item>
		<title>Struts 2</title>
		<link>http://mundogeek.net/archivos/2009/02/08/struts-2/</link>
		<comments>http://mundogeek.net/archivos/2009/02/08/struts-2/#comments</comments>
		<pubDate>Sun, 08 Feb 2009 16:32:25 +0000</pubDate>
		<dc:creator>Zootropo</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[desarollo]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[struts 2]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://mundogeek.net/?p=2469</guid>
		<description><![CDATA[Struts 2 es, como el nombre sugiere, la nueva versión del popular framework de desarrollo web en Java Apache Struts. Sin embargo, contrariamente a lo que cabría esperar, el código de ambos tiene poco que ver, dado que Struts 2 no se basa en el código de Struts 1.x, sino en el de otro framework [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://struts.apache.org/2.x/" title="Struts 2">Struts 2</a> es, como el nombre sugiere, la nueva versión del popular framework de desarrollo web en Java Apache Struts. Sin embargo, contrariamente a lo que cabría esperar, el código de ambos tiene poco que ver, dado que Struts 2 no se basa en el código de Struts 1.x, sino en el de otro framework de desarrollo web en Java llamado WebWork, un framework que el creador de Struts consideraba superior a Struts 1.x en varios aspectos.<br />
<span id="more-2469"></span><br />
Struts 2 está basado en el patrón MVC (Modelo-Vista-Controlador), una arquitectura que busca reducir el acoplamiento dividiendo las responsabilidades en 3 capas claramente diferenciadas:</p>
<ul>
<li>El modelo, que hace referencia a los datos que maneja la aplicación y las reglas de negocio que operan sobre ellos y que se traducen en Struts 2 en las acciones.</li>
<li>La vista, encargada de generar la interfaz con la que la aplicación interacciona con el usuario. En Struts 2 equivale a los resultados.</li>
<li>El controlador, que comunica la vista y el modelo respondiendo a eventos generados por el usuario en la vista, invocando cambios en el modelo, y devolviendo a la vista la información del modelo necesaria para que pueda generar la respuesta adecuada para el usuario. El controlador se implementa en Struts 2 mediante el filtro <code>FilterDispatcher</code></li>
</ul>
<p>Por supuesto, podríamos utilizar <a href="http://mundogeek.net/archivos/2007/01/25/jsp-javaserver-pages/" title="JSP">JSP</a> y <a href="http://mundogeek.net/archivos/2007/01/26/servlets/">servlets</a> para crear una aplicación utilizando el patrón MVC: en una aplicación con JSP y servlets clásica se suelen utilizar páginas JSP para la vista, un servlet como controlador (patrón front controller) y POJOs (Plain Old Java Objects) para el modelo. El modelo, a su vez, suele estar dividido en dos subcapas siguiendo el patrón DAO (Data Access Object).</p>
<p>Sin embargo no tiene sentido reinventar la rueda cuando podemos recurrir a un framework, como Struts 2, para que se encargue de obtener y transformar los parámetros de las peticiones del cliente, validar los datos, buscar qué acción se debe realizar en el modelo según la petición, buscar la página a mostrar al usuario según la respuesta del modelo, proporcionar los datos del modelo a la vista, ocuparse de la internacionalización, etc.</p>
<p>Veamos cómo crear un pequeño &#8220;Hola mundo&#8221; con Struts 2. O mejor aún: un hola <em>algo</em>.</p>
<p>Como IDE utlizaremos <a href="http://www.eclipse.org/" title="Eclipse">Eclipse</a>. También necesitaremos un servidor de aplicaciones o un contenedor web, como <a href="http://tomcat.apache.org/" title="Tomcat">Tomcat</a>. Para ver cómo integrar tu servidor en Eclipse puedes consultar la entrada <a href="http://mundogeek.net/archivos/2009/02/02/eclipse-y-tomcat/" title="Eclipse y Tomcat">Eclipse y Tomcat</a>, adaptando los pasos necesarios en caso de utilizar un servidor distinto.</p>
<p>Por supuesto también necesitaremos <a href="http://struts.apache.org/downloads.html" title="Descargar Struts 2">descargar Struts 2</a> desde su página web. En principio basta con descargar las librerías que componen Struts 2 y sus dependencias (Essential Dependencies Only) aunque también os puede interesar descargar la versión completa (Full Distribution) que incluye además la documentación, el código fuente, y distintas aplicaciones de ejemplo.</p>
<p>En todo caso una vez hemos descargado Struts 2, Eclipse y Tomcat ya está todo listo para comenzar a trabajar.</p>
<p>Abrimos Eclipse y nos dirigimos a File -> New -> Dynamic Web Project para crear un nuevo proyecto para web dinámica. En Project name introducimos el nombre que queramos utilizar para el proyecto, por ejemplo, hola. Pulsamos Finish.</p>
<p>Copiamos las librerías básicas a la carpeta WebContent\WEB-INF\lib. Estas son commons-fileupload, commons-logging, freemarker, ognl, struts2-core y xwork. Hacemos clic con el botón derecho sobre el proyecto, y seleccionamos Refresh para que Eclipse las vea.</p>
<p>Editamos el descriptor de despliegue (web.xml) para añadir el filtro que sirve a Struts 2 a modo de punto de entrada a la aplicación: <code>FilterDispatcher</code>. Hacemos doble clic sobre &#8220;Deployment Descriptor: hola&#8221; y sustituimos el contenido por el siguiente:</p>
<pre name="code" class="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    id="WebApp_ID" version="2.5"&gt;
    &lt;display-name&gt;hola&lt;/display-name&gt;

    &lt;welcome-file-list&gt;
        &lt;welcome-file&gt;index.jsp&lt;/welcome-file&gt;
    &lt;/welcome-file-list&gt;

    &lt;filter&gt;
        &lt;filter-name&gt;struts&lt;/filter-name&gt;
        &lt;filter-class&gt;org.apache.struts2.dispatcher.FilterDispatcher&lt;/filter-class&gt;
    &lt;/filter&gt;

    &lt;filter-mapping&gt;
        &lt;filter-name&gt;struts&lt;/filter-name&gt;
        &lt;url-pattern&gt;/*&lt;/url-pattern&gt;
    &lt;/filter-mapping&gt;
&lt;/web-app&gt;</pre>
<p>Como vemos lo único que estamos haciendo es indicar al contenedor web (Tomcat en este caso) que toda petición, tenga esta la URL que tenga, debe pasar por el filtro FilterDispatcher. FilterDispatcher es en realidad el controlador de nuestra aplicación; nosotros sólo tendremos que ocuparnos de la vista y el modelo, llamados resultados y acciones en la terminología de Struts 2.</p>
<p>Ahora vamos a crear la página de inicio de nuestra aplicación. Como en el descriptor de despliegue hemos indicado que index.jsp es uno de los &#8220;archivos de bienvenida&#8221; (welcome-file), cuando en la URL no se especifique el archivo a mostrar dentro del directorio se mostrará por defecto index.jsp; de esta forma tanto http://localhost:8080/hola/index.jsp como http://localhost:8080/hola/ mostrarán nuestra nueva página.</p>
<p>Hacemos clic con el botón derecho sobre WebContent y seleccionamos New -> JSP, en File name escribimos index.jsp y pulsamos Finish. El contenido de la página será el siguiente:</p>
<pre name="code" class="html">&lt;%@ taglib uri="/struts-tags" prefix="s" %&gt;

&lt;html&gt;
&lt;body&gt;
&lt;s:form action="Hola"&gt;
&lt;s:textfield name="nombre" label="Nombre"/&gt;
&lt;s:submit/&gt;
&lt;/s:form&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>
<p>Como vemos se utiliza la directiva taglib de JSP para indicar al contenedor que queremos usar la librería de etiquetas struts-tags, para las que se usará el prefijo &#8220;s&#8221;. Los nombres de las etiquetas de struts-tags que utilizamos son bastante descriptivos: estamos creando un formulario (<code>&lt;s:form&gt;&lt;/s:form&gt;</code>) con un campo de texto (<code>&lt;s:textfield/&gt;</code>) y un botón de enviar (<code>&lt;s:submit/&gt;</code>), que mandará los datos a la acción <code>Hola</code> (campo <code>action</code> del formulario).</p>
<p>Veamos ahora el código de la acción <code>Hola</code>. Las acciones en Struts 2 son clases Java que suelen implementar la interfaz <code>Action</code> o extender la clase <code>ActionSupport</code> (suelen, porque no es obligatorio). Creamosla haciendo clic con el botón derecho sobre Java Resources:src y seleccionando New -> Class; en Name, introducimos Hola y pulsamos Finish. Al crear el WAR de la aplicación el archivo .class acabará en WebContent/WEB-INF/classes. El código de la acción es el siguiente:</p>
<pre name="code" class="java">import com.opensymphony.xwork2.ActionSupport;

@SuppressWarnings("serial")
public class Hola extends ActionSupport {
    private String nombre;

    public String getNombre() {
        return nombre;
    }

    public void setNombre(String nombre) {
        this.nombre = nombre;
    }

    public String execute() {
        System.out.println(nombre);
        return SUCCESS;
    }
}</pre>
<p>El código a ejecutar por nuestra acción está contenido en un método <code>execute()</code>. Como vemos la funcionalidad es bastante pobre, una simple excusa para utilizar una acción, ya que podríamos haber prescindido totalmente de ella. Sin embargo este código tan sencillo, que imprime en la consola el nombre que el usuario introdujo en el formulario, pone de manifiesto algo bastante interesante y es que no aparece por ningún lado un objeto <code>HttpServletRequest</code> ni similar del que obtener el valor del parámetro <code>nombre</code> del formulario, luego, ¿de dónde sale la propiedad <code>nombre</code>?</p>
<p>Lo cierto es que Struts 2 (o más bien el interceptor <code>param</code> de Struts 2) nos tiene preparada una sorpresa, y es que basta con crear getters y setters con los nombres de los campos de los formularios para que estos se rellenen auto mágicamente, incluso aunque las propiedades no sean cadenas y sea necesaria una sencilla conversión. Este es el trabajo del interceptor <code>param</code>, como hemos dicho.</p>
<p>Los interceptores son unos de los elementos más importantes de Struts 2. Se trata de objetos que ejecutan código antes y después de una cierta acción, de forma que podamos añadir nueva funcionalidad no relacionada directamente con el modelo de forma modular. Tenemos interceptores para logging, para validación, para capturar excepciones, etc.</p>
<p>Como vemos el método <code>execute</code> devuelve un string indicando el resultado de la acción. En este caso se devuelve <code>SUCCESS</code>, que es una constante proveniente de la clase que extendemos, ActionSupport, y cuyo valor es &#8220;success&#8221;. ¿Y de qué sirve esto? Pues para que Struts 2 sepa a qué página redirigir, según el mapping que definimos en el archivo de configuración de Struts 2 struts.xml.</p>
<p>Vamos a crear este archivo. Hacemos clic con el botón derecho sobre Java Resources:src, seleccionamos New -> XML, pulsamos Next y seleccionamos como nombre struts.xml y como directorio de destino src. Este archivo acabará en WebContent/WEB-INF/classes al crear el WAR de la aplicación. Su contenido debe ser el siguiente:</p>
<pre name="code" class="xml">&lt;?xml version="1.0" encoding="UTF-8" ?&gt;
&lt;!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd"&gt;

&lt;struts&gt;
    &lt;package name="mi-paquete" extends="struts-default"&gt;
        &lt;action name="Hola" class="Hola"&gt;
            &lt;result name="success"&gt;/hola.jsp&lt;/result&gt;
        &lt;/action&gt;
    &lt;/package&gt;
&lt;/struts&gt;</pre>
<p>En este caso lo que estamos haciendo es indicar al framework que queremos que se ejecute el código de la clase <code>Hola</code> cuando llegue una petición a Hola.action, y que se muestre la página hola.jsp como resultado cuando el valor devuelto sea &#8220;success&#8221;.</p>
<p>Vamos a ver por último el código de hola.jsp. Hacemos clic con el botón derecho sobre WebContent y seleccionamos New -> JSP; en File name escribimos hola.jsp y pulsamos Finish. El contenido del archivo es el siguiente:</p>
<pre name="code" class="xml">&lt;%@ taglib uri="/struts-tags" prefix="s" %&gt;

&lt;html&gt;
&lt;body&gt;
Hola &lt;s:property value="nombre"/&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>
<p>En esta página lo único que hacemos es utilizar la etiqueta <code>&lt;s:property/&gt;</code> para mostrar la propiedad nombre de la acción, que se toma de una pila de valores llamada <code>ValueStack</code>.</p>
<p>Solo resta probar el código de nuestra aplicación. Arrastramos el proyecto sobre nuestra instancia de Tomcat en la pestaña Servers, e iniciamos el servidor haciendo clic con el botón derecho sobre él y seleccionando Start. Si abrimos la URL http://localhost:8080/hola/ en nuestro navegador y todo funciona correctamente, deberíamos ver algo como esto:</p>
<p><img src="http://mundogeek.net/wp-content/struts-2-ejemplo.png" alt="Struts 2 ejemplo" title="Struts 2 ejemplo"/></p>
<link type="text/css" rel="stylesheet" href="http://mundogeek.net/sh/css/SyntaxHighlighter.css"></link>
<script language="javascript" src="http://mundogeek.net/sh/js/shCore.js"></script><br />
<script language="javascript" src="http://mundogeek.net/sh/js/shBrushJava.js"></script><br />
<script language="javascript" src="http://mundogeek.net/sh/js/shBrushXml.js"></script><br />
<script language="javascript">dp.SyntaxHighlighter.ClipboardSwf = 'http://mundogeek.net/sh//flash/clipboard.swf';
dp.SyntaxHighlighter.HighlightAll('code');</script></p>
]]></content:encoded>
			<wfw:commentRss>http://mundogeek.net/archivos/2009/02/08/struts-2/feed/</wfw:commentRss>
		<slash:comments>80</slash:comments>
		</item>
		<item>
		<title>Los usuarios de verdad&#8230;</title>
		<link>http://mundogeek.net/archivos/2008/05/18/los-usuarios-de-verdad/</link>
		<comments>http://mundogeek.net/archivos/2008/05/18/los-usuarios-de-verdad/#comments</comments>
		<pubDate>Sun, 18 May 2008 11:00:53 +0000</pubDate>
		<dc:creator>Zootropo</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[citas]]></category>
		<category><![CDATA[desarollo]]></category>
		<category><![CDATA[humor]]></category>
		<category><![CDATA[programacion]]></category>

		<guid isPermaLink="false">http://mundogeek.net/archivos/2008/05/18/los-usuarios-de-verdad/</guid>
		<description><![CDATA[En respuesta a Los programadores de verdad Los usuarios de verdad nunca saben lo que quieren, pero saben que tu programa no lo ofrece. Los usuarios de verdad son capaces de encontrar la única combinación de valores que puede hacer que el sistema se caiga por días. Los usuarios de verdad saben tu número de [...]]]></description>
			<content:encoded><![CDATA[<p>En respuesta a <a href="http://mundogeek.net/archivos/2008/05/14/los-programadores-de-verdad/" title="Los programadores de verdad">Los programadores de verdad</a></p>
<blockquote><p>Los usuarios de verdad nunca saben lo que quieren, pero saben que tu programa no lo ofrece.</p></blockquote>
<blockquote><p>Los usuarios de verdad son capaces de encontrar la única combinación de valores que puede hacer que el sistema se caiga por días.</p></blockquote>
<blockquote><p>Los usuarios de verdad saben tu número de teléfono.</p></blockquote>
<blockquote><p>Los usuarios de verdad nunca usan la función de ayuda.</p></blockquote>
<blockquote><p>Los usuarios de verdad odian a los programadores de verdad.</p></blockquote>
<blockquote><p>Los usuarios de verdad no ayudan a definir los requisitos. Si estos tipos de los ordenadores son tan listos, deberían ser capaces de adivinar lo que queremos.</p></blockquote>
<blockquote><p>Los usuarios de verdad prueban todos los botones de la aplicación. Y vuelven a probarlos otra vez para ver si hacen algo distinto y maravilloso.</p></blockquote>
<blockquote><p>Los usuarios de verdad escriben preguntas estúpidas en los foros y esperan respuesta.</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://mundogeek.net/archivos/2008/05/18/los-usuarios-de-verdad/feed/</wfw:commentRss>
		<slash:comments>25</slash:comments>
		</item>
	</channel>
</rss>

