Mikel

Mikel

(38 comentarios, 115 entradas)

Este usuario no ha compartido ninguna información de perfil

Web: http://interadictos.es

Entradas de Mikel

Cassandra y PHP para desarrolladores SQL: Instalación

0

La base de datos No-SQL Cassandra fue creada por Facebook a causa de la necesidad de disponer de una base de datos distribuida de alto rendimiento, flexible, tolerante a fallos, escalable y que fuese capaz de procesar grandes cantidades de datos, más tarde fue liberada bajo licencia Apache y actualmente es utilizada principalmente por empresas de internet con proyectos con un alto uso de base de datos como Twitter.

En esta serie de artículos iré desgranando la instalación, funcionamiento y desarrollo de aplicaciones en PHP con Cassandra, comparando las sentencias utilizadas para insertar, actualizar, etc de SQL con los métodos a utilizar en Cassandra. Por desgracia al ser algo completamente distinto a cualquier base de datos SQL tendré que añadir algo de teoría, pero intentaré que os resulte lo más ameno posible.

Al toro.

 

 

REQUISITOS

Para la realización de esta guía se utilizará Debian Squeeze como sistema operativo. En algunos de los links que dejo como bibliografía al final del artículo existen ejemplos para realizar la instalación en otros sistemas operativos, principalmente CentOS.

Doy por hecho que ya se dispone de un servidor web Apache con PHP instalado en la máquina de testeo que se esté usando. Las aplicaciones que se van a instalar han sido probadas en una máquina virtual Debian utilizando como aplicación de virtualización, VirtualBox instalado en un host Windows XP SP3.

En un servidor de producción recomiendo que tenga bastante RAM (por encima de 1GB, ya veremos más adelante el porqué. En la máquina virtual que uso de testeo dispone de 700 MB y funciona bien, pero en producción no es lo recomendable).

Instalaremos la base de datos Cassandra, el protocolo para conectar con ella y que nos generará el módulo para poder trabajar desde PHP, y PHPCassa que será la abstracción de la base de datos donde tenemos los métodos básicos para trabajar con Cassandra: insertar, actualizar, borrar, crear, etc.

 

PREPARANDO EL SISTEMA

Antes de empezar a instalar debemos actualizar el sistema operativos de la forma habitual:

apt-get update
apt-get upgrade

Una vez actualizado el sistema empezamos a instalar.

 

INSTALANDO CASSANDRA

Lo primero que necesitamos hacer para instalar Cassandra es editar los repositorios de Debian:

  1. nano /etc/apt/sources.list

 

Una vez que se abra el editor añadimos las siguientes lineas:

deb http://www.apache.org/dist/cassandra/debian/ 08x main
deb-src http://www.apache.org/dist/cassandra/debian/ 08x main

Como podrás observar después de la ruta del repositorio se ha añadido “08x” estoy indica el número de versión a obtener, en este caso es la versión actual de cassandra al crear este post. No se indica el número de parche, es decir, actualmente se puede descargar Cassandra 8.4, el “.4″ lo obviamos a la hora de los repositorios.

Si dentro de unos meses sale la versión “9.0″ solo tendrás que cambiar el ocho por el nueve.
Volvemos a consola y actualizamos los repositorios.

apt-get update

Nos dará un error en las claves gpg. Procedemos a actualizarlas con las siguientes instrucciones:

  1. gpg --keyserver pgp.mit.edu --recv-keys F758CE318D77295D
  2. gpg --export --armor F758CE318D77295D | sudo apt-key add -

Ojo con el guión del final, hay que añadirlo sino dará error.

Con el paquete 0.7.5 nos da otro error de clave gpg así que también instalamos esta de la misma manera:

gpg --keyserver pgp.mit.edu --recv-keys 2B5C1B00
gpg --export --armor 2B5C1B00 | sudo apt-key add -

Verificamos que tenemos el sistema actualizado.

Actualizamos todos los paquetes que aparezcan.

Procedemos a instalar el paquete de la base de datos NoSQL Cassandra:

  1. apt-get install cassandra

Cassandra necesita a Java para funcionar para ello, una vez instalado Cassandra instalaremos el paquete sun-java6-jdk de la siguiente manera:

  1. apt-get install sun-java6-jdk

En el caso de que no encuentre el paquete verificar que los repositorios de Debian son correctos. Verifica la versión de Java con:

Debería aparecer algo así:

java version "1.6.0_20"
Java(TM) SE Runtime Environment (build 1.6.0_20-b02)
Java HotSpot(TM) Client VM (build 16.3-b01, mixed mode, sharing)

Se recomienda usar la versión de Java de Sun (Sun JDK) en vez de Open JDK debido a un bug encontrado en el mismo.

Si os muestra algo distinto a esto, escribid el siguiente comando:

update-alternatives --config javac

Os mostrará un listado con los diferentes paquetes instalados en el sistema que pueden ser utilizados para trabajar con Java. Nosotros usaremos el paquete de Sun, así que pulsa el número del paquete para que Debian lo utilice.

Por último, ejecutamos el siguiente comando para construir las dependencias:

dpkg-buildpackage -uc -us

Una vez instalado procedemos a realizar la configuración de Cassandra:

Creamos varias carpetas necesarias si no han sido creadas automáticamente:

  1. mkdir -p {callouts,commitlog,data,saved,caches,staging}
  2. mkdir /var/log/cassandra

Damos permisos a esta carpeta:

chmod -R 777 /var/log/cassandra/

Creamos el archivo /var/log/cassandra/system.log y le damos permisos:

chmod -R 777 /var/log/cassandra/system.log

 

INSTALANDO THRIFT Y LA EXTENSIÓN PARA PHP

Thrift es tan solo el protocolo de conexión para poder utilizar Cassandra. Aunque en la extensión para PHP existen métodos para poder trabajar con cassandra, requieren bastante código por eso utilizaremos PHPCassa como abstracción de la base de datos.

Primero descargamos Thrift desde su web: http://thrift.apache.org/download/ y descomprimimos

  1. tar -xzvf thrift-0.7.0.tar.gz

Nos colocamos dentro de la carpeta de Thrift.

Antes de hacer nada ahí instalamos algunos paquetes que nos serán necesarios:

  1. apt-get install libboost-dev automake libtool flex bison pkg-config g++

Una vez instalados esos paquetes configuramos y construimos Thrift:

  1. ./configure
  2. make

Construimos la interfaz de PHP Thrift para Cassandra:

  1. ./compiler/cpp/thrift -gen php ../ruta-a-cassandra/interface/cassandra.thrift

Copiamos archivos necesario para que PHPCassa funcione:

  1. mkdir -p /usr/share/php/Thrift
  2. cp -R gen-php/ /usr/share/php/Thrift/packages/
  3. cp -R lib/php/src/* /usr/share/php/Thrift/

Cambiamos al directorio del protocolo de Thrif: ruta-a-thrift/lib/php/src/ext/thrift_protocol.

Instalamos el paquete para construir las extensiones de PHP:

  1. apt-get install php5-dev

Construimos la extensión:

  1. phpize
  2. ./configure --enable-thrift_protocol
  3. make

Copiamos la extensión a la siguiente carpeta (cuidado: dependiendo del sistema el nombre de la carpeta de destino puede variar):

  1. cp modules/thrift_protocol.so /usr/lib/php5/20060613/

Habilitamos el módulo creando el archivo /etc/php5/conf.d/thrift_protocol.ini con el siguiente texto:

  1. extension=thrift_protocol.so

Comprobamos la instalación:

  1. php -i | grep -v "PWD" | grep "thrift_protocol"

Si todo ha ido bien, reiniciamos Apache:

  1. /etc/init.d/apache2 restart

Iniciamos Cassandra:

  1. /opt/cassandra/bin/cassandra -f

Y probamos la consola para comprobar que todo ha ido correctamente:

  1. /opt/cassandra/bin/cassandra-cli -host localhost -port 9160

Debería indicarte algo así:

  1. Connected to: "Test Cluster" on localhost/9160
  2. Welcome to cassandra CLI.

 

INSTALANDO PHPCassa

Bajamos PHPCassa desde github: https://github.com/thobbs/phpcassa

Al descomprimir verás cuatro archivos PHP, copia esos archivos a una carpeta del proyecto en el que estés trabajando.

Abre el archivo “connection.php”, la primera línea será una variable global: $GLOBALS['THRIFT_ROOT'], modifica su valor con la ruta hacia los archivos Thrift que copiamos con anterioridad. En mi caso se quedaría así:

  1. <?php
  2. $GLOBALS['THRIFT_ROOT'] = '/usr/share/php/Thrift/';

Con esto finalizamos la instalación de Cassandra para que pueda ser utilizada por PHP.

Os dejo algunas páginas de interés:
CASSANDRA
http://cassandra.apache.org/
http://cassandra.apache.org/download/
http://wiki.apache.org/cassandra/
http://www.apache.org/dist/cassandra/debian/dists/
http://wiki.apache.org/cassandra/DebianPackaging
http://wiki.apache.org/cassandra/CloudConfig
http://cassandra-user-incubator-apache-org.3065146.n2.nabble.com/Cannot-connect-to-Cassandra-td6463518.html
http://sentidoweb.com/2010/03/18/instalar-cassandra-en-ubuntu.php
http://gettingstartedwithcassandra.blogspot.com/2011/06/exception-connecting-to-localhost9160.html
https://wiki.fourkitchens.com/display/PF/Using+Cassandra+with+PHP
http://es.paperblog.com/instalar-cassandra-en-ubuntu-78327/
http://www.unixmen.com/linux-tutorials/960-install-nosql-cassandra-db-in-ubuntu-via-ppa-repository
http://wiki.apache.org/cassandra/ClientOptions

THRIFT
http://thrift.apache.org/

 



PHPCassa
https://github.com/thobbs/phpcassa
http://groups.google.com/group/phpcassa?pli=1

logo unidadesdemedida.com

unidadesdemedida.com: ¿Cuántas piscinas olímpicas es un campo de fútbol?

0

Desde hace bastante tiempo, los medios de comunicación han utilizado unidades de medida diferentes a las del Sistema Internacional (SI) para medir las nuevas infraestructuras o vehículos que el ser humano crea. Últimamente se ve incluso la utilización de unidades de medida especiales para el coste de los fichajes de deportistas, principalmente en el fútbol.

 

Para aquellos que desean saber cuántas piscinas olímpicas es un campo de fútbol entre otras unidades, no os perdáis mi nuevo proyecto que espero os guste aunque aun le quedan muchas unidades que añadir.

 

Cualquier sugerencia o crítica será bienvenida.

 

Link: http://www.unidadesdemedida.com

Symfony: Enrutamiento (II)

0

Por defecto Symfony no muestra el archivo que hace de controlador (index.php, frontend_dev.php, etc) para cambiarlo vamos al archivo settings.yml aquí podemos indicar que no se muestre el nombre del controlador de la siguiente manera:

  1. prod:
  2. .settings:
  3. no_script_name: off

 

Hiperenlaces, botones y formularios

  1. / Opciones adicionales como array asociativo
  2. <?php echo link_to('Mi artículo', 'articulo/ver?titulo=Economia_en_Francia', array(
  3. 'class' => 'miclasecss',
  4. 'target' => '_blank'
  5. )) ?>
  6.  
  7. // Opciones adicionales como cadena de texto (producen el mismo resultado)
  8. <?php echo link_to('Mi artículo', 'articulo/ver?titulo=Economia_en_Francia','class=miclasecss target=_blank') ?>
  9. => <a href="/url/con/enrutamiento/a/Economia_en_Francia" class="miclasecss" target="_blank">Mi artículo</a>
  1. // URI interna
  2. <?php echo link_to('Mi artículo', 'articulo/ver?titulo=Economia_en_Francia') ?>
  3. => <a href="/url/con/enrutamiento/a/Economia_en_Francia">Mi artículo</a>
  4.  
  5. // URI interna con parámetros dinámicos
  6. <?php echo link_to('Mi artículo', 'articulo/ver?titulo='.$articulo->getTitulo()) ?>
  7.  
  8. // URI interna con anclas (enlaces a secciones internas de la página)
  9. <?php echo link_to('Mi artículo', 'articulo/ver?titulo=Economia_en_Francia#seccion1') ?>
  10. => <a href="/url/con/enrutamiento/a/Economia_en_Francia#seccion1">Mi artículo</a>
  11.  
  12. // URL absolutas
  13. <?php echo link_to('Mi artículo', 'http://www.ejemplo.com/cualquierpagina.html') ?>
  14. => <a href="http://www.ejemplo.com/cualquierpagina.html">Mi artículo</a>
  1. // Enlace simple de texto
  2. <?php echo link_to('Mi artículo', 'articulo/ver?titulo=Economia_en_Francia') ?>
  3. => <a href="/url/con/enrutamiento/a/Economia_en_Francia">Mi artículo</a>
  4.  
  5. // Enlace en una imagen
  6. <?php echo link_to(image_tag('ver.gif'), 'articulo/ver?titulo=Economia_en_Francia') ?>
  7. => <a href="/url/con/enrutamiento/a/Economia_en_Francia"><img src="/images/ver.gif" /></a>
  8.  
  9. // Boton
  10. <?php echo button_to('Mi artículo', 'articulo/ver?titulo=Economia_en_Francia') ?>
  11. => <input value="Mi artículo" type="button" onclick="document.location.href='/url/con/enrutamiento/a/Economia_en_Francia';" />
  12.  
  13. // Formulario
  14. <?php echo form_tag('articulo/ver?titulo=Economia_en_Francia') ?>
  15. => <form method="post" action="/url/con/enrutamiento/a/Economia_en_Francia" />
  1. <?php echo link_to('Borrar elemento', 'item/borrar?id=123', 'confirm=¿Estás seguro?') ?>
  2. => <a onclick="return confirm('¿Estás seguro?');"
  3. href="/url/con/enrutamiento/a/borrar/123.html">Borrar elemento</a>
  4.  
  5. <?php echo link_to('Añadir al carrito', 'carritoCompra/anadir?id=100', 'popup=true') ?>
  6. => <a onclick="window.open(this.href);return false;"
  7. href="/url/con/enrutamiento/a/carritoCompra/anadir/id/100.html">Añadir al carrito</a>
  8.  
  9. <?php echo link_to('Añadir al carrito', 'carritoCompra/anadir?id=100', array(
  10. 'popup' => array('popupWindow', 'width=310,height=400,left=320,top=0')
  11. )) ?>
  12. => <a onclick="window.open(this.href,'popupWindow','width=310,height=400,left=320,top=0');return false;"
  13. href="/url/con/enrutamiento/a/carritoCompra/anadir/id/100.html">Añadir al carrito</a>

 

Symfony: El enrutamiento (I)

0

Continuo con el libro de Symfony 1.4 en esta ocasión toca el enrutamiento.

Normalmente las urls que escribimos son así:

http://www.ejemplo.com/web/galeria/album.php?nombre=mis%20vacaciones

http://www.ejemplo.com/web/weblog/publico/post/listado.php

http://www.ejemplo.com/web/general/contenido/pagina.php?nombre=sobre%20nosotros

Y deberían ser así:

http://www.ejemplo.com/articulos/economia/2006/sectores-actividad.html

Principalmente porque son mucho más legibles para los usuarios y buscadores, y además evitamos mostrar información a un posible atacante.

El sistema de enrutamiento utiliza un archivo de configuración especial, llamado routing.yml, en el que se pueden definir las reglas de enrutamiento.

  1. articulo_segun_titulo:
  2. url: articulos/:tema/:ano/:titulo.html
  3. param: { module: articulo, action: permalink }

Todas las peticiones realizadas a una aplicación Symfony son analizadas en primer lugar por el sistema de enrutamiento (que es muy sencillo porque todas las peticiones se gestionan mediante un único controlador frontal). El sistema de enrutamiento busca coincidencias entre la URL de la petición y los patrones definidos en las reglas de enrutamiento. Si se produce una coincidencia, las partes del patrón que tienen nombre se transforman en parámetros de la petición y se juntan a los parámetros definidos en la clave param:.

Después, la petición se pasa a la acción permalink del módulo articulo, que dispone de toda la información necesaria en los parámetros de la petición para obtener el artículo solicitado.

El mecanismo de enrutamiento también funciona en la otra dirección. Para mostrar las URL en los enlaces de una aplicación, se debe proporcionar al sistema de enrutamiento la información necesaria para determinar la regla que se debe aplicar a cada enlace. Además, no se deben escribir los enlaces directamente con etiquetas <a> (ya que de esta forma no se estaría utilizando el sistema de enrutamiento) sino con un helper especial:

  1. // El helper url_for() transforma una URI interna en una URL externa
  2. <a href="<?php echo url_for('articulo/permalink?tema=economia&ano=2006&titulo=sectores-actividad') ?>">pincha aquí</a>
  3.  
  4. // El helper reconoce que la URI cumple con la regla articulo_segun_titulo
  5. // El sistema de enrutamiento crea una URL externa a partir de el
  6. => <a href="http://www.ejemplo.com/articulos/economia/2006/sectores-actividad.html">pincha aquí</a>
  7.  
  8. // El helper link_to() muestra directamente un enlace
  9. // y evita tener que mezclar PHP y HTML
  10. <?php echo link_to(
  11. 'pincha aqui',
  12. 'articulo/permalink?tema=economia&ano=2006&titulo=sectores-actividad'
  13. ) ?>
  14.  
  15. // Internamente link_to() llama a url_for(), por lo que el resultado es el mismo
  16. => <a href="http://www.ejemplo.com/articulos/economia/2006/sectores-actividad.html">pincha aquí</a>

Sintel | Corto de animación 3D hecho en Blender

0
Imagen de previsualización de YouTube

Symfony: El modelo (III)

0

CONEXIONES A LA BASE DE DATOS

  1. > php symfony configure:database "mysql://login:password@localhost/blog"
  1. > php symfony --env=prod configure:database "mysql://login:password@localhost/blog"
  1. > php symfony --app=frontend configure:database "mysql://login:password@localhost/blog"

 

  1. > php symfony --name=otraconexion configure:database "mysql://login:password@localhost/blog"

 

Las opciones de conexión con la base de datos también se pueden establecer manualmente en el archivo databases.yml que se encuentra en el directorio config/.

 

  1. all:
  2. propel:
  3. class: sfPropelDatabase
  4. param:
  5. dsn: mysql://login:password@localhost/blog
  1. prod:
  2. propel:
  3. param:
  4. hostspec: mi_servidor_datos
  5. usuarioname: mi_nombre_usuario
  6. password: xxxxxxxxxx
  7.  
  8. all:
  9. propel:
  10. class: sfPropelDatabase
  11. param:
  12. phptype: mysql # fabricante de la base de datos
  13. hostspec: localhost
  14. database: blog
  15. usuarioname: login
  16. password: passwd
  17. port: 80
  18. encoding: utf8 # Codificación utilizada para crear la tabla
  19. persistent: true # Utilizar conexiones persistentes

Los valores permitidos para el parámetro phptype corresponden a los tipos de bases de datos soportados por PDO:

  • mysql
  • mssql
  • pgsql
  • sqlite
  • oracle

Si se utiliza una base de datos de tipo SQLite, el parámetro hostspec debe indicar la ruta al archivo de base de datos.

  1. all:
  2. propel:
  3. class: sfPropelDatabase
  4. param:
  5. phptype: sqlite
  6. database: %SF_DATA_DIR%/blog.db

 

EXTENDER EL MODELO

Los métodos del modelo que se generan automáticamente están muy bien, pero no siempre son suficientes. Si se incluye lógica de negocio propia, es necesario extender el modelo añadiendo nuevos métodos o redefiniendo algunos de los existentes.

 

AÑADIR NUEVOS MÉTODOS

Los nuevos métodos se pueden añadir en las clases vacías del modelo que se generan en el directorio lib/model/. Se emplea $this para invocar a los métodos del objeto actual y self:: para invocar a los métodos estáticos de la clase actual. No se debe olvidar que las clases personalizadas heredan los métodos de las clases Base del directorio lib/model/om/.

  1. <?
  2.  
  3. class Articulo extends BaseArticulo
  4. {
  5. public function __toString()
  6. {
  7. return $this->getTitulo(); // getTitulo() se hereda de BaseArticulo
  8. }
  9. }

También se pueden extender las clases peer, como por ejemplo para obtener todos los artículos ordenados por fecha de creación:

  1. <?
  2.  
  3. class ArticuloPeer extends BaseArticuloPeer
  4. {
  5. public static function getTodosOrdenadosPorFecha()
  6. {
  7. $c = new Criteria();
  8. $c->addAscendingOrderByColumn(self::CREATED_AT);
  9. return self::doSelect($c);
  10. }
  11. }

 

  1. <?
  2.  
  3. foreach (ArticuloPeer::getTodosOrdenadosPorFecha() as $articulo)
  4. {
  5. echo $articulo; // Se llama al método mágico __toString()
  6. }

 

REDEFINIR MÉTODOS EXISTENTES

Si alguno de los métodos generados automáticamente en las clases Base no satisfacen las necesidades de la aplicación, se pueden redefinir en las clases personalizadas. Solamente es necesario mantener el mismo número de argumentos para cada método.

Por ejemplo, el método $articulo->getComentarios() devuelve un array de objetos Comentario, sin ningún tipo de ordenamiento. Si se necesitan los resultados ordenados por fecha de creación siendo el primero el comentario más reciente, se puede redefinir el método getComentarios(). Como el método getComentarios() original (guardado en lib/model/om/BaseArticulo.php) requiere como argumentos un objeto de tipo Criteria y una conexión, la nueva función debe contener esos mismos parámetros.

  1. <?
  2.  
  3. public function getComentarios($criteria = null, $con = null)
  4. {
  5. if (is_null($criteria))
  6. {
  7. $criteria = new Criteria();
  8. }
  9. else
  10. {
  11. // Los objetos se pasan por referencia en PHP5, por lo que se debe clonar
  12. // el objeto original para no modificarlo
  13. $criteria = clone $criteria;
  14. }
  15. $criteria->addDescendingOrderByColumn(ComentarioPeer::CREATED_AT);
  16.  
  17. return parent::getComentarios($criteria, $con);
  18. }

El método personalizado acaba llamando a su método padre en la clase Base, lo que se considera una buena práctica. No obstante, es posible saltarse completamente la clase Base y devolver el resultado directamente.

 

USO DE COMPORTAMIENTOS EN EL MODELO

Algunas de las modificaciones que se realizan en el modelo son genéricas y por tanto se pueden reutilizar. Por ejemplo, los métodos que hacen que un objeto del modelo sea reordenable o un bloqueo de tipo optimistic en la base de datos para evitar conflictos cuando se guardan de forma concurrente los objetos se pueden considerar extensiones genéricas que se pueden añadir a muchas clases.

Symfony encapsula estas extensiones en “comportamientos” (del inglés behaviors). Los comportamientos son clases externas que proporcionan métodos extras a las clases del modelo. Las clases del modelo están definidas de forma que se puedan enganchar estas clases externas y Symfony extiende las clases del modelo mediante sfMixer.

Para habilitar los comportamientos en las clases del modelo, se debe modificar una opción del archivo config/propel.ini:

propel.builder.AddBehaviors = true // El valor por defecto es false

Symfony no incluye por defecto ningún comportamiento, pero se pueden instalar mediante plugins. Una vez que el plugin se ha instalado, se puede asignar un comportamiento a una clase mediante una sola línea de código. Si por ejemplo se ha instalado el plugin sfPropelParanoidBehaviorPlugin en la aplicación, se puede extender la clase Articulo con este comportamiento añadiendo la siguiente línea de código al final del archivo Articulo.class.php:

  1. <?
  2.  
  3. sfPropelBehavior::add('Articulo', array(
  4. 'paranoid' => array('column' => 'deleted_at')
  5. ));

 

Después de volver a generar el modelo, los objetos de tipo Articulo que se borren permanecerán en la base de datos, aunque será invisibles a las consultas que hacen uso de los métodos del ORM, a no ser que se deshabilite temporalmente el comportamiento mediante sfPropelParanoidBehavior::disable().

Desde la versión 1.1 de Symfony también es posible declarar los comportamientos directamente en el archivo schema.yml, incluyéndolos bajo la clave _behaviors.

La lista de plugins de Symfony disponible en el wiki incluye numerosos comportamientos http://trac.symfony-project.org/wiki/SymfonyPlugins#Behaviors. Cada comportamiento tiene su propia documentación y su propia guía de instalación.

 

SINTAXIS EXTENDIDA DEL ESQUEMA

Atributos

Se pueden definir atributos específicos para las conexiones y las tablas. Estas opciones se establecen bajo la clave _attributes.

  1. propel:
  2. _attributes: { noXsd: false, defaultIdMethod: none, package: lib.model }
  3. blog_articulo:
  4. _attributes: { phpName: Articulo }

Si se quiere validar el esquema antes de que se genere el código asociado, se debe desactivar en la conexión el atributo noXSD. La conexión también permite que se le indique el atributo defaultIdMethod. Si no se indica, se utilizará el método nativo de generación de IDs –por ejemplo, autoincrement en MySQL o sequences en PostgreSQL. El otro valor permitido es none.

El atributo package es como un namespace; indica la ruta donde se guardan las clases generadas automáticamente. Su valor por defecto es lib/model/, pero se puede modificar para organizar el modelo en una estructura de subpaquetes. Si por ejemplo no se quieren mezclar en el mismo directorio las clases del núcleo de la aplicación con las clases de un sistema de estadísticas, se pueden definir dos esquemas diferentes con los paquetes lib.model.business y lib.model.stats.

Ya se ha visto el atributo de tabla phpName, que se utiliza para establecer el nombre de la clase generada automáticamente para manejar cada tabla de la base de datos.

Las tablas que guardan contenidos adaptados para diferentes idiomas (es decir, varias versiones del mismo contenido en una tabla relacionada, para conseguir la internacionalización) también pueden definir dos atributos adicionales.

  1. propel:
  2. blog_articulo:
  3. _attributes: { isI18N: true, i18nTable: db_group_i18n }

 

DETALLE DE LAS COLUMNAS

La sintaxis básica ofrece dos posibilidades: dejar que Symfony deduzca las características de una columna a partir de su nombre (indicando un valor vacío para esa columna) o definir el tipo de columna con uno de los tipos predefinidos.

  1. propel:
  2. blog_articulo:
  3. id: # Symfony se encarga de esta columna
  4. titulo: varchar(50) # Definir el tipo explícitamente

Se pueden definir muchos más aspectos de cada columna. Si se definen, se utiliza un array asociativo para indicar las opciones de la columna.

  1. propel:
  2. blog_articulo:
  3. id: { type: integer, required: true, primaryKey: true, autoIncrement: true }
  4. name: { type: varchar(50), default: foobar, index: true }
  5. group_id: { type: integer, foreignTable: db_group, foreignReference: id, onDelete: cascade }

Los parámetros de las columnas son los siguientes:

  • type: Tipo de columna. Se puede elegir entre boolean, tinyint, smallint, integer, bigint, double, float, real, decimal, char, varchar(tamano), longvarchar, date, time, timestamp, bu_date, bu_timestamp, blob y clob
  • required: valor booleano. Si vale true la columna debe tener obligatoriamente un valor.
  • default: el valor por defecto.
  • primaryKey: valor booleano. Si vale true indica que es una clave primaria.
  • autoIncrement: valor booleano. Si se indica true para las columnas de tipo integer, su valor se auto-incrementará.
  • sequence: el nombre de la secuencia para las bases de datos que utilizan secuencias para las columnas autoIncrement (por ejemplo PostgreSQL y Oracle).
  • index: valor booleano. Si vale true, se construye un índice simple; si vale unique se construye un índice único para la columna.
  • foreignTable: el nombre de una tabla, se utiliza para crear una clave externa a otra tabla.
  • foreignReference: el nombre de la columna relacionada si las claves externas se definen mediante foreignTable.
  • onDelete: determina la acción que se ejecuta cuando se borra un registro en una tabla relacionada. Si su valor es setnull, la columna de la clave externa se establece a null. Si su valor es cascade, se borra el registro relacionado. Si el sistema gestor de bases de datos no soporta este comportamiento, el ORM lo emula. Esta opción solo tiene sentido para las columnas que definen una foreignTable y una foreignReference.
  • isCulture: valor booleano. Su valor es true para las columnas de tipo culture en las tablas de contenidos adaptados a otros idiomas.

 

CLAVES EXTERNAS

Además de los atributos de columna foreignTable y foreignReference, es posible añadir claves externas bajo la clave _foreignKeys: de cada tabla.

  1. propel:
  2. blog_articulo:
  3. id:
  4. titulo: varchar(50)
  5. usuario_id: { type: integer }
  6. _foreignKeys:
  7. -
  8. foreignTable: blog_usuario
  9. onDelete: cascade
  10. references:
  11. - { local: usuario_id, foreign: id }

La sintaxis alternativa es muy útil para las claves externas múltiples y para indicar un nombre a cada clave externa.

  1. _foreignKeys:
  2. mi_clave_externa:
  3. foreignTable: db_usuario
  4. onDelete: cascade
  5. references:
  6. - { local: usuario_id, foreign: id }
  7. - { local: post_id, foreign: id }

 

INDICES

Además del atributo de columna index, es posible añadir claves índices bajo la clave _indexes: de cada tabla. Si se quieren crean índices únicos, se debe utilizar la clave _uniques:. En las columnas que requieren un tamaño, por ejemplo por ser columnas de texto, el tamaño del índice se indica entre paréntesis, de la misma forma que se indica el tamaño de cualquier columna.

  1. propel:
  2. blog_articulo:
  3. id:
  4. titulo: varchar(50)
  5. created_at:
  6. _indexes:
  7. mi_indice: [titulo(10), usuario_id]
  8. _uniques:
  9. mi_otro_indice: [created_at]

 

COLUMNAS VACÍAS

Cuando Symfony se encuentra con una columna sin ningún valor, utiliza algo de magia para determinar su valor.

  1. // Las columnas vacías llamadas "id" se consideran claves primarias
  2. id: { type: integer, required: true, primaryKey: true, autoIncrement: true }
  3.  
  4. // Las columnas vacías llamadas "XXX_id" se consideran claves externas
  5. loquesea_id: { type: integer, foreignTable: db_loquesea, foreignReference: id }
  6.  
  7. // Las columnas vacías llamadas created_at, updated at, created_on y updated_on
  8. // se consideran fechas y automáticamente se les asigna el tipo "timestamp"
  9. created_at: { type: timestamp }
  10. updated_at: { type: timestamp }

Para las claves externas, Symfony busca una tabla cuyo phpName sea igual al principio del nombre de la columna; si se encuentra, se utiliza ese nombre de tabla como foreignTable.

 

TABLAS I18N

Symfony permite internacionalizar los contenidos mediante tablas relacionadas. De esta forma, cuando se dispone de contenido que debe ser internacionalizado, se guarda en 2 tablas distintas: una contiene las columnas invariantes y otra las columnas que permiten la internacionalización.

Todo lo anterior se considera de forma implícita cuando en el archivo schema.yml se dispone de una tabla con el nombre cualquiernombre_i18n.

  1. propel:
  2. db_group:
  3. id:
  4. created_at:
  5.  
  6. db_group_i18n:
  7. name: varchar(50)
  1. propel:
  2. db_group:
  3. _attributes: { isI18N: true, i18nTable: db_group_i18n }
  4. id:
  5. created_at:
  6.  
  7. db_group_i18n:
  8. id: { type: integer, required: true, primaryKey: true, foreignTable: db_group, foreignReference: id, onDelete: cascade }
  9. culture: { isCulture: true, type: varchar(7), required: true, primaryKey: true }
  10. name: varchar(50)

 

COMPORTAMIENTOS

Los comportamientos son plugins que modifican el modelo de datos para añadir nuevas funcionalidades a las clases de Propel.

  1. propel:
  2. blog_articulo:
  3. titulo: varchar(50)
  4. _behaviors:
  5. paranoid: { column: deleted_at }

 

Optimizar el servidor web Apache

1

Tenía intención de crear un post explicando la optimización de Apache, pero la verdad es que en la red ya existe bastante información al respecto por tanto os dejo dos links, uno explicando cada uno de los parámetros que se pueden modificar en el archivo httpd.conf de Apache y el otro con algunos ejemplos de optimización:   – Definición de parámetros: http://www.codenb.com/optimizar-apache-16/ – Ejemplos: http://www.forosdelweb.com/f58/recetas-para-configuracion-apache-404961/

Symfony: El modelo (II)

0

Cuando Symfony construye el modelo, crea una clase de objeto base para cada una de las tablas definidas en schema.yml. Cada una de estas clases contiene una serie de constructores y accesores por defecto en función de la definición de cada columna: los métodos new, getXXX() y setXXX() (donde XXX es el nombre del campo) permiten crear y obtener las propiedades de los objetos:

  1. <?php
  2.  
  3. $articulo = new Articulo();
  4. $articulo->setTitulo('Mi primer artículo');
  5. $articulo->setContenido('Este es mi primer artículo. \n Espero que te guste.');
  6.  
  7. $titulo = $articulo->getTitulo();
  8. $contenido = $articulo->getContenido();

 

Para establecer el valor de varios campos a la vez, se puede utilizar el método fromArray(), que también se genera para cada clase objeto:

  1. <?php
  2.  
  3. $articulo->fromArray(array(
  4. 'titulo' => 'Mi primer artículo',
  5. 'contenido' => 'Este es mi primer artículo. \n Espero que te guste.'
  6. ));
  1. <?php
  2.  
  3. // Relación de "muchos a uno"
  4. echo $comentario->getArticulo()->getTitulo();
  5. => Mi primer artículo
  6. echo $comentario->getArticulo()->getContenido();
  7. => Este es mi primer artículo.
  8. Espero que te guste.
  9.  
  10. // Relación "uno a muchos"
  11. $comentarios = $articulo->getComentarios();

La columna articulo_id de la tabla blog_comentario define implícitamente una clave externa a la tabla blog_articulo. Cada comentario está relacionado con un artículo y un artículo puede tener muchos comentarios. Las clases generadas contienen 5 métodos que traducen esta relación a la forma orientada a objetos, de la siguiente manera:

  • $comentario->getArticulo(): para obtener el objeto Articulo relacionado
  • $comentario->getArticuloId(): para obtener el ID del objeto Articulo relacionado
  • $comentario->setArticulo($articulo): para definir el objeto Articulo relacionado
  • $comentario->setArticuloId($id): para definir el objeto Articulo relacionado a partir de un ID
  • $articulo->getComentarios(): para obtener los objetos Comentario relacionados
  1. <?php
  2.  
  3. $comentario = new Comentario();
  4. $comentario->setAutor('Steve');
  5. $comentario->setContenido('¡Es el mejor artículo que he leído nunca!');
  6.  
  7. // Añadir este comentario al anterior objeto $articulo
  8. $comentario->setArticulo($articulo);
  9.  
  10. // Sintaxis alternativa
  11. // Solo es correcta cuando el objeto artículo ya
  12. // ha sido guardado anteriormente en la base de datos
  13. $comentario->setArticuloId($articulo->getId());

El método getArticulo() devuelve un objeto de tipo Articulo, que permite utilizar el método accesor getTitulo(). Se trata de una alternativa mucho mejor que realizar la unión de las tablas manualmente, ya que esto último necesitaría varias líneas de código (empezando con la llamada al método $comment->getArticuloId()).

La variable $comentarios contiene un array de objetos de tipo Comentario. Se puede mostrar el primer comentario mediante $comentarios[0] o se puede recorrer la colección entera mediante foreach ($comentarios as $comentario).

Al utilizar el constructor new se crea un nuevo objeto, pero no un registro en la tabla blog_articulo. Si se modifica el objeto, tampoco se reflejan esos cambios en la base de datos. Para guardar los datos en la base de datos, se debe invocar el método save() del objeto.

  1. <?php
  2.  
  3. $articulo->save();
  1. <?php
  2.  
  3. foreach ($articulo->getComentarios() as $comentario)
  4. {
  5. $comentario->delete();
  6. }

Si se conoce la clave primaria de un registro concreto, se puede utilizar el método retrieveByPk() de la clase peer para obtener el objeto relacionado.

  1. <?php
  2.  
  3. $articulo = ArticuloPeer::retrieveByPk(7);

En algunos casos, la clave primaria está formada por más de una columna. Es esos casos, el método retrieveByPK() permite indicar varios parámetros, uno para cada columna de la clave primaria.

También se pueden obtener varios objetos a la vez mediante sus claves primarias, invocando el método retrieveByPKs(), que espera como argumento un array de claves primarias.

 

Cuando se quiere obtener más de un registro, se debe utilizar el método doSelect() de la clase peer correspondiente a los objetos que se quieren obtener. Por ejemplo, para obtener objetos de la clase Articulo, se llama al método ArticuloPeer::doSelect().

El primer parámetro del método doSelect() es un objeto de la clase Criteria, que es una clase para definir consultas simples sin utilizar SQL, para conseguir la abstracción de base de datos.

Un objeto Criteria vacío devuelve todos los objetos de la clase.

  1. <?php
  2.  
  3. $c = new Criteria();
  4. $articulos = ArticuloPeer::doSelect($c);
  5.  
  6. // Genera la siguiente consulta SQL
  7. SELECT blog_articulo.ID, blog_articulo.TITLE, blog_articulo.CONTENIDO,
  8. blog_articulo.CREATED_AT
  9. FROM blog_articulo;

Para las selecciones más complejas de objetos, se necesitan equivalentes a las sentencias WHERE, ORDER BY, GROUP BY y demás de SQL. El objeto Criteria dispone de métodos y parámetros para indicar todas estas condiciones. Por ejemplo, para obtener todos los comentarios escritos por el usuario Steve y ordenados por fecha:

  1. <?php
  2.  
  3. $c = new Criteria();
  4. $c->add(ComentarioPeer::AUTOR, 'Steve');
  5. $c->addAscendingOrderByColumn(ComentarioPeer::CREATED_AT);
  6. $comentarios = ComentarioPeer::doSelect($c);
  7.  
  8. // Genera la siguiente consulta SQL
  9. SELECT blog_comentario.ARTICULO_ID, blog_comentario.AUTOR, blog_comentario.CONTENIDO,
  10. blog_comentario.CREATED_AT
  11. FROM blog_comentario
  12. WHERE blog_comentario.autor = 'Steve'
  13. ORDER BY blog_comentario.CREATED_AT ASC;

as constantes de clase que se pasan como parámetros a los métodos add() hacen referencia a los nombres de las propiedades. Su nombre se genera a partir del nombre de las columnas en mayúsculas. Por ejemplo, para indicar la columna contenido de la tabla blog_articulo, se utiliza la constante de clase llamada ArticuloPeer::CONTENIDO.

Otro ejemplo del uso de Criteria con condiciones múltiples. En el ejemplo se obtienen todos los comentarios del usuario Steve en los artículos que contienen la palabra enjoy y además, ordenados por fecha.

 

  1. <?php
  2.  
  3. $c = new Criteria();
  4. $c->add(ComentarioPeer::AUTOR, 'Steve');
  5. $c->addJoin(ComentarioPeer::ARTICULO_ID, ArticuloPeer::ID);
  6. $c->add(ArticuloPeer::CONTENIDO, '%enjoy%', Criteria::LIKE);
  7. $c->addAscendingOrderByColumn(ComentarioPeer::CREATED_AT);
  8. $comentarios = ComentarioPeer::doSelect($c);
  9.  
  10. // Genera la siguiente consulta SQL
  11. SELECT blog_comentario.ID, blog_comentario.ARTICULO_ID, blog_comentario.AUTOR,
  12. blog_comentario.CONTENIDO, blog_comentario.CREATED_AT
  13. FROM blog_comentario, blog_articulo
  14. WHERE blog_comentario.AUTOR = 'Steve'
  15. AND blog_articulo.CONTENIDO LIKE '%enjoy%'
  16. AND blog_comentario.ARTICULO_ID = blog_articulo.ID
  17. ORDER BY blog_comentario.CREATED_AT ASC

Además del método doSelect(), todas las clases peer tienen un método llamado doCount(), que simplemente cuenta el número de registros que satisfacen las condiciones pasadas como parámetro y devuelve ese número como un entero.

Las clases peer también incluyen métodos doDelete(), doInsert() y doUpdate() (todos ellos requieren como parámetro un objeto de tipo Criteria).

Por último, si solo se quiere obtener el primer objeto, se puede reemplazar el método doSelect() por doSelectOne(). Es muy útil cuando se sabe que las condiciones de Criteria solo van a devolver un resultado, y su ventaja es que el método devuelve directamente un objeto en vez de un array de objetos.

A veces, no es necesario obtener los objetos, sino que solo son necesarios algunos datos calculados por la base de datos. Por ejemplo, para obtener la fecha de creación de todos los artículos, no tiene sentido obtener todos los artículos y después recorrer el array de los resultados.

Para realizar consultas a la base de datos con PDO, es necesario realizar los siguientes pasos:

  • Obtener la conexión con la base de datos.
  • Construir la consulta.
  • Crear una sentencia con esa consulta.
  • Iterar el result set que devuelve la ejecución de la sentencia.
  1. <?php
  2.  
  3. conexion = Propel::getConnection();
  4. $consulta = 'SELECT MAX(%s) AS max FROM %s';
  5. $consulta = sprintf($consulta, ArticuloPeer::CREATED_AT, ArticuloPeer::TABLE_NAME);
  6. $sentencia = $conexion->prepare($consulta);
  7. $sentencia->execute();
  8. $resultset = $sentencia->fetch(PDO::FETCH_OBJ);
  9. $max = $resultset->max;

Normalmente, cuando una tabla tiene una columna llamada created_at, se utiliza para almacenar un timestamp de la fecha de creación del registro. La misma idea se aplica a las columnas updated_at, cuyo valor se debe actualizar cada vez que se actualiza el propio registro.

La buena noticia es que Symfony reconoce estos nombres de columna y se ocupa de actualizar su valor de forma automática. No es necesario establecer manualmente el valor de las columnas created_at y updated_at; se actualizan automáticamente. Lo mismo se aplica a las columnas llamadas created_on y updated_on.

  1. <?php
  2.  
  3. $comentario = new Comentario();
  4. $comentario->setAutor('Steve');
  5. $comentario->save();
  6.  
  7. // Muestra la fecha de creación
  8. echo $comentario->getCreatedAt();
  9. => [fecha de la operación INSERT de la base de datos]

Además, los getters de las columnas de fechas permiten indicar el formato de la fecha como argumento:

  1. <?php
  2.  
  3. echo $comentario->getCreatedAt('Y-m-d');

 

“Chuletas” para Symfony

0

Más de uno conocerá esas imágenes o PDFs que, de forma resumida, muestran todos los métodos y funciones de los lenguajes de programación o de frameworks. Con Symfony eso no es diferente, además de ser muy útil en las primeras etapas de aprendizaje. Os dejo el link:

http://trac.symfony-project.org/wiki/CheatSheets

 

¡Qué lo disfrutéis!

Symfony: El modelo (I)

0

Las bases de datos son relacionales. PHP 5 y Symfony están orientados a objetos. Para acceder de forma efectiva a la base de datos desde un contexto orientado a objetos, es necesaria una interfaz que traduzca la lógica de los objetos a la lógica relacional. Esta interfaz se llama ORM (object-relational mapping) o “mapeo de objetos a bases de datos”, y está formada por objetos que permiten acceder a los datos y que contienen en sí mismos el código necesario para hacerlo.

La utilización de objetos en vez de registros y de clases en vez de tablas, tiene otra ventaja: permite añadir métodos accesores en los objetos que no tienen relación directa con una tabla. Si se dispone por ejemplo de una tabla llamada cliente con dos campos llamados nombre y apellidos, puede que se necesite un dato llamado NombreCompleto que incluya y combine el nombre y los apellidos. En el mundo orientado a objetos, es tan fácil como añadir un método accesor a la clase Cliente. Desde el punto de vista de la aplicación, no existen diferencias entre los atributos Nombre, Apellidos, NombreCompleto de la clase Cliente. Solo la propia clase es capaz de determinar si un atributo determinado se corresponde con una columna de la base de datos.

  1. <?php
  2.  
  3. public function getNombreCompleto()
  4. {
  5. return $this->getNombre().' '.$this->getApellidos();
  6. }

Todo el código repetitivo de acceso a los datos y toda la lógica de negocio de los propios datos se puede almacenar en esos objetos. Imagina que se ha definido la clase CarritoCompra en la que se almacenan Productos (que son objetos). Para obtener el precio total del carrito de la compra antes de realizar el pago, se puede crear un método que encapsula el proceso de cálculo:

  1. <?php
  2.  
  3. public function getTotal()
  4. {
  5. $total = 0;
  6. foreach ($this->getProductos() as $producto)
  7. {
  8. $total += $producto->getPrecio() * $producto->getCantidad();
  9. }
  10.  
  11. return $total;
  12. }

 

ESQUEMA DE BASE DE DATOS DE SYMFONY

Para crear el modelo de objetos de datos que utiliza Symfony, se debe traducir el modelo relacional de la base de datos a un modelo de objetos de datos. Para realizar ese mapeo o traducción, el ORM necesita una descripción del modelo relacional, que se llama “esquema” (schema). En el esquema se definen las tablas, sus relaciones y las características de sus columnas.

La sintaxis que utiliza Symfony para definir los esquemas hace uso del formato YAML. Los archivos schema.yml deben guardarse en el directorio miproyecto/config/.

  1. propel:
  2. blog_articulo:
  3. _attributes: { phpName: Articulo }
  4. id:
  5. titulo: varchar(255)
  6. contenido: longvarchar
  7. created_at:
  8. blog_comentario:
  9. _attributes: { phpName: Comentario }
  10. id:
  11. articulo_id:
  12. autor: varchar(255)
  13. contenido: longvarchar
  14. created_at:

 

SINTAXIS BÁSICA DE LOS ESQUEMAS

En el archivo schema.yml, la primera clave representa el nombre de la conexión. Puede contener varias tablas, cada una con varias columnas. Siguiendo la sintaxis de YAML, las claves terminan con dos puntos (:) y la estructura se define mediante la indentación con espacios, no con tabuladores.

Cada tabla puede definir varios atributos, incluyendo el atributo phpName (que es el nombre de la clase PHP que será generada para esa tabla). Si no se menciona el atributo phpName para una tabla, Symfony crea una clase con el mismo nombre que la tabla al que se aplica las normas del camelCase.

Las tablas contienen columnas y el valor de las columnas se puede definir de 3 formas diferentes:

  • Si no se indica nada, Symfony intenta adivinar los atributos más adecuados para la columna en función de su nombre y de una serie de convenciones. Por ejemplo, en el listado anterior no es necesario definir la columna id. Symfony por defecto la trata como de tipo entero (integer), cuyo valor se auto-incrementa y además, clave principal de la tabla. En la tabla blog_comentario, la columna articulo_id se trata como una clave externa a la tabla blog_articulo (las columnas que acaban en _id se consideran claves externas, y su tabla relacionada se determina automáticamente en función de la primera parte del nombre de la columna). Las columnas que se llaman created_at automáticamente se consideran de tipo timestamp. Para este tipo de columnas, no es necesario definir su tipo. Esta es una de las razones por las que es tan fácil crear archivos schema.yml.
  • Si sólo se define un atributo, se considera que es el tipo de columna. Symfony entiende los tipos de columna habituales: boolean, integer, float, date, varchar(tamaño), longvarchar (que se convierte, por ejemplo, en tipo text en MySQL), etc. Para contenidos de texto de más de 256 caracteres, se utiliza el tipo longvarchar, que no tiene tamaño definido (pero que no puede ser mayor que 65KB en MySQL). Los tipos date y timestamp tienen las limitaciones habituales de las fechas de Unix y no pueden almacenar valores anteriores al 1 de Enero de 1970. Como puede ser necesario almacenar fechas anteriores (por ejemplo para las fechas de nacimiento), existe un formato de fechas “anteriores a Unix” que son bu_date and bu_timestamp.
  • Si se necesitan definir otros atributos a la columna (por ejemplo su valor por defecto, si es obligatorio o no, etc.), se indican los atributos como pares clave: valor.

Las columnas también pueden definir el atributo phpName, que es la versión modificada de su nombre según las convenciones habituales (Id, Titulo, Contenido, etc) y que normalmente no es necesario redefinir.

 

LAS CLASES DEL MODELO

Como ya has podido leer, Symfony a través de Propel genera una clase para cada tabla. Para generar esas clases simplemente, una vez hayas terminado de crear el esquema del modelo, en la consola escribe:

> php symfony propel:build-model

Al ejecutar ese comando, se analiza el esquema y se generan las clases base del modelo, que se almacenan en el directorio lib/model/om/ del proyecto:

  • BaseArticulo.php
  • BaseArticuloPeer.php
  • BaseComentario.php
  • BaseComentarioPeer.php

Además, se crean las verdaderas clases del modelo de datos en el directorio lib/model/:

  • Articulo.php
  • ArticuloPeer.php
  • Comentario.php
  • ComentarioPeer.php

Sólo se han definido dos tablas y se han generado ocho archivos. Aunque este hecho no es nada extraño, merece una explicación.

Puede ser necesario añadir métodos y propiedades personalizadas en los objetos del modelo (piensa por ejemplo en el método getNombreCompleto()). También es posible que a medida que el proyecto se esté desarrollando, se añadan tablas o columnas. Además, cada vez que se modifica el archivo schema.yml se deben regenerar las clases del modelo de objetos mediante el comando propel-build-model. Si se añaden los métodos personalizados en las clases que se generan, se borrarían cada vez que se vuelven a generar esas clases.

Las clases con nombre Base del directorio lib/model/om/ son las que se generan directamente a partir del esquema. Nunca se deberían modificar esas clases, porque cada vez que se genera el modelo, se borran todas las clases.

Por otra parte, las clases de objetos propias que están en el directorio lib/model heredan de las clases con nombre Base. Estas clases no se modifican cuando se ejecuta la tarea propel:build-model, por lo que son las clases en las que se añaden los métodos propios.

  1. <?php
  2.  
  3. class Articulo extends BaseArticulo
  4. {
  5. }

Articulo y Comentario son clases objeto que representan un registro de la base de datos. Permiten acceder a las columnas de un registro y a los registros relacionados. Por tanto, es posible obtener el título de un artículo invocando un método del objeto Articulo:

  1. <?php
  2.  
  3. $articulo = new Articulo();
  4.  
  5. // ...
  6. $titulo = $articulo->getTitulo();

ArticuloPeer y ComentarioPeer son clases de tipo “peer“; es decir, clases que tienen métodos estáticos para trabajar con las tablas de la base de datos. Proporcionan los medios necesarios para obtener los registros de las tablas. Sus métodos devuelven normalmente un objeto o una colección de objetos de la clase objeto relacionada:

  1. <?php
  2.  
  3. // $articulos es un array de objetos de la clase Articulo
  4. $articulos = ArticuloPeer::retrieveByPks(array(123, 124, 125));
Feed RSS de Mikel
Ir arriba