Anda di halaman 1dari 52

Desarrollo de aplicaciones

con

Symfony 2
CRUD bsico
@symfony_zgz

Symfony 2

Recordemos
algo ya visto en la
primera charla

Crear el proyecto Symfony 2


composer create-project symfony/framework-standard-edition
<directorio> 2.4.*
Ejemplo en Windows
C:\> composer create-project symfony/framework-standard-edition
"D:\Proyectos\Cupon" 2.4.*
Ejemplo en Linux y Mac OS X
$ composer create-project symfony/framework-standardedition "/prueba" 2.4.*

*Importante - Permisos
Un problema comn al instalar Symfony2 es que los directorios
app/cache y app/logs deben tener permiso de escritura, tanto para el
servidor web cmo para el usuario de la consola de comandos.
Podeis ver como hacerlo en el apartado 3.1.2. Instalando y
configurando de
http://librosweb.es/symfony_2_4/capitulo_3/instalando_una_distribucio
n_de_symfony2.html

*Importante - Entornos
Si revisas el directorio web/, encontrars dos archivos PHP: app.php y
app_dev.php. Estos archivos son controladores frontales: todas las
peticiones a la aplicacin se hacen a travs de ellos. Pero, por qu
tenemos dos controladores frontales si hemos definido slo una
aplicacin?
Muy sencillo, ambos archivos apuntan a la misma aplicacin pero para
distintos entornos.
Y un entorno symfony es un conjunto nico de ajustes de
configuracin. El framework Symfony incluye tres de ellos: dev, test, y
prod.
Produccin: www.symfony-demo.local/app.php
Desarrollo: www.symfony-demo.local/app_dev.php

Comprobar la instalacin
Antes de empezar a programar tu aplicacin debes asegurarte
de que tu ordenador cumple con los requisitos para que
Symfony2 funcione bien.
$ php app/check.php
El scriptcheck.phpmuestra por consola una lista de requisitos
obligatorios (Mandatory requirements) y otra lista de
requisitos deseables (Optional checks) para ejecutar
Symfony2. No sigas adelante si incumples alguno de los
requisitos obligatorio

Estructura de directorios
app
Contiene los archivos de configuracin, la cach, los logs y los
recursos globales.
app/config/
Guarda todos los archivos de configuracin de la aplicacin.
app/cache/
Contiene todos los archivos generados por las numerosas
cachs de Symfony2 (clases, enrutamiento, plantillas,
entidades, validacin, etc.). Junto con el directorio app/logs/ es
el nico en el que Symfony2 debe tener permisos de escritura.

Estructura de directorios
app/logs/
Contiene los archivos de log generados por la aplicacin en
cualquier entorno de ejecucin (desarrollo, produccin, tests,
etc.). Junto con el directorio app/cache/ es el nico en el que
Symfony2 debe tener permisos de escritura.
app/Resources/
Almacena los recursos que se utilizan globalmente en el
proyecto (como por ejemplo el layout de las plantillas) o
recursos muy especiales que no encajan en ningn otro sitio
(como por ejemplo una librera Java para comprimir archivos
CSS y JavaScript)

Estructura de directorios
src/
Guarda todo el cdigo fuente propio del proyecto. Aqu es
donde creas los bundles de tu aplicacin.
vendor/
Contiene todo el cdigo fuente de Symfony2 y de todas las
libreras externas.
web/
El nico directorio pblico del proyecto. Contiene los archivos
web (CSS, JavaScript e imgenes) y los controladores frontales
de la aplicacin (app.php y app_dev.php)

Estructura de directorios de
un bundle
( vemoslo en un editor)

YAML
YAML es un lenguaje muy sencillo que permite describir los
datos como en XML, pero con una sintaxis mucho ms
sencilla. YAML es un formato especialmente til para describir
datos que pueden ser transformados en arrays simples y
asociativos.
$casa = array(
'familia' => array(
'apellido' => 'Garca',
'padres' =>
array('Antonio', 'Mara'), 'hijos' => array('Jose', 'Manuel',
'Carmen')),
'direccion' => array( 'numero' => 34, 'calle' => 'Gran Va',
'ciudad' => 'Cualquiera',
'codigopostal' => '12345' )
);

YAML
casa:
familia:
apellido: Garca
padres:
- Antonio
- Mara
hijos:
- Jose
- Manuel
- Carmen
direccion:
numero: 34
calle: Gran Va
ciudad: Cualquiera
codigopostal: 12345

Doctrine
Doctrine es un mapeador de objetos-relacional (ORM) escrito
en PHP que proporciona una capa de persistencia para objetos
PHP. Es una capa de abstraccin que se sita justo encima de
un SGBD.

TWIG
Twig es un motor y lenguaje de plantillas para PHP muy rpido
y eficiente. Symfony2 recomienda utilizar Twig para crear
todas las plantillas de la aplicacin. No obstante, si lo prefieres
puedes seguir escribiendo las plantillas con cdigo PHP normal
y corriente.
La sintaxis de Twig se ha diseado para que las plantillas sean
concisas y muy fciles de leer y de escribir.
Esto en Twig:
{% if usuario is defined %}
Hola {{ usuario.nombre }} hoy es {{ 'now' |
date('d/m/Y') }}
{% endif %}

Symfony 2

A que
esperamos?
Empecemos ya!

Aplicando la filosofa de
Symfony
Antes de empezar a programar la aplicacin, es necesario
adaptar todas las funcionalidades y wireframes a la filosofa
de trabajo de Symfony2. Planificar bien el proyecto segn la
forma de pensar de Symfony2 te asegura que podrs
desarrollarlo lo ms eficientemente posible.
El orden recomendado para aplicar la
filosofa de Symfony consiste en definir
primero las entidades, despus los
bundles y por ltimo el enrutamiento.

Nuestro caso
Entidades
Solo una, Prueba (name, surname, email, phone)
Bundles
Solo uno, Prueba
Enrutamiento
/
/new/
/view/{id}
/edit/{id}
/delete/{id}

Creando el bundle
Dentro de un bundle puedes utilizar cualquier estructura de
directorios, pero Symfony2 espera que utilices una estructura
muy especfica para simplificar su trabajo.
Para ayudarte, Symfony tiene el siguiente comando:
$ php app/console generate:bundle
Este comando te har una serie de preguntas:
-

Bundle namespace: SymfonyZgz/PruebaBundle


Bundle name: PruebaBundle
Target directory: <Enter> (para elegir el valor por defecto)
Configuration format: yml

Creando el bundle
- Do you want to generate the whole directory structure?
Respuesta recomendada: no
- Confirm automatic update of your Kernel?, contesta yes para
que el bundle se active en la aplicacin despus de generarlo
- Confirm automatic update of the Routing?, contesta tambin
yes para que el archivo de enrutamiento del bundle se cargue
automticamente desde el archivo de enrutamiento general
de la aplicacin.

Creando la entidad
Para ayudarte, Symfony tiene el siguiente comando:
$ php app/console doctrine:generate:entity
The Entity shortcut name: PruebaBundle:Prueba
Configuration format (yml, xml, php, or annotation)
[annotation]: <Enter>
// Vamos creando los campos
New field name (press <return> to stop adding fields):
nombre
Field type [string]: <Enter>
Field length [255]: <Enter>

La base de datos
# app/config/parameters.yml
parameters:
database_driver: pdo_mysql
database_host: 127.0.0.1
database_port: null
database_name: prueba
database_user: root
database_password: mipass
// Creando la base de datos
php app/console doctrine:database:create
// Creando la estructura
php app/console doctrine:schema:create
// Actualizando la estructura
php app/console doctrine:schema:update --force

Creando las rutas


# src/SymfonyZgz/PruebaBundle/Resources/config/routing.yml
prueba:
path:
/
defaults: { _controller: "PruebaBundle:Prueba:index" }
prueba_new:
path: /new
defaults: { _controller: "PruebaBundle:Prueba:new" }
prueba_view:
path: /view/{id}
defaults: { _controller: "PruebaBundle:Prueba:view" }
prueba_edit:
path: /edit/{id}
defaults: { _controller: "PruebaBundle:Prueba:edit" }
prueba_delete:
path: /delete/{id}
defaults: { _controller: "PruebaBundle:Prueba:delete" }

Nuestro controlador
# src/SymfonyZgz/PruebaBundle/Controller/PruebaController.php
use SymfonyZgz\PruebaBundle\Entity\Prueba;
use SymfonyZgz\PruebaBundle\Form\PruebaType;
class PruebaController extends Controller
{
public function indexAction(){...}
public function newAction(){...}
public function viewAction(){...}
public function editAction(){...}
public function deleteAction(){...}
}

indexAction
public function indexAction(){
$results = $this->getDoctrine()->getRepository('PruebaBundle:Prueba)->findAll();
return $this->render('PruebaBundle:Prueba:list.html.twig', array('results' => $results));
}

newAction
public function newAction(){
$prueba = new Prueba();
$form = $this->createForm(new PruebaType(), $prueba );
$request = $this->getRequest();
$form->handleRequest($request);
if($form->isSubmitted()){
if($form->isValid()){
$em = $this->getDoctrine()->getManager();
$em->persist($prueba);
$em->flush();
return $this->redirect(
$this->generateUrl('prueba_view', array('id' => $prueba )),301);
}
}
return $this->render('PruebaBundle:Prueba:edit.html.twig', array(
'form' => $form->createView(), 'prueba' => $prueba));
}

viewAction
public function viewAction($id){
$prueba = $this->getDoctrine()->getRepository('PruebaBundle:Prueba')->find($id);
return $this->render('PruebaBundle:Prueba:view.html.twig', array('prueba' => $prueba));
}

editAction
public function editAction($id){
$prueba = $this->getDoctrine()->getRepository('PruebaBundle:Prueba')->find($id);
$form = $this->createForm(new PruebaType(), $prueba );
$request = $this->getRequest();
$form->handleRequest($request);
if($form->isSubmitted()){
if($form->isValid()){
$em = $this->getDoctrine()->getManager();
$em->persist($prueba);
$em->flush();
return $this->redirect($this->generateUrl('prueba_view', array('id' => $id)),301);
}
}
return $this->render('PruebaBundle:Prueba:edit.html.twig', array(
'form' => $form->createView(), 'prueba' => $prueba));
}

deleteAction
public function deleteAction($id){
$prueba = $this->getDoctrine()->getRepository('PruebaBundle:Prueba')->find($id);
if($prueba){
$em = $this->getDoctrine()->getManager();
$em->remove($prueba);
$em->flush();
}
return $this->redirect( $this->generateUrl('prueba'), 301 );
}

Nuestro formulario
namespace SymfonyZgz\PruebaBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class PruebaType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options){...}
public function setDefaultOptions(OptionsResolverInterface $resolver){..}
public function getName(){..}
}

Nuestro formulario buildForm


public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name', <tipo>, <array options>)
->add('surname', 'text', array('label' => 'Apellidos','required' => false))
->add('email', 'text', array('label' => 'Email','required' => false))
->add('phone', 'text', array('label' => 'Telfono','required' => false));
$builder->add('save', 'submit');
}

Nuestro formulario-tipos de
campo
Campos de
texto
text
textarea
email
integer
money
number
password
percent
search
url

Campos de
seleccin
choice
entity
country
language
locale
timezone

Campos de
fecha y hora
date
datetime
time
birthday
Otros
campos
checkbox
file
radio

Campos para
grupos
collection
repeated
Campos
ocultos
hidden
csrf
Campos
base
field
form

Nuestro formulario dataClass

Cada formulario debe conocer el nombre de la clase asociada al objeto manejado por el
formulario. Por lo general, esta informacin se deduce automticamente en funcin del objeto
que se pasa como segundo argumento del mtodo createForm, aunque es recomendable
indicarlo:
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'SymfonyZgz\PruebaBundle\Entity\Prueba'
));
}

Nuestro formulario getName


Simplemente devuelve un identificador nico para este tipo de formulario.
public function getName()
{
return prueba;
}

Nuestro formulario Validaciones


El mtodo $form->isValid() en realidad es un atajo que pregunta al objeto $prueba si tiene datos
vlidos o no.
Validacin en archivo yml
# SymfonyZgz/PruebaBundle/Resources/config/validation.yml
SymfonyZgz\PruebaBundle\Entity\Prueba:
properties:
name:
- NotBlank: ~
surname:
- NotBlank: ~

Nuestro formulario Validaciones


Validacin con anotaciones:
use Symfony\Component\Validator\Constraints as Assert;
class Prueba
{
/**
* @Assert\NotBlank()
*/
public $name;
/**
* @Assert\NotBlank()
*/
protected $surname;
}

Las vistas
Se crean en la carpeta:
src/SymfonyZgz/PruebaBundle/Resources/views/<nombre_controller>
En nuesto caso:
src/SymfonyZgz/PruebaBundle/Resources/views/Prueba
index.html.twig
edit.html.twig
view.html.twig
Si en lugar de utilizar Twig, quisisemos utitilizar PHP, bastara con
cambiar la extensin de la vista:
index.html.php
edit.html.php

Las vistas - index.html.twig


{% extends '::base.html.twig' %}
{% block body %}
<h1>Listado</h1>
<ul>
{% for row in results %}
<li>
{{ row.name }}
<a href="{{ path('prueba_view', { 'id': row.id }) }}">ver</a>
<a href="{{ path('prueba_edit', { 'id': row.id }) }}">edit</a>
<a href="{{ path('prueba_delete', { 'id': row.id }) }}">borrar</a>
</li>
{% endfor %}
</ul>
<a href="{{ path('prueba_new') }}">Nueva</a>
{% endblock %}

Las vistas - view.html.twig


{% extends '::base.html.twig' %}
{% block body %}
<h1>Ver</h1>
Id: {{ prueba.id }}<br/>
Name {{ prueba.name }}<br/>
Surname {{ prueba.surname }}<br/>
Email {{ prueba.email }}<br/>
Phone {{ prueba.phone }}<br/>
<br/>
<a href="{{ path('prueba_edit', { 'id': prueba.id }) }}">edit</a>
<a href="{{ path('prueba_delete', { 'id': prueba.id }) }}">borrar</a>
<a href="{{ path('prueba') }}">Listado</a>
{% endblock %}

Las vistas - edit.html.twig


{% extends '::base.html.twig' %}
{% block body %}
<h1>Edicin</h1>
{{ form_start(form) }}
{{ form_errors(form) }}
{{ form_row(form.name) }}
{{ form_row(form.surname) }}
{{ form_row(form.email) }}
{{ form_row(form.phone) }}
{{ form_row(form.save) }}
{{ form_end(form) }}
<a href="{{ path('prueba') }}">Listado</a>
{% endblock %}

Las vistas - Formularios


form_start(form), muestra la etiqueta <form> de apertura del formulario.
form_errors(form), muestra los errores globales del formulario (los errores
especficos se muestran al lado de cada campo de formulario errneo).
form_row(form.name), muestra el ttulo, los errores (si los hay) y las etiquetas HTML
necesarias para mostrar el campo indicado (por ejemplo, dueDate). Por defecto todos
estos elementos se agrupan dentro de una etiqueta <div>.
form_end(form), muesta la etiqueta </form> de cierre del formulario y todos los
campos de formulario que no se han mostrado todava. Por lo general es buena idea
utilizar este helper en la parte inferior de cada formulario (por si te has olvidado de
mostrar algn campo o para no tener que mostrar uno a uno los campos ocultos del
formulario). Este helper tambin es muy til para mostrar automticamente el campo
oculto relacionado con la proteccin CSRF.
Si quisisemos tener ms control a la hora de pintar los campos, podramos utilizar
en lugar de form_row:
{{ form_label(form.name) }}
{{ form_errors(form.mane) }}
{{ form_widget(form.name, { 'attr': {'class': 'mi_class'} }) }}

Las vistas - Un poco ms


Uso de funciones:
{{ prueba.descripcion | striptags }}
{{ prueba.name | upper }}
Todos los filtros de Symfony2 se pueden encadenar para aplicarlos en cascada
{{ prueba.descripcion | striptags | upper }}
Fechas:
{{ prueba.fecha | date('d/m/Y') }}
Asignar un valor a las variables que no existen o estn vacas.
{{ descripcion | default('Presentacin de Symfony Zgz') }}
Twig por defecto escapa los caracteres hml. Para no aplicar el mecanismo de
escape en una determinada variable
{{ producto.descripcion | raw }}

Las vistas - Un poco ms


Declarar variables:
{% set variable = valor %}
Arrays:
{% set miArray = [4, 8, 18] %}
Estructuras de control
{% for articulo in articulos %}
{# ... #}
{% endfor %}
{% if articulos is divisibleby(5) %}
{# ... #}
{% endif %}

Las vistas - Herencia


Plantilla base:
# base.html.twig #}
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>{% block titulo %}{% endblock %}</title>
<link href="estilos.css" rel="stylesheet" type="text/css" />
</head>
<body>
{% block contenido %}{% endblock %}
</body>
</html>

Las vistas - Herencia


{% extends 'base.html.twig' %}
{% block titulo %}Aqu pondramos el ttulo{% endblock %}
{% block contenido %}
Y aqu el contenido
{% endblock %}
Reutilizando el contenido de los bloques:
{% block contenido %}
<h1>{{ block('titulo') }}</h1>
Y aqu el contenido
{% endblock %}

Las vistas - Herencia


Anidando bloques
{% block contenido %}
<article>
{% block principal %}
<section></section>
{% endblock principal %}
{% block secundario %}
<aside></aside>
{% endblock secundario %}
</article>
{% endblock contenido %}

Las vistas - Herencia


Herencia dinmica
{% extends opciones.compacta ? 'listado.html.twig' : 'tabla.html.twig' %}
Reutilizacin
{% include '::admin/header.html.twig' %}
Reutilizacin dinmica
{% for oferta in ofertas %}
{% include oferta.tipo == 'destacada' ?
'destacada.html.twig' : 'oferta.html.twig' %}
{% endfor %}

Tengo una pregunta !!!

Si esto se repite en
las mayora de proyectos
no hay un comando?

Generar CRUD por consola


Todo el tiempo dedicado a realizar este CRUD podramos
haber ejecutado este comando y habernos ido de caas :)
php app/console generate:doctrine:crud
--entity=PruebaBundle:Prueba
--format=yml --with-write

Gracias por su atencin !

https://groups.google.com/forum/#!forum/symfony-zaragoza
@symfony_zgz
@david_labarta
@grisendo

Preguntas?

Bibliografa
http://symfony.com/doc
Desarrollo web gil con Symfony2:
http://symfony.es/libro/
Symfony 2.4, el libro oficial:
http://librosweb.es/symfony_2_x/

Anda mungkin juga menyukai