Los datos de las ofertas de trabajo, afiliados y categorías se guardan en una base de datos relacional. Por otra parte, como Symfony es un framework orientado a objetos, nuestro objetivo es trabajar con objetos siempre que sea posible. Así por ejemplo, preferimos utilizar objetos a tener que escribir sentencias SQL para obtener los registros de la base de datos.
Para trabajar con objetos en una base de datos relacional, es necesario realizar un mapeo o conversión entre la información de la base de datos y los objetos PHP. Este mapeo se realiza con unas herramientas llamadas ORM y Symfony incluye por defecto dos de las más utilizadas: Propel y Doctrine. En este tutorial vamos a utilizar Propel.
A partir de la descripción de cada tabla y de las relaciones entre tablas, el ORM crea las clases PHP necesarias para trabajar con objetos. Existen dos formas de crear la descripción del esquema de datos: mediante la introspección de una base de datos existente o creando el esquema manualmente.
Existen aplicaciones para crear bases de datos gráficamente (por ejemplo Dbdesigner de Fabforce) y para generar archivos de tipo schema.xml (por ejemplo DB Designer 4 TO Propel Schema Converter).
Como todavía no tenemos ninguna base de datos y como queremos que Jobeet funcione con todos los tipos de gestores de bases de datos, vamos a crear el archivo del esquema a mano. Para ello, abre el archivo config/schema.yml y añade lo siguiente tal y como está escrito:
# config/schema.yml propel: jobeet_category: id: ~ name: { type: varchar(255), required: true, index: unique } jobeet_job: id: ~ category_id: { type: integer, foreignTable: jobeet_category, foreignReference: id, required: true } type: { type: varchar(255) } company: { type: varchar(255), required: true } logo: { type: varchar(255) } url: { type: varchar(255) } position: { type: varchar(255), required: true } location: { type: varchar(255), required: true } description: { type: longvarchar, required: true } how_to_apply: { type: longvarchar, required: true } token: { type: varchar(255), required: true, index: unique } is_public: { type: boolean, required: true, default: 1 } is_activated: { type: boolean, required: true, default: 0 } email: { type: varchar(255), required: true } expires_at: { type: timestamp, required: true } created_at: ~ updated_at: ~ jobeet_affiliate: id: ~ url: { type: varchar(255), required: true } email: { type: varchar(255), required: true, index: unique } token: { type: varchar(255), required: true } is_active: { type: boolean, required: true, default: 0 } created_at: ~ jobeet_category_affiliate: category_id: { type: integer, foreignTable: jobeet_category, foreignReference: id, required: true, primaryKey: true, onDelete: cascade } affiliate_id: { type: integer, foreignTable: jobeet_affiliate, foreignReference: id, required: true, primaryKey: true, onDelete: cascade }
Si eres de los que prefieres crear la base de datos directamente con sentencias SQL, puedes generar el archivo de configuración schema.yml a partir de una base de datos existente mediante la tarea propel:build-schema
$ php symfony propel:build-schema
La tarea anterior requiere que se haya configurado una base de datos en el archivo databases.yml, tal y como se explica más adelante. Por tanto, si ejecutas ahora esa tarea, no va a funcionar correctamente porque no sabe la base de datos para la que debe crear el esquema.
El esquema de datos no es más que la traducción del diagrama de entidad-relación al formato YAML.
El archivo schema.yml describe todas las tablas y columnas de la base de datos. Cada columna se describe con la siguiente información:
type: el tipo de columna, que puede ser boolean, tinyint, smallint, integer, bigint, double, float, real, decimal, char, varchar(size), longvarchar, date, time, timestamp, blob y clob.required: si vale true, la columna es obligatoria.index: si vale true, se crea un índice para la columna; si vale unique, se crea un índice único.primaryKey: indica que esta columna es clave primaria de la tabla.foreignTable, foreignReference: indica que esta columna es clave externa de otra tabla. En las columnas cuyo valor es simplemente ~, que en realidad es como se indica el valor null en YAML (id, created_at y updated_at), Symfony adivina cuál es la mejor configuración para esa columna (los campos llamados id se consideran claves primarias y los campos llamados created_at y updated_at se consideran de tipo timestamp).
El atributo onDelete define el comportamiento de las claves primarias ante las sentencias ON DELETE. Propel admite los valores CASCADE, SETNULL y RESTRICT. Cuando se borra por ejemplo el registro de una oferta de trabajo (job) todos los registros relacionados de la tabla jobeet_category_affiliate se borran automáticamente mediante la base de datos o mediante Propel si el sistema gestor de base de datos no es capaz de hacerlo.
válido para Symfony 1.2