Mostrando entradas con la etiqueta caracteristicas. Mostrar todas las entradas
Mostrando entradas con la etiqueta caracteristicas. Mostrar todas las entradas

viernes, 2 de septiembre de 2011

Yupp CMS: un nuevo comienzo

Hace ya varios años que vengo desarrollando en PHP, y desde el principio comencé a experimentar distintas técnicas para el desarrollo de sitios web dinámicos. La culminación de esa investigación dio lugar a mi primer proyecto de CMS. Luego de seguir avanzando en mi formación universitaria, y conociendo diversas tecnologías, me di cuenta que aquel primer CMS no era suficiente, y tratando de hacerlo más genérico y extensible fue que comencé el proyecto Yupp Framework (si, todo esto comenzó como una librería que sería el core de un CMS).

Ahora Yupp tiene vida propia y superó mis expectativas como proyecto, convirtiéndose en una herramienta muy potente para el desarrollo PHP en general. Ahora estoy volviendo a las raíces, y con todo lo aprendido de los distintos intentos de CMS, y de la experiencia acumulada durante años, me lancé a lograr algo mejor, más genérico, más extensible, más fácil de usar, más dinámico, o sea la herramienta perfecta. Claro está, que la herramienta perfecta para unos puede no serlo para otros, desde mi humilde lugar lo que quiero es bajar a tierra todas esas "grandes ideas" y ponerlas en una herramienta que me facilite en el trabajo diario.

Aquí están algunas capturas de pantalla del prototipo que tengo hasta ahora. Es una aplicación para Yupp Framework v0.4, donde desarrollé varias funcionalidades básicas, y aunque faltan otras tantas, se puede usar.

Todos los que quieran colaborar con el proyecto, por favor contesten este hilo de discusión.

Esta primer captura de pantalla muestra una página del portal en modo "edición", donde hay zonas que se ven de colores (rojo, violeta, azul, etc), y cada zona puede contener varios módulos (las cajitas celestes).
Los módulos pueden ser de 3 tipos: html, menú y google maps. Estos son solo algunos que desarrollé para probar el concepto, la idea es que sea algo con extensibilidad ilimitada y cualquiera pueda crear sus propios módulos fácilmente, extendiendo así la funcionalidad del CMS.



Los módulos pueden arrastrarse y soltarse en distintas zonas, lo que ayuda a que rápidamente un editor pueda ubicar los módulos en las zonas correctas. En la siguiente imagen se ve como el módulo html que contenía el banner en la zona superior, es movido a la zona intermedia.



Esta tercer captura de pantalla muestra la edición del contenido de un módulo de html.



Y esta cuarta captura muestra el resultado luego de la edición del contenido del módulo de html.



Otra funcionalidad que provee este prototipo, es el cambio de layout con un clic. Un layout define la estructura general de las páginas, con las zonas donde se pueden ubicar distintos módulos. Un programador puede generar nuevos layouts, e instalarlo en el CMS. Incluso los diseñadores gráficos no programadores, podrían generar layouts. La siguiente imagen muestra el cambio de layout con respecto a las imágenes anteriores:


Esta imagen muestra otro cambio de layout:



Un editor podría crear nuevos módulos y agregarlos en distintas zonas con un par de clics.



La siguiente imagen muestra el módulo luego de creado:



El editor podría también crear subpáginas para la página actual:



Las subpáginas de la página actual aparecen en el menú en la parte inferior:



Por último, si salimos del modo "edición", podemos ver la página en modo "visualización":




martes, 19 de enero de 2010

Testing del ORM

En la línea de acción que estamos siguiendo para estabilizar el framework, estamos implementando un set de pruebas para YORM, el componente de ORM de Yupp Framework. Los tests se centran en la generación de las tablas en la base de datos, guardar correctamente estructuras complejas de datos, obtener estructuras complejas de datos desde la base, y verificar restricciones sobre los datos que se intentan guardar en la base.

Con esto lograremos encontrar las debilidades del YORM, al mismo tiempo que demostramos las fortalezas que tiene actualmente.

Los juegos de tests pueden ser descargados del SVN en nuestro sitio en Google Codehttp://code.google.com/p/yupp/source/checkout

De esta forma nos acercamos a una versión estable de Yupp Framework, garantizando su poder para crear proyectos web de forma ágil y sencilla, ordenando el desarrollo y evitando las tareas repetitivas.


Actualización:
Uno de los tests que estoy desarrollando es el de probar estructuras de árboles en la base de datos. La prueba consiste en implementar una clase persistente en YORM, la cual es una página web, que a su vez puede tener subpáginas. Aquí está la implementación de la clase:

class Pagina extends PersistentObject
{
   function __construct($args = array (), $isSimpleInstance = false)
   {
      $this->setWithTable("test_a004_pagina");

      $this->addAttribute("titulo",  Datatypes :: TEXT);
      $this->addAttribute("contenido", Datatypes :: TEXT);

      // Pagina padre
      $this->addHasOne('owner', 'Pagina');

      // Paginas hijas
      $this->addHasMany('subpages', 'Pagina');

      $this->addConstraints(
         "titulo",
         array (
            Constraint :: maxLength(255)
         )
      );
      $this->addConstraints(
         "contenido",
         array (
            Constraint :: maxLength(100000)
         )
      );
      $this->addConstraints(
         "owner",
         array (
            Constraint :: nullable(true) // Las paginas del primer nivel no tienen padre.
         )
      );

      parent :: __construct($args, $isSimpleInstance);
   }

   // Mas codigo ...
}

Y ahora la prueba de cómo generar una estructura de árbol y guardarla en la base. Lo que vamos a hacer son 4 instancias de la clase Pagina, la primera es la página raíz, la segunda es hija de la página raíz y las dos restantes son a su vez hijas de esta última. Con el siguiente código no solo creamos la estructura de árbol de páginas, si no que vamos a ver que toda la estructura se guarda automáticamente en la base con una única línea de código por parte del programador!!!

$p1 = new Pagina(
        array(
          "titulo" => "Pagina raiz",
          "contenido" => "This step is usually done transparently as most compilers perform it and then invoke the assembler..."
        )
      );
      $p11 = new Pagina(
        array(
          "titulo" => "Subpagina de raiz 1",
          "contenido" => "This step is usually done transparently as most compilers perform it and then invoke the assembler...",
          "owner" => $p1
        )
      );
      $p111 = new Pagina(
        array(
          "titulo" => "Sub subpagina de raiz 1",
          "contenido" => "This step is usually done transparently as most compilers perform it and then invoke the assembler...",
          "owner" => $p11
        )
      );
      $p112 = new Pagina(
        array(
          "titulo" => "Sub subpagina de raiz 2",
          "contenido" => "This step is usually done transparently as most compilers perform it and then invoke the assembler...",
          "owner" => $p11
        )
      );
      
      
      // subpaginas de p11
      $p11->addToSubpages($p111);
      $p11->addToSubpages($p112);
      
      // subpaginas de p1
      $p1->addToSubpages($p11);
      
      // Guarda toda la estructura con esta única línea de código!
      if (!$p1->save())
      {
         Logger::struct( $p1->getErrors(), "Falla test A004.2 1" );
      }
      else
      {
         echo "Guarda Ok";
      }

sábado, 30 de agosto de 2008

ORM: Mapeo de herencia a multiples tablas

Como es sabido, Yupp Framework PHP implementa mapeo de herencia de una sola tabla, pero para la próxima versión (0.1.5) queríamos implementar también la posibilidad de mapear herencia a diferentes tablas, pudiendo así optar por cualquiera de las dos opciones según las necesidades del problema a resolver.

Estudiando el tema, tiene dos puntos bien importantes, la generación del esquema y como son pedidos los datos a la base. En primer lugar, la generación del esquema debe tener reglas que permitan saber cuando una clase se debe mapear a la misma tabla que su superclase o a una tabla distinta, para esto decidimos usar el atributo "withTable" con el que cuentan todas las clases persistentes, de este modo si una subclase define este atributo en un valor distinto al de alguna superclase, automáticamente se toma como que para esa clase (y sus subclases que sigan las mismas reglas) se genere una nueva tabla.

Por otro lado, para obtener datos de la base, como una instancia de una clase puede estar dividida entre varias tablas, debe haber algún mecanismo que permita hacer joins entre las tablas para reconstruir el registro completo, y así levantar toda la información de una instancia de una determinada clase. Para esto se inyecta un nuevo atributo "super_id" que es una foreign key a la tabla que mapee las superclases de la clase que se quiere cargar, y el join se hace por ese atributo con el identificador en la tabla de las superclases. Esto es medio complicado de explicar pero va a ser muy simple de utilizar, más que simple, va a ser transparente al usuario, ya que toda la responsabilidad de cargar la información correctamente corre por parte del framework.

Como se mencionaba antes, esta característica da más flexibilidad a la hora de resolver un problema, por ejemplo en el caso de tener muchas clases que heredan de una sola, en el caso de mapeo de una sola tabla la cantidad de columnas de la misma sería muy alta, y se podría "dividir" el problema mapeando algunas clases en otras tablas y dejando que las clases más utilizadas se sigan mapeando en la misma tabla que la superclase (para que sea más rápida la carga por no tener que hacer joins).

Esperamos tener esta caracteristica funcionando para la semana que viene y con suerte también tendremos la liberación de la próxima versión del framework.

martes, 15 de julio de 2008

Soporte para layouts

El soporte para layouts es una característica bien importante para cualquier framework MVC y Yupp Framework no se podría quedar atrás, así que empecé a buscar información sobre implementación de layouts, patrones de diseño, y frameworks especializados en layouts y templates.

Un sistema de layout ayuda a ahorrar código en las vistas, de forma que varias vistas puedan compartir código común que está en un único archivo externo.

En un momento, luego de leer un rato sobre las posibles formas de implementarlo, más algunas ideas que tenía en mente, probé una pequeña implementación de un sistema de layout, y luego de un par de horas (y para mi sorpresa) lo teníaandando integrado con el framework. En este post mostraré como es que se utilizaría esta implementación de layouts.

La idea principal era no tener que modificar demasiado las vistas de forma que las vistas ya creadas sigan funcionando bien aunque no tengan referencia a un layout. Por lo tanto inventé una tag que sirve para crear la referencia desde una vista:

<layout name="blog" />

Esta tag debe ser incluída luego de <html> y antes de <head>,
para hacer más clara la referencia y más fácil de implementar el procesamiento de esa tag.

El procesamiento debía ser muy rápido y casi no afectar la velocidad de procesamiento actual, de esta forma probé hacer un procesamiento de layout mediante expresiones regulares y mediante operaciones con strings, y la velocidad con las operaciones con strings fue muchísimo mejor que con expresiones regulares, y muchísimo mejor me refiero a varios órdenes por debajo:

velocidad con expresiones regulares promedio: 0.03 ms
velocidad con operaciones de strings promedio: 5.5E-5 ms

El layout tiene la estructura de una vista pero no hace referencia al modelo y tiene dos variables disponibles para poder mostrar el contenido de la vista de la cual es layout, estas son $head y $body, que representan el contenido del <head> y del <body> de la vista.

Este es un ejemplo de un layout:

<html>
<head>
<style type="text/css">
...
</style>
<?php echo $head; ?>

</head>
<body>

<div style="padding:10px; background-color:#6af;" align="right">

<?php echo h('locale_chooser'); ?>
</div>

<div style="padding:10px;">

<?php echo $body; ?>

</div>
</body>
</html>

Por último quien hace el proceso de la vista es una clase llamada LayoutManager que se
encarga de resolver referencias a layouts y mostrar la vista generada. Si la vista no contiene una referencia a un layout, simplemente muestra la vista igual que antes.

Si bien esta solución funciona bien, se puede mejorar en varios aspectos:

  • Chequeos de errores, para hacerlo más robusto.

  • Más flexible, por ejemplo poder acceder a más información de la vista como el título, ahora solo se accede al head y al body.

  • Poder incluir N niveles de layouts en cascada, podría servir para que un layout a su vez pueda tener un layout que
    lo contiene y poder definir distintas secciones de la página que se arma en distintas layouts.
Esta característica estará disponible con la próxima liberación del framework, Yupp Framework PHP v0.1.3.

viernes, 11 de julio de 2008

Característica: devolver directamente el modelo

Una nueva característica que vino con la versión 0.1.2 del framework es la de no necesitar explicitar la vista que se va a utilizar. Por ejemplo con la acción edit, la forma de especificar la vista a utlizar se hace mediante el retorno de llamar al método “render” de YuppController:

class EntradaBlogController extends YuppController {

public function editAction()

{

$id = $this->params['id'];

$obj = EntradaBlog::get( $id );

$this->params['object'] = $obj;

return $this->render("entradaBlog/edit", &$this->params);

}

}

Esta es la única forma de especificar la vista previo a la versión 0.1.2, con Yupp Framework PHP v0.1.2 se puede retornar solo el modelo y la vista se resuelve de forma automática por Yupp Framework:

class EntradaBlogController extends YuppController {

public function editAction()

{

$id = $this->params['id'];

$obj = EntradaBlog::get( $id );

$this->params['object'] = $obj;

return $this->params;

}

}

En este caso, el framework buscará una vista llamada “edit”, igual al nombre de la acción, dentro del directorio de vistas del controller “EntradaBlog”. También se podría retornar NULL o nada en caso de no querer mostrar modelo. En una próxima versión no será necesario tampoco retornar el modelo, ya que como “params” es un campo de “YuppController” puede ser accedido sin necesidad de retornarlo de forma explícita.

La idea fundamental de estas pequeñas características es reducir la cantidad de código que es necesario escribir para implementar cierta funcionalidad y tener varias formas consistentes de hacer lo mismo de forma que cada usuario programe como más le guste y que el framework no restrinja esa libertad.