Yupp Framework PHP

Modelo de datos

Las clases del dominio

Para contextualizar, el "modelo" es la "M" en MVC, o sea en Model-View-Controller, el patrón de diseño que implementa Yupp PHP Framework. Más concretamente, el "modelo" es la capa de acceso a los datos persistentes de nuestra aplicación.

En Yupp, el modelo de datos se define como clases y relaciones, y todas esas clases y relaciones son persistentes, es decir que instancias de estas clases se pueden almacenar en una base de datos de forma automática. Yupp PHP Framework se encarga de todo el trabajo de generar las tablas, guardar los datos y pedir los datos realizando búsquedas sin necesidad de programar consultas SQL, lo que simplifica enormemente las tareas del programador.

Los objetos y relaciones se definen utilizando el paradigma de Programación Orientada a Objetos, como todo en Yupp Framework.

En Programación Orientada a Objetos, los objetos pueden estar relacionados de distintas formas, por ejemplo mediante asociaciones o especialización (herencia). La relación de referencia es básicamente una asociación entre dos clases, y la relación de herencia es cuando una clase hereda de otra.

Definición de clases del modelo

La mejor forma de explicar como se define una clase del modelo es con un ejemplo:

<?php

class Usuario extends PersistentObject {

    function 
__construct$args = array() )
    {
        
$this->withTable "usuarios";

        
$this->addAttribute("name" Datatypes::TEXT);
        
$this->addAttribute("email"Datatypes::TEXT);
        
$this->addAttribute("age",   Datatypes::INT_NUMBER);
        
        
        
parent::__construct$args );
    }
}

?>

Como primer regla, todas las clases del modelo heredan de PersistentObject, que es la clase que implementa toda la lógica necesaria para definición del modelo.

En este caso definimos una clase "Usuario" con tres campos: name (nombre del usuario), email (correo electrónico del usuario) y age (edad del usuario). Para definir estos campos se utiliza el método "addAttribute" de PersistentObject. El segundo argumento de dicho método es el tipo de atributo, este tipo servirá luego para generar el tipo de la columna donde se guarden los valores correspondientes a ese atributo en la tabla en la que se almacenan las instancias de esta clase.

El atributo "withTable" de PersistentObject se utiliza para definir el nombre de la tabla donde las instancias de la clase Usuario van a ser almacenadas. Yupp Framework no tiene restricciones sobre los nombres de las tablas, por ejemplo, no exige nombres definidos en plural, como en otros frameworks donde esta regla es necesaria.

Para los nombres de los atributos de las clases se debe tener especial cuidado en no usar nombres que sean palabras reservadas en el DBMS que estamos utilizando, por ejemplo el atributo "end" será fuente de problemas en PosgreSQL pero no en MySQL. Aquí se encuentran las referencias a palabras reservadas de los DBMS soportados por Yupp Framework:

Generación de tablas

Yupp framework genera la tabla donde se guadarán las instancias de la clase Usuario. El SQL que genera Yupp para la clase definida antes sería el siguiente:
CREATE TABLE usuarios (
   id INT(11) DEFAULT 1 PRIMARY KEY,
   name VARCHAR(30) NULL,
   email TEXT NULL,
   age INT(11) NULL,
   class TEXT NOT NULL,
   deleted BOOL NOT NULL
);

Notar que también se incluyen los atributos id, class y deleted, estos son atributos que Yupp Frameowrk inyecta a todas sus clases del dominio. El atributo id es el identificador de la instancia en la base de datos. El atributo class indica la clase de la instancia, en este caso class sería siempre "Usuario". Y por último el atributo deleted es utilizado para realizar borrados lógicos.

En la última línea del constructor de Usuario, es necesario llamar al construcor de la superclase, en este caso PersistentObject, para que se haga el trabajo necesario de inicialización del objeto. Esto inyecta los atributos mencionados antes.

Introducción a relaciones entre clases

Yupp soporta relaciones de distinta cardinalidad entre clases del modelo de datos. La cardinalidad indica cuantas instancias de la clase relacionada se pueden tener asociadas.

Las tres posibilidades de cardinalidad de las relaciones son: 1-1, 1-N y N-N. Y las relaciones pueden ser unidireccionales o bidireccionales, en la siguiente imagen se muestran todas las opciones que soporta Yupp PHP Framework para las reslaciones entre clases:

Yupp PHP Framework class model link support

Nota: Yupp PHP Framework soporta salvar un modelo en cascada, esto quiere decir que si se salva una sola instancia de una clase, se salvan también las instancias de las clases asociadas. Para poder hacer esto, Yupp necesita saber cual es la clase "fuerte" en la relación. Yupp posee una forma de declarar explícitamente cual es la parte fuerte de la relación, esto es a través del atributo "belongsTo" en las clases del modelo, que indica que la clase pertenece a otra mediante una asociación, y esta última es la parte fuerte de esa asociación. No siempre es necesario declarar ese atributo, en los casos que no se declara Yupp Framework sigue ciertas reglas para determinar la parte fuerte de la relació, aquí se listan todas las reglas:

  1. Si la relacion es A (1) -> (1) B, entonces B belongsTo A.
  2. Si la relacion es A (1) <-> (1) B, se necesita belongsTo para saber cual es el lado fuerte.
  3. Si la relacion es A (1) -> (*) B, entonces B belongsTo A.
  4. Si la relacion es A (1) <-> (*), B entonces B belongsTo A.
  5. Si la relacion es A (*) -> (*) B, entonces B belongsTo A.
  6. Si la relacion es A (*) <-> (*) B, se necesita belongsTo para saber cual es el lado fuerte.

La característica importante del modelo es que es persistente, y a través del componente de ORM de Yupp (YORM), se pueden persistir y obtener datos de la base de datos sin necesidad de escribir SQL ni manejar la estructura de la base de datos (generar la estructura, obtener datos, hacer JOINs, etc).

Definiendo relaciones:

Un usuario tiene un login donde se almacena un nombre de usuario y una clave que el usuario utiliza para ingresar a nuestro sistema. Este ejemplo presenta una forma unidireccional de generar esta relación, desde el "Login" al "Usuario":

<?php

class Login extends PersistentObject {

    function 
__construct$args = array() )
    {
        
$this->withTable "login";

        
$this->addAttribute("username"Datatypes::TEXT);
        
$this->addAttribute("password",  Datatypes::TEXT);
        
        
$this->addHasOne("user"Usuario);

        
parent::__construct$args );
    }
}

?>


Con el método addHasOne, se especifica una relación 1-1 unidireccional desde Login a Usuario, mediante un atributo usuario en la clase Login.

Un ejemplo de como se utiliza el modelo es el siguiente:

<?php

$usuario 
= new Usuario( array("name" =>"Pablo",
                              
"email" =>"a@b.com",
                              
"age" =>26) );
$usuario->save();

$login = new Login( array("username"=>"unusuario""password"=>"abcd1234" );
$login->setUser$usuario );
$login->save();

?>

Yupp también soporta relaciones múltiples, por ejemplo, si el usuario escribe entradas en un blog, el usuario tiene varias entradas:

<?php

class Entrada extends PersistentObject {

   function 
__construct$args = array() )
   {
      
$this->withTable "entradas";

      
$this->addAttribute("title"Datatypes::TEXT);
      
$this->addAttribute("text",  Datatypes::TEXT);
        
      
parent::__construct$args );
   }
}

?>

Ahora agregamos la nueva relación 1-N de Usuario a Entrada:

<?php

class Usuario extends PersistentObject {

   function 
__construct$args = array() )
   {
      
$this->withTable "usuarios";

      
$this->addAttribute("name"Datatypes::TEXT);
      
$this->addAttribute("email",  Datatypes::TEXT);
      
$this->addAttribute("age",   Datatypes::INT_NUMBER);
        
      
$this->addHasMany("entradas"Entrada);
        
      
parent::__construct$args );
   }
}

?>

Como podemos ver, este es un caso de relaciones 1-N unidireccionales, por que se define la relación de Usuario a Entrada pero no de Entrada a Usuario. En la mayoría de los casos no será necesario definir relaciones bidireccionales, pero como vimos antes, Yupp Framework igualmente las soporta.

Un ejemplo de uso de la relación 1-N:

<?php

$usuario 
Usuario::get$id );
$entrada1 = new Entrada( array("title"=>"Un titulo",
                               
"text" =>"Lorem ipsum dolor sit amet...") );

$entrada2 = new Entrada( array("title"=>"Otro titulo",
                               
"text" =>"Lorem ipsum dolor sit amet...") );

$usuario->addToEntradas$entrada1 );
$usuario->addToEntradas$entrada2 );

$usuario->save();

?>

Más ejemplos de uso de clases del modelo:

  1. Crear un nuevo usuario y guardarlo en la base de datos:

    <?php

       $obj 
    = new Usuario();
       $obj->setProperties( array("name" => "Pablo"
                                  
    "email" => "a@b.com",
                                  
    "age" => 26) );
       $obj->save();

    ?>

  2. Pedir todos los usuarios guardados en la base y mostrar sus nombres:

    01  <?php 02   03  $params = new ArrayObject( array("offset" => 0"max" => 10) ); 04  $list = Usuario::listAll$params ); 05   06  foreach ( $list as $usuario ) 07  { 8     echo $usuario->getNombre() . "<br/>"; 09  } 10   11  ?>
  3. Eliminar un usuario:

    <?php

    $obj 
    Usuario::get$id );
    $obj->delete();

    ?>
Yupp por defecto inyecta 3 atributos de forma implícita a cada clase, el atributo class tiene el nombre de la clase, el atributo deleted dice si el objeto está eliminado o no, sirve para eliminación lógica (Yupp por defecto utiliza eliminación lógica en lugar de física, o sea, eliminar el registro físicamente de la tabla de la base de datos), también inyecta un atributo id que guarda el identificador asignado al objeto cuando se guarda en la base de datos.

Por consultas o comentarios ir al grupo:
Grupos de Google
Suscribirte a Yupp Framework PHP
Correo electrónico:
Consultar este grupo