Download - MANUAL DE SYMFONY 3.pdf
Manual de Symfony
Objetivos:
1. Modelar correctamente nuestra base de datos en formato YML con sus respectivas relaciones
2. Exportar la base de datos con información por defecto.
En la presente ficha aprenderemos a modelar nuestra base de datos en formato YML, luego a partir de la
estructura que creemos construir su respectivo modelo, formularios y filtros y finalmente exportar la base de
datos con datos iniciales.
1. Como observamos en el manual 1 de symfony para la creación de un mantenimiento de la clase
persona, primero generamos la definición de la entidad “Persona” en el archivo “config » doctrine »
schema.yml”, este archivo no sólo sirve para definir una entidad sino que en realidad se deben definir
todas las entidades de nuestro proyecto en formato YML.
En esta parte del manual aprenderemos como definir varias entidades con sus respectivas relaciones.
Para empezar, debemos definir la conexión que vamos a usar para conectarnos a nuestra base de
datos, esto la hacíamos en el fichero “config » databases.yml”:
Donde “doctrine” es el nombre de la conexión la cual vamos a usar para definir todas nuestras
entidades.
2. Antes de construir nuestra entidades tenemos que centrarnos un poco en como hace symfony para
reconocer una entidad, tomamos como ejemplo la siguiente la siguiente entidad “Persona”:
Donde:
all:
doctrine:
class: sfDoctrineDatabase
param:
dsn: mysql:host=localhost;dbname=bd_proyecto
username: root password:
attributes:
default_table_charset: utf8
default_table_collate: utf8_spanish_ci
Persona:
connection: doctrine
tableName: t_persona
actAs:
Sluggable: alias: slug_persona
fields: [nombres, ape_paterno, ape_materno]
canUpdate: true
Timestampable:
created:
name: fec_crea updated:
name: fec_modifica
columns:
nro_doc: { type: string(15), notnull: true }
ape_paterno: { type: string(40), notnull: true } ape_materno: { type: string(40), notnull: true }
nombres: { type: string(40), notnull: true }
sexo: { type: enum, values: [M, F] }
fec_nacimiento: { type: date(25), notnull: true }
direccion: { type: string(80) } telefono: { type: string(20) }
celular: { type: string(20) }
correo: { type: string(60) }
Es el nombre de la entidad y la clase que se va a generar después.
Es la conexión que definimos anteriormente y la forma como symfony se conecta con nuestra base de
datos física.
Es el nombre de la tabla que se va a generar en nuestra base de datos física.
Es el comportamiento particular que puede adoptar nuestra entidad:
Sluggable » Genera un campo “slug” que será único para cada registro de la entidad y que puede
funcionar como una clave pero que toma valores más comprensible para el usuario, por ejemplo el slug
para: Jose Carlos Fernández Gomez sería » jose-carlos-fernandez-gomez.
Timestampable » Genera en este caso dos campos adicionales “fec_crea” y “fec_modifica” que tienen
la función de registrar de forma automática la fecha de creación de un registro y la última fecha de
modificación del mismo.
Aquí se describen todas las columnas de nuestra entidad, fíjese que no se ha descrito la columna que
corresponde a la clave primaria, esta se genera por defecto con el nombre de “id”.
Primero se coloca el nombre de la columna y a continuación los atributos de esta:
type: Es el tipo de dato de nuestra columna, puede ser de varios tipos:
boolean: que puede tomar solo dos valores 1 | 0.
integer:
Persona:
connection: doctrine
tableName: t_persona
actAs:
Sluggable:
alias: slug_persona
fields: [nombres, ape_paterno, ape_materno] canUpdate: true
Timestampable:
created:
name: fec_crea
updated: name: fec_modifica
columns: nro_doc: { type: string(8), fixed: true, notnull: true }
ape_paterno: { type: string(40), notnull: true }
ape_materno: { type: string(40), notnull: true }
nombres: { type: string(40), notnull: true }
sexo: { type: enum, values: [M, F] } fec_nacimiento: { type: date(25), notnull: true }
direccion: { type: string(80) }
telefono: { type: string(20) }
celular: { type: string(20) }
correo: { type: string(60) }
Test:
columns:
booltest: boolean
Test:
columns: integertest:
type: integer(4)
unsigned: true
Campo de tipo entero, se define entre paréntesis la longitud del entero y luego si será un entero con o
sin signo.
float:
Campo de tipo real.
decimal:
Numero decimal con 18 números enteros y 2 decimales
string:
Cadena de longitud 200 variable -> varchar(200)
Cadena de longitud fija de 20 -> char(20)
time:
date:
enum:
Tipo de datos especial que solo acepta los valores enumerados en “values”.
3. Relaciones:
Test:
columns: floattest: float
Test: columns:
decimaltest:
type: decimal(18)
scale: 2
Test:
columns:
stringtest:
type: string(200)
Test:
columns:
stringtest: type: string(20)
fixed: true
Test:
columns:
timetest: time
Test:
columns:
datetest: date
Test:
columns:
enumtest:
type: enum
values: [php, java, python]
Algo importante al momento de diseñar nuestra base de datos es definir correctamente las relaciones
de integridad referencial, lo cual podemos hacer perfectamente con YML, para ello veremos los tipos de
relaciones que veremos con más frecuencia, para ello tomaremos como ejemplo:
El anterior gráfico representa una base de datos para foros. La representación de sus entidades sería la
siguiente:
Foro:
connection: doctrine
tableName: t_foro
columns:
nombre: { type: string(100), notnull: true } descripcion: { type: string(5000) }
# ----------------------------------
HiloForo:
Connection: doctrine tableName: t_hilo_foro
columns:
usuario_id: { type: integer, notnull: true }
foro_id: { type: integer, notnull: true }
titulo: { type: string(100), notnull: true }
actualizado: { type: integer(4) } cerrado: { type: boolean }
# ------------------------------------
Usuario:
Connection: doctrine tableName: t_usuario
columns:
nombre: { type: string(100) , notnull: true }
login: { type: string(20) , notnull: true }
password: { type: string(50) , notnull: true }
activo: { type: boolean }
# ------------------------------------
Correo:
Connection: doctrine
tableName: t_correo columns:
usuario_id: { type: integer, notnull: true }
direccion: { type: string(60), notnull: true }
# ------------------------------------ Grupo:
Connection: doctrine
tableName: t_grupo
columns:
nombre: { type: string(50), notnull: true }
# ------------------------------------
UsuarioGrupo:
Connection: doctrine
tableName: t_usuario_grupo
columns: usuario_id: { type: integer, notnull: true }
grupo_id: { type: integer, notnull: true }
Ahora debemos definir la relación entre ellos:
Sabemos por definición que tenemos 3 tipos de relaciones (más frecuentes):
- Relación de 1 a 1.
- Relación de 1 a varios o varios a 1.
- Relación de varios a varios.
Observamos en nuestro diagrama que existen definidos los 3 tipos de relaciones:
- 1 foro tiene varios hilos (1 a varios).
- 1 usuarios está presente en varios hilos (1 a varios).
- 1 usuario sólo tiene 1 correo (1 a 1).
- 1 usuario puede pertenecer a varios grupos y un grupo puede tener varios usuarios (varios a
varios).
La forma como debemos construir las relaciones es la siguiente:
1 a 1:
# ------------------------------------ Usuario:
Connection: doctrine
tableName: t_usuario
columns:
nombre: { type: string(100) , notnull: true } login: { type: string(20) , notnull: true }
password: { type: string(50) , notnull: true }
activo: { type: boolean }
# ------------------------------------ Correo:
Connection: doctrine
tableName: t_correo
columns:
usuario_id: { type: integer, notnull: true } direccion: { type: string(60), notnull: true }
relations:
Usuario:
local: usuario_id
foreign: id ## hace referencia a la clave primaria de usuario que es “id”
foreignType: one ## el tipo de relación es de 1 a 1
1 a varios | varios a 1:
Foro: connection: doctrine
tableName: t_foro
columns:
nombre: { type: string(100), notnull: true }
descripcion: { type: string(5000) } relations:
Hilos: ## un foro tiene “varios hilos”
class: HiloForo
local: id ## es la clave primaria de esta entidad “id”
foreign: foro_id
type: many ## la relación de es de varios
# ----------------------------------
HiloForo:
Connection: doctrine
tableName: t_hilo_foro columns:
usuario_id: { type: integer, notnull: true }
foro_id: { type: integer, notnull: true }
titulo: { type: string(100), notnull: true }
actualizado: { type: integer(4) }
cerrado: { type: boolean } relations:
Foro: ## un hilo de un foro pertenece a “un solo foro”
local: foro_id ## es la clave foranea de esta entidad “foro_id”
foreign: id ## es la clave primaria de la entidad foro
type: one ## la relación en esta entidad es de 1
Usuario: ## un hilo de un foro pertenece a “un solo usuario”
local: usuario_id ## es la clave foranea de esta entidad “usuario_id”
foreign: id ## es la clave primaria de la entidad usuario
type: one ## la relación en esta entidad es de 1
# ------------------------------------ Usuario:
Connection: doctrine
tableName: t_usuario
columns:
nombre: { type: string(100) , notnull: true } login: { type: string(20) , notnull: true }
password: { type: string(50) , notnull: true }
activo: { type: boolean }
relations:
Hilos: ## un usuario participa en “varios hilos”
class: HiloForo
local: id ## es la clave primaria de esta entidad “id”
foreign: usuario_id
type: many ## la relación de es de varios
varios a varios:
# ------------------------------------ Usuario:
Connection: doctrine
tableName: t_usuario
columns:
nombre: { type: string(100) , notnull: true } login: { type: string(20) , notnull: true }
password: { type: string(50) , notnull: true }
activo: { type: boolean }
relations:
Grupos: ## un usuario esta en “varios grupos”
class: Grupo ## la clase a la que se debe hacer referencia
refClass: UsuarioGrupo ## es la clase que permite la definición de varios a varios
local: usuario_id ## la clave local de usuario en UsuarioGrupo
foreign: grupo_id ## la clave foránea de grupo en UsuarioGrupo
# ------------------------------------
Grupo:
Connection: doctrine
tableName: t_grupo
columns:
nombre: { type: string(50), notnull: true } relations:
Usuarios: ## un grupo tiene “varios usuarios”
class: Usuario ## la clase a la que se debe hacer referencia
refClass: UsuarioGrupo ## es la clase que permite la definición de varios a varios
local: grupo_id ## la clave local de grupo en UsuarioGrupo
foreign: usuario_id ## la clave foránea de usuario en UsuarioGrupo
# ------------------------------------
UsuarioGrupo:
Connection: doctrine tableName: t_usuario_grupo
columns:
usuario_id: { type: integer, notnull: true }
grupo_id: { type: integer, notnull: true }
Entonces nuestro esquema de datos quedaría de la siguiente forma:
# ------------------------------------ Usuario:
Connection: doctrine
tableName: t_usuario
columns:
nombre: { type: string(100) , notnull: true } login: { type: string(20) , notnull: true }
password: { type: string(50) , notnull: true }
activo: { type: boolean }
Hilos:
class: HiloForo
local: id foreign: usuario_id
type: many
Grupos:
class: Grupo
refClass: UsuarioGrupo local: usuario_id
foreign: grupo_id
# ------------------------------------
Correo:
Connection: doctrine tableName: t_correo
columns:
usuario_id: { type: integer, notnull: true }
direccion: { type: string(60), notnull: true }
relations: Usuario:
local: usuario_id
foreign: id
foreignType: one
# ------------------------------------ Foro:
connection: doctrine
tableName: t_foro
columns:
nombre: { type: string(100), notnull: true } descripcion: { type: string(5000) }
relations:
Hilos:
class: HiloForo
local: id
foreign: foro_id type: many
# ----------------------------------
HiloForo:
Connection: doctrine tableName: t_hilo_foro
columns:
usuario_id: { type: integer, notnull: true }
foro_id: { type: integer, notnull: true }
titulo: { type: string(100), notnull: true }
actualizado: { type: integer(4) } cerrado: { type: boolean }
relations:
Foro:
local: foro_id
foreign: id type: one
Usuario:
local: usuario_id
foreign: id
type: one
# ------------------------------------ Grupo:
Connection: doctrine
tableName: t_grupo
columns:
nombre: { type: string(50), notnull: true } relations:
Usuarios:
class: Usuario
refClass: UsuarioGrupo
local: grupo_id
foreign: usuario_id
# ------------------------------------
UsuarioGrupo:
Connection: doctrine
tableName: t_usuario_grupo columns:
usuario_id: { type: integer, notnull: true }
grupo_id: { type: integer, notnull: true }
4. Una vez aprendido esto modele el esquema para sus respectivas bases de datos.