Monthly Archives: October 2008

Comandos básicos de SVN: referencia rápida

Importación inicial del proyecto al repositorio.

$ svn import <ruta>/proyecto http://svn.servidor.net/proyecto/trunk -m 'Descripción de la creación'

Recepción de primera vez.

$ svn co http://svn.servidor.net/proyecto/trunk

Recepción ordinaria.

$ svn checkout http://svn.servidor.net/proyecto/trunk <ruta>/proyecto

Verificación del estado actual del repositorio local.

$ svn status

Revisión de cambios entre versiones.

$ svn log -v -r<version>

Solicitud de información de un archivo específico.

$ svn info index.php

Agregar un archivo al repositorio.

$ svn add <ruta>/class.php

Actualizar las fuentes locales.

$ svn update

Envío de modificaciones locales al repositorio.

$ svn commit -m 'Descripción de la actualización'

Enlaces:

Introducción a StaticMaps de Google

Introducción

StaticMaps es una herramienta de Google que nos permite integrar en nuestras aplicaciones a imagenes estáticas de su cartografía de una manera muy simple.  Como se puede inferir, para utilizarlos es necesario que la aplicación tenga acceso a Internet y su acceso se realiza a través de un requerimiento HTTP convencional con ciertos parámetros que se verán a continuación y que permiten refinar el contenido de la imagen del mapa producido.

Esta herramienta la he utilizado varias veces en diferentes tipos de proyectos como Mi Primer Moblet (móviles), GeoReferenciación con Java (escritorio) y la demostración de MandarinaSocial (agentes de software).

Para su uso se requiere que el desarrollador registre de manera gratuita el dominio desde donde se va a utilizar el servicio.  El registro se materializa a través de una llave de API particular.  Esta llave se solicita a través del siguiente enlace.

http://code.google.com/apis/maps/signup.html

El servicio se restringe a un máximo de 1000 requerimientos únicos diarios, siendo este límite aplicado por solicitante (ubicación) y no por llave lo que disminuye el impacto de esta restricción, mas aún cuando las solicitudes repetidas de la misma imagen no son tomadas en cuenta para la estadística de la cuota.

Un primer acercamiento a la herramienta consiste en jugar un poco con ella utilizando el Static Map Wizard.

Forma de acceso

Como se mencionó anteriormente, la solicitud se inicia requiriendo un URL con ciertos parámetros a través de GET y el servicio retorna una imagen en un formato compatible con web que puede ser insertada en una página web con una etiqueta <img> o puede ser manipulada por una aplicación desarrollada en cualquier lenguaje de programación como Java o C#.

Los siguientes aspectos del StaticMap pueden ser parametrizados a través de los parámetros del URL.

  • La ubicación del mapa.
  • El tamaño de la imagen generada.
  • El nivel de acercamiento.
  • El tipo de mapa.
  • El lugar de los marcadores.
  • El lugar de las rutas trazadas.
Estructura general del URL

Esta es la estructura básica del URL sobre la cual se estructura el requerimiento del servicio.

http://maps.google.com/staticmap?PARÁMETROS

La lista de PARÁMETROS consiste en varias secciones separadas entre sí por & y que se encuentran construídas con un formato especial y que serán descritas a continuación.

Estos son los parámetros del servicio suceptibles de personalizarse.

  1. center.
  2. zoom.
  3. size.
  4. format.
  5. maptype.
  6. markers.
  7. path.
  8. frame.
  9. key.
Ubicaciones

Las ubicaciones georreferenciadas son especificadas de la forma latitud y longitud como dos valores reales con 6 dígitos decimales de precisión y separados por una coma: 5.07,-75.521.

Los valores válidos de una latitud varían desde -90 hasta 90 grados mientras que los valores válidos para una longitud varía desde -180 hasta 180 grados.

Parámetro Key

Es obligatorio y se utiliza para especificar la llave del API que se obtuvo inicialmente.  Sin esto, es imposible acceder al servicio.

http://maps.google.com/staticmap?center=5.07,-75.521&zoom=5&size=500×300&key=ABQIAAAAAa_xc3cplYGMwVbx_zW2chTWZSld1Wm-gV17JxrvtQa7WXWbRRTOL98qj5hk-yEw1n5LrYmEoAwzOg

Parámetro Center

Es obligatorio pero se convierte en opcional bajo ciertas circunstancias.  Determina la ubicación al rededor de la cual se centrará el mapa generado.

http://maps.google.com/staticmap?center=5.07,-75.521

El mapa anterior se encuentra centrado al rededor de las coordenadas de Manizales, Caldas.

Parámetro Zoom

Es obligatorio pero se convierte en opcional bajo ciertas circunstancias.  Determina el nivel de acercamiento al mapa.

Es definido por un número entero que varía entre 0 (menor) hasta 19 (máxima).  Debe tenerse en cuenta que no todos los niveles de acercamiento están disponibles para todos los tipos de mapas.

http://maps.google.com/staticmap?center=5.07,-75.521&zoom=11

El mapa anterior determina un nivel 11 de acercamiento sobre Manizales.

Parámetro Size.

Es obligatorio.  Especifica el tamaño de la imagen generada.

Su valor se especifica por un ancho y un alto separados por la letra 'x' y su unidad es en pixels: 500×300.  El valor máximo de estas dimensiones es 640×480.

http://maps.google.com/staticmap?center=5.07,-75.521&zoom=11&size=500×300

La imagen generada a partir del requerimiento anterior tiene un ancho de 500px y un alto de 300px.

Parámetro Format.

Es opcional y determina el tipo de formato de la imagen generada.  Su selección depende de la relación tamaño/calidad deseada.  Si se omite, su valor por defecto es GIF.

Los posibles valores para este parámetro son los siguientes.

  • gif (por defecto).
  • jpg
  • jpg-baseline (no progresivo)
  • png8 (8 bits)
  • png32 (32 bits)

http://maps.google.com/staticmap?center=5.07,-75.521&zoom=11&size=500×300&format=png8

El ejemplo anterior genera una imagen con formato PNG de 8 bits.

Parámetro MapType.

Es opcional y determina el tipo de cartografía a utilizarse para la generación de la imagen.  Si se omite, su valor por defecto es roadmap.

Los posibles valores para este parámetro son los siguientes.

  • roadmap (por defecto).
  • mobile.  Presenta mejoras gráficas para la visualización en dispositivos móviles.
  • satellite. Muestra las imagenes de satélite.
  • terrain. Muesta el mapa del relieve y la vegetación.
  • hybrid. Mezcla el contenido de los tipos roadmap y satellite.

http://maps.google.com/staticmap?center=5.07,-75.521&zoom=11&size=500×300&format=png8&maptype=hybrid

El ejemplo anterior modifica el tipo de mapa visto hasta ahora (roadmap) y presenta un mapa estilo híbrido de la misma ubicación.

Parámetro Markers.

Es opcional y permite especificar y personalizar los marcadores que referenciarán ubicaciones importantes en el mapa.  Es posible especificar hasta 50 marcadores diferentes por mapa.

Cuando se especifica el parámetro markers no es necesario especificar a los parámetros center y zoom ya que estos se pueden calcular automáticamente.

La información de los marcadores se especifica con una cadena separada por '|' (%7C) de la siguiente manera.

markers=infoMarcador1|infoMarcador2|infoMarcador3|…

La información de los marcadores incluye datos tanto de su ubicación como de su presentación.  Cada marcador se crea con la siguiente estructura.

{latitud},{longitud},{tamaño}{color}{identificador}

El siginificado de cada uno de estos campos se describe a continuación.

  • latitud (requerido).  Latitud de la ubicación del marcador.
  • longitud (requerido).  Longitud de la ubicación del marcador.
  • tamaño (opcional).  Tamaño de la imagen del marcador.  Puede tomar uno de los siguientes valores.
    • tiny
    • mid (por defecto)
    • small
  • color (opcional).  Determina el color de la imagen del marcador.  Puede tomar una de las siguientes constantes.
    • black
    • brown
    • green
    • purple
    • yellow
    • blue
    • gray
    • orange
    • red (por defecto)
    • white
  • identificador (opcional).  Permite especificar un carácter alfanumérico y en minúsculas para identificar al marcador.  Debe tenerse en cuenta que este identificador sólo aplica para marcadores tamaño mid.  Su valor por defecto es el punto.

http://maps.google.com/staticmap?size=500×300&format=png8&maptype=hybrid&markers=5.07,-75.521,midyellowm|4.813,-75.696,midbluep|4.534,-75.681,midreda

El ejemplo anterior muestra el mapa del eje cafetero colombiano resaltando sus ciudades con marcadores de la siguiente manera: Manizales (amarillo), Pereira (azul) y Armenia (rojo).

Parámetro Path.

Es opcional y permite especificar y personalizar rutas sobre el mapa que conectan a dos o mas puntos georreferenciados.  El límite es el de máximo 100 puntos por ruta.

El parámetro se define de manera similar a markers siguiendo el siguiente formato.

path=tipoColor:#color,weight:pesoRuta|punto1|punto2|punto3|…

El siginificado de cada uno de estos campos se describe a continuación.

  • tipoColor.  Especifica el tipo de formato del color.  Puede tomar uno de los siguientes valores.
    • rgb.  Esquema RGB estándar con valores de 24 bits de la forma 0xffffff.  Su nivel de opacidad por defecto es de 50%.
    • rgba.  Utiliza valores de 32 bits de la forma 0xffffffff.  El nivel de opacidad está dado por el cuarto byte (últimos dos carácteres) que conforman el canal alfa de transparencia.
  • weight.  Especifica el grosor de la ruta en pixels.

http://maps.google.com/staticmap?size=500×300&format=png8&maptype=hybrid&markers=5.07,-75.521,midyellowm|4.813,-75.696,midbluep|4.534,-75.681,midreda&path=rgb:0x0000ff,weight:5|5.07,-75.521|4.813,-75.696|4.534,-75.681

En este ejemplo se agrega una ruta azul entre Armenia – Pereira – Manizales sobre el ejemplo inmediatamente anterior.

Parámetro Frame.

Es opcional y especifica si la imagen resultante se debe o no mostrar con un borde azul de 5px y con 55% de opacidad a su alrededor.  Por defecto no se muestra.

http://maps.google.com/staticmap?size=500×300&format=png8&maptype=hybrid&markers=5.07,-75.521,midyellowm|4.813,-75.696,midbluep|4.534,-75.681,midreda&path=rgb:0x0000ff,weight:5|5.07,-75.521|4.813,-75.696|4.534,-75.681&frame=true

Enlaces:

Ejecutar después de un efecto con Scriptaculous

Algunas veces es necesario ejecutar cierta acción exactamente después de que se ejecute un efecto sobre la interfaz de usuario, por ejemplo, resaltar la fila que se va a remover y solamente después de terminado el efecto, se remueve efectivamente la fila.

Con Scriptaculous se debe utilizar el callback afterFinish ya que de lo contrario las instrucciones se ejecutarán de manera serial interfiriéndose mutuamente provocando que la fila sea removida casi de inmediato y el efecto no pueda ser apreciado.

A continuación se muestra un pequeño fragmento de código que ejemplifica la implementación descrita anteriormente.

var op = $('fila_a_remover');
op.puff({
    afterFinish: function()
    {
        op.remove();
    }
});

Enlace: Effect.Puff API.

Top 10 Things That Annoy Programmers

Un resúmen muy interesante, mas que ciertos.

10.  Comments that explain the "how" but not the "why"
9.  Interruptions
8.  Scope creep
7.  Management that doesn't understand programming
6.  Documenting our applications
5.  Applications without documentation
4.  Hardware
3.  Vagueness
2.  Other programmers
1.  Their own code, 6 months later

Versión completa en inglés y en español.

Instalación de OpenOffice 3 en Ubuntu

Bueno, no me aguanté las ganas de probar al OpenOffice3 hasta que Ubuntu publicara la actualización en el repositorio oficial.

Para realizar la instalación manual seguí estos pasos.

  1. Desinstalar la versión anterior desde el Synaptic Package Manager, aunque es opcional porque se supone que pueden convivir las dos versiones.
  2. Descargué y descomprimí la última distribución disponible para Debian: OOo_3.0.0_LinuxIntel_install_en-US_deb.
  3. Desde la carpeta recién creada ejecuté los siguientes comandos.

    $ cd <RUTA>/OOO300_m9_native_packed-1_en-US.9358/DEBS
    $ sudo dpkg -i *.deb

  4. Listo.

La desventaja de este método es que no se crean automáticamente los íconos en el menú de usuario, sin embargo es fácil crearlos a través de System > Preferences > Main Menu para las siguientes aplicaciones que quedan instaladas bajo /opt/openoffice.org3/program/.

  • OpenOffice -> soffice
  • OpenOffice Base -> sbase
  • OpenOffice Draw -> sdraw
  • OpenOffice Impress -> simpress
  • OpenOffice Writer -> swriter
  • OpenOffice Calc -> scalc
  • OpenOffice Math -> smath

Autocompletador con Prototype/Scriptaculous – Parte II

Como complemento a la primera parte, en este artículo se ampliará el concepto del Autocompleter de Prototype/Scriptaculous a su versión mas flexible que hace uso del envío de mensajes asíncronos mejor conocidos como AJAX.

Para su implementación se requieren de dos partes las cuales se analizarán en el orden expuesto a continuación.

  • Un formulario HTML con el campo que incluye la autocompletación.
  • Una aplicación PHP que recibe y procesa la solicitud de información y genera los resultados de manera dinámica.

El formulario es igual al anterior, incluye el text donde el usuario escribirá el criterio que se autocompletará cuyo identificador es t_criterio y un espacio, cuyo identificador es resultado, donde se desplegarán las posibles sugerencias arrojadas por la aplicación PHP basada en el criterio antes especificado.

<div id='contenedor'>
    <div id='criterio'>
        Criterio
        <input type='text' id='t_criterio' size='50' maxlength='200' />
    </div>
    <div id='resultado'>
        No hay resultados que mostrar.
    </div>
</div>
Ejemplo de Ajax.Autocompleter

Ejemplo de Ajax.Autocompleter

Para activar el autocompletado del campo t_criterio se ejecuta el método estático Ajax.Autocompleter tan pronto como el árbol DOM de la página ha sido cargado de la siguiente manera.

new Ajax.Autocompleter('t_criterio',
                       'resultado',
                       'fuente.php',
                       {
                           paramName: 'criterio',
                           method: 'post',
                           parameters: 'estatico1=valor1&estatico2=valor2',
                           callback: function(editor, paramText) {
                               return paramText + '&time=' + new Date().getTime();
                           },
                           select: 'm_nombre',
                           afterUpdateElement: function (inputField, suggestion) {
                               inputField.value = suggestion.down('span.m_nombre').innerHTML + " / " + suggestion.down('span.m_departamento').innerHTML;
                           }
                       });

Los parámetros que recibe el método se describen a continuación, de los cuales sólo los tres primeros son obligatorios.

  • Id del text con el criterio de búsqueda para la autocompletación.
  • Id del área donde se van a mostrar las opciones sugeridas.
  • URL donde se ubica a la aplicación dinámica que va a procesar la búsqueda de sugerencias a través de AJAX.
  • Hash con opciones adicionales.
    • paramName: nombre del parámetro que se enviará a la aplicación dinámica con el contenido del texto especificado por el usuario.  Si no se especifica este parámetro, se utilizará el atributo name del campo de texto del formulario.
    • method: método a través del cual se enviará la información a la aplicación web: post o get.
    • parameters: parámetros estáticos para ser enviados adicionalmente.
    • callback: función ejecutada antes de ser invocada la aplicación PHP y que permite manipular de manera dinámica los parámetros enviados.
    • select: campo de la sugerencia elegida que es mostrado en el campo de texto cuando la sugerencia es seleccionada.  El valor de este campo se relaciona con el selector CSS donde se encuentra ubicada la información.
    • afterUpdateElement: función invocada justo después de que el usuario ha seleccionado a una de las opciones presentadas.  Permite componer de manera dinámica un valor para ser mostrado como la selección del usuario.  Es mas elaborado y sobreescribe lo especificado en el parámetro select.

Adicionalmente las opciones adicionales minChars y frequency se encuentran también disponibles y operan de igual manera que en el autocompletador local.

La aplicación dinámica (fuente.php) por su parte, desarrollada en PHP para este ejemplo, realiza las siguientes acciones.

Obtiene el valor del criterio de búsqueda especificado por el usuario.  La forma de recuperarlo depende del método (method) utilizado por el formulario.

$criterio = $_POST['criterio'];

Se realiza una consulta a la base de datos y/o un procesamiento de la información lo que constituye el carácter dinámico de la aplicación.  Para este ejemplo, se consulta la base de datos (SQLite utilizando PDO) de la división geopolítica de Colombia y se buscan los municipios cuyos nombres contengan a la subcadena especificada.

$link = new PDO('sqlite:data/database.sqlite');
$sql = "SELECT m.nombre AS nombre, d.nombre AS departamento,
               m.latitud AS latitud, m.longitud AS longitud
        FROM municipios m, departamentos d
        WHERE m.id_departamento = d.id_departamento AND
              m.nombre LIKE '%{$criterio}%'";
$result = $link -> query($sql);

El resultado enviado al formulario está constituído por la salida estándar (echo/print/etc.) de la aplicación PHP.  Su estructura es la de una lista no ordenada: <ul><li>…</li>…</ul>.

Para finalizar, se construye la lista no ordenada con la información obtenida de la base de datos.

$str = "<ul>\n";
foreach ($result as $row)
{
    $str .= "<li>\n";
    $str .= "<div class='titulo'>Título: <span class='m_nombre'>" . utf8_decode($row['nombre']) . "</span></div>";
    $str .= "<div class='titulo'>Departamento: <span class='m_departamento'>" . utf8_decode($row['departamento']) . "</span></div>";
    $str .= "<div class='titulo'>Latitud: <span class='m_latitud'>" . utf8_decode($row['latitud']) . "</span></div>";
    $str .= "<div class='titulo'>Longitud: <span class='m_longitud'>" . utf8_decode($row['longitud']) . "</span></div>";
    $str .= "</li>\n";
}
$str .= "</ul>\n";
echo utf8_encode($str);

La información almacenada e impresa en la variable $str es la que será mostrada en el área de sugerencias: #resultado.

Enlaces:

Autocompletador con Prototype/Scriptaculous – Parte I

Prototype, al igual que otros frameworks de JavaScript, permite implementar fácilmente comportamientos que que serían dispendiosos de crear a partir del JavaScript básico y convencional.  El hermanito Scriptaculous viene a ayudarnos aún mas con sus efectos y ayudantes.

Un ejemplo de estas posibilidades de rápida implementación es la simulación del autocompletar de un campo de texto.

El objeto Autocompleter acepta dos fuentes de datos diferentes.

  1. Una local como un arreglo de JavaScript.
  2. Una remota y mas dinámica a través de solicitudes AJAX.

En este artículo se va a realizar la demostración del uso de un Autocompleter.local.  Para esto se requieren dos componentes.

  • Un campo de texto donde el usuario escribe el criterio de búsqueda.
  • Una sección de sugerencias donde el Autocompleter despliega las coincidencias basadas en el criterio de búsqueda.
Ejemplo de Autocompleter.local

Ejemplo de Autocompleter.local

Para el ejemplo anterior cuenta con los siguientes elementos.

  • t_criterio: campo de texto para el criterio de búsqueda.
  • resultado: es el div donde se  desplegarán las sugerencias encontradas.
  • departamentos: es un arreglo JavaScript con la información local y estática para las opciones de búsqueda, en este caso el listado de los departamentos de Colombia.

Para activar el autocompletado sobre t_criterio basado en los valores de departamentos, se ejecuta la siguiente instrucción JavaScript.

var ac = new Autocompleter.Local('t_criterio',
                 'resultado',
                 departamentos,
                 {
                     autoSelect     : false,
                     frequency      : 0.4,
                     minChars       : 1,
                     choices        : 10,
                     paritialSearch : false,
                     paritialChars  : 2,
                     fullSearch     : true,
                     ignoreCase     : true
                 });

Los parámetros especificados al método Local son descritos a continuación.

  1. Id del campo de texto con el criterio de búsqueda.
  2. Id del contenedor de los resultados obtenidos.
  3. Arreglo con la información disponible.
  4. Hash con las opciones de configuración del autocompletador.  Todos estos valores son opcionales y los mostrados corresponden con los valores por defecto.

A continuación se describen las opciones de configuración disponibles.

  • autoSelect: Acepta automáticamente la primera sugerencia cuando sólo hay una.
  • frecuency: Tiempo en segundos entre dos intentos de autocompletar.
  • minChars: Cantidad mínima de carácteres necesarios para que se active el autocompletar.
  • choices: Cantidad máxima de opciones sugeridas a mostrarse.
  • paritialSearch: Tomar en cuenta para la búsqueda el comienzo de cada palabra o sólo el comienzo del texto.
  • paritialChars: Cantidad mínima de carácteres necesarios para que se active la búsqueda parcial.
  • fullSearch: Tomar en cuenta cualquier subcadena de las opciones o sólo los comienzos (palabra o línea).
  • ignoreCase: Tomar o no en cuenta la diferencia entre mayúsculas/minúsculas.

Enlaces:

Modelos en PHP: cosas buenas/malas del lenguaje

PHP es un lenguaje muy fácil de aprender si se tienen conocimientos en C/C++/Java/C# o similares.  Es muy fácil de utilizar y es muy fácil de desarrollar aplicaciones pequeñas-medianas con él.

También, como todo en la vida, tiene sus desventajas.  Lo interesante es que a mi parecer, las ventajas del lenguaje son también desventajas y viceversa según como se miren, es decir, según lo que se necesite.

En este momento me interesa mencionar dos de ellas:

  • Fuera de la caja de se obtiene lo básico, un lenguaje para empezar a escribir código, a diferencia de otros lenguajes que incluyen por si mismos todo un framework o ambiente de desarrollo.
  • Es un lenguaje señoritero, la falta de tipos y de la mucha rigurosidad de los demás lenguajes hace que hasta la gente que no sabe desarrollar software crea que si lo hace.

Estas son verdades: el lenguaje es deficiente para muchas cosas aunque les duelan a algunos que les gusta desgastarse simulando fanatismos hasta por un lenguaje de programación.  Pero como mencioné anteriormente, son cosas buenas/malas según como se les mire.

  • La independencia de tanta infraestructura que tal vez excede lo que necesitamos evita que las soluciones pequeñas y puntuales se conviertan en todo un circo de capas y niveles que consumen tiempo, recursos y paciencia.  Sería como utilizar JSF+Hibernate+Spring para hacer un HolaMundo.  Las soluciones son de la forma y el tamaño como el desarrollador las quiera: el problema es saber que querer y como lograrlo.De todos modos hay muchos frameworks para PHP allá afuera, desde los diminutos, los medianos y los grandes: MoonPHP, Picora, CodeIgniter, KohanaPHP, CakePHP, Prado, Symfony y Zend para nombrar a solo unos pocos del montón que existen en esta Internet que es tan larga como ancha.
  • Esta falta de rigurosidad bien utilizada, nos permite aprovecharla para hacer cosas cosas interesantes.  Todo es un arma peligrosa o una herramienta útil según quien la esté sosteniendo.

Y es con la flexibilidad que confiere la falta de rigurosidad la que permite o facilita la implementación -rápida- de códigos útiles.  MyModel 0.1 es solamente una demostración de las cosas que se pueden hacer con PHP y estoy seguro casi nadie conoce.

Los modelos son la representación de las clases de la lógica del negocio en una aplicación.  Algunos dicen que coinciden 1:1 con las entidades de persistencia: tablas de la base de datos.

Para los modelos, clases ellos con atributos y métodos, gracias al encapsulamiento acostumbramos a definir sus atributos como private/protected y a implementarles métodos setter/getter (obt/pon) para modificar o consultar su estado.

Este procedimiento trae consigo consecuencias negativas en medio de todo lo útil que es el encapsulamiento.

  • Hay que hacer métodos set/get para todos los atributos (que sea interesantes) de todas las clases de los modelos.
  • La mayoría de las veces hacemos unos métodos setter/getter que daría lo mismo que los atributos fueran public.
  • Es tedioso hacer los métodos, mas aún si como acabo de mencionar no incluyen siempre una ventaja tangible.  Los IDEs amables acostumbran a hacer por nosotros las plantillas básicas de estos métodos.

Este mes estuve pensando como poder hacer algo para solucionar estos problemas con PHP y recordé los métodos __set/ __get incluídos en toda clase PHP y se me ocurrió intentar implementar algo como las propiedades de .NET pero que funcionaran de manera automática.

Rápidamente implementé una primera versión que permite hacer esto.

Persona es una clase con un atributo llamado $nombre.  Si Persona hereda de MyModel estará entonces posibilitada para hacer esto:

$p -> Nombre = "Jorge";
echo $p -> Nombre;

La sobreescritura de los métodos mencionados antes me permiten decirle al modelo que cuando le hablen de la propiedad Nombre haga referencia al atributo nombre.  Mas aún, cuando le hablen de Nombre primero verifique si existen los métodos setNombre y getNombre y haga uso de ellos.

Una segunda mini versión le agregó un poco mas de encapsulamiento.

  • Si el atributo es private, no se puede acceder de ninguna manera.
  • Si el atributo es protected sólo se puede acceder desde el exterior si tiene setter/getter.
  • Si el atributo es public se puede acceder externamente.
  • Si el atributo es public pero tiene setter/getter, estos métodos serán utilizados en lugar del acceso directo.
  • Sólo las propiedades cuyos métodos setter/getter sean public pueden ser accedidas desde el exterior.

Con esto podemos hacer, digo yo, los modelos con atributos public y filtrar con métodos setter/getter los que nos interese restringir su acceso.

Ejemplo:

Téngase en cuenta a la clase User cuya implementación es de la siguiente manera.

class User extends MyModel
{
    private   $id;
    public    $username;
    public    $password;
    protected $name;
    public function getPassword()
    {
        return str_repeat("*", strlen($this -> password));
    }
    public function setName($value)
    {
        $this -> name = "--- " . $value . " ---";
    }
    public function getName()
    {
        return strtoupper($this -> name);
    }
}

Considérese un programa que la utiliza como se muestra a continuación.

$u = new User();
// $u -> id = 7;                               // Inválido porque $id es private y no ha métodos set/get.
$u -> Username = 'jimezam';                  // Se accede directamente porque $username es público.
echo "username: " . $u -> Username . "";     // Se accede directamente porque $username es público.
$u -> Password = 'secreto';                   // Se accede directamente porque $password es público.
echo "password: " . $u -> Password . "";     // Se ejecuta getPassword.
$u -> Name = "Jorge Ivan";                   // Se ejecuta setName.
echo "nombre: " . $u -> Name . "";           // Se ejecuta getName.

El resultado es el siguiente por los motivos explicados en los comentarios frente a cada línea del código.

username: jimezam
password: *******
nombre: --- JORGE IVAN ---

Se aceptan sugerencias constructivas para ir complementando a MyModel.

Enlaces:

Actualización de portales web basados en Drupal a la versión 5.11

En este artículo se resumen los pasos realizados para la actualización de los portales Drupal a la versión 5.11 la cual fue liberada en octubre 8 de 2008 y aparece como crítica para ser actualizada lo mas pronto posible.

1. Realizar la copia de seguridad de la base de datos del portal.

2. Actualizar los módulos disponibles según update-status.

3. Realizar la actualización de los archivos.

$ wget http://ftp.drupal.org/files/projects/drupal-5.11.tar.gz
$ mv site site.old
$ tar zxvf drupal-5.11.tar.gz
$ mv drupal-5.11/ site
$ cp -rf site.old/files site
$ cp -rf site.old/sites site
$ cp -rf site.old/themes/MITEMA site/themes/
$ cp -rf site.old/sites/default/modules site/sites/default
(web) $URL/apps/site/update.php
(web) $URL/?q=admin/logs/updates
(web) $URL/apps/site/update.php
$ rm drupal-5.11.tar.gz

Con esta actualización se introducen dos modificaciones al esquema de actualizaciones de Drupal bastante estable que he estado siguiendo hasta la fecha.

  • Actualizar los módulos primero antes de realizar la actualización de Drupal para evitar posibles conflictos aún peores con la nueva versión.
  • Guardar los módulos de terceros bajo sites/default/modules en lugar de bajo modules.  Esto permite separar los módulos de la distribución de Drupal de los instalados del repositorio confiriendo mayor claridad y facilidad en la administración y actualización.

Historia gráfica en el tiempo: UNIX, Windows y Lenguajes de Programación

En el sitio de Éric Lévénez encontré algo muy interesante, los gráficos con la distribuciones de UNIX, Windows y los principales lenguajes de programación ordenados en el tiempo y con actualización frecuente!

Toda una joya documental e histórica.