Вы находитесь на странице: 1из 192

Frameworks de desarrollo

Symfony
Clase 1

Javier Eguíluz
javier.eguiluz@gmail.com
Esta obra dispone de una licencia de tipo Creative
Commons Reconocimiento‐No comercial‐ Compartir 
bajo la misma licencia 3.0 

Se prohíbe explícitamente el uso de este material en 
actividades de formación comerciales

http://creativecommons.org/licenses/by‐nc‐sa/3.0/es/
This work is licensed under a Creative Commons
Attribution‐Noncommercial‐Share Alike 3.0 

The use of these slides in commercial courses or


trainings is explicitly prohibited

http://creativecommons.org/licenses/by‐nc‐sa/3.0/es/
Capítulo 1

Comenzando el 
proyecto
¿Qué es 
Symfony?
Framework para el 
desarrollo de aplicaciones 
web con PHP
• El más profesional

• El más documentado

• El mejor
PHP      Frameworks
Productividad

Calidad programación

Mantenimiento

Rendimiento aplicación
Curva de aprendizaje 
de Symfony
aprendizaje

tiempo
¿Qué es Jobeet?
diciembre 2008
1 2 3 4 5 6 7

8 9 10 11 12 13 14

15 16 17 18 19 20 21

22 23 24 25 26 27 28

29 30 31
La mejor forma de aprender 
Symfony 1.2 a través de 24
tutoriales de 1 hora
Un tutorial
diferente
• Serio

• Profesional

• Completo
Prerrequisitos
5.2.4
Instalación de 
Symfony
http://www.symfony‐project.org/installation/1_2

symfony‐1.2.4.tgz
check_configuration.php
$ php lib/vendor/symfony/data/bin/symfony
Preparar el 
proyecto
frontend backend
proyecto
aplicación jobeet

frontend backend
$ symfony generate:project jobeet

apps/ log/
cache/ plugins/
config/ test/
lib/ web/
frontend/
$ symfony config/
generate:app
jobeet lib/
‐‐escaping‐strategy=on
‐‐csrf‐secret=UniqueSecret modules/
frontend templates/
‐‐escaping‐strategy XSS
‐‐csrf‐secret CSRF
config/ProjectConfiguration.class.php

require_once dirname(__FILE__).
'/../lib/vendor/'.
'symfony/lib/autoload/'.
'sfCoreAutoload.class.php';
Los entornos
• Entorno de desarrollo (dev)
• Entorno de pruebas
• Entorno intermedio
• Entorno de producción (prod)
Errores en el entorno de desarrollo (dev)
Errores en el entorno de producción (prod)
web/index.php
<?php

require_once(dirname(__FILE__).
'/../config/ProjectConfiguration.class.php');

$configuration = 
ProjectConfiguration::getApplicationConfiguration(
'frontend',
'prod',
false
);

sfContext::createInstance($configuration)‐>dispatch();
Configurar bien el 
servidor web
<VirtualHost 127.0.0.1:80>
ServerName jobeet.localhost
DocumentRoot "/home/sfprojects/jobeet/web"
DirectoryIndex index.php

<Directory "/home/sfprojects/jobeet/web">
AllowOverride All
Allow from All
</Directory>

Alias /sf /home/sfprojects/jobeet/lib/vendor/symfony/data/web/sf
<Directory "/home/sfprojects/jobeet/lib/vendor/symfony/data/web/sf">
AllowOverride All
Allow from All
</Directory>
</VirtualHost>
/etc/hosts
c:\windows\system32\drivers\etc\hosts

127.0.0.1    jobeet.localhost
http://jobeet.localhost/

prod
http://jobeet.localhost/frontend_dev.php

dev
Versionado de 
código
Capítulo 2

El proyecto
La idea del 
proyecto
Aplicación de software 
libre que permite crear 
sitios web de búsqueda 
de empleo
características

• Completo y personalizable
• Multilingüe
• AJAX, RSS y API
Los escenarios del 
proyecto
• administrador (admin)
• usuario (user)
• publicador (poster)
• afiliado (affiliate)
F1
El usuario accede a 
la portada y ve las 
últimas ofertas de 
trabajo activas
F2
El usuario puede 
visualizar todas 
las ofertas de 
trabajo de una 
categoría
F3
El usuario refina el 
listado mediante 
palabras clave
F4
El usuario pincha 
sobre una oferta de 
trabajo para ver 
más información
F5
El usuario publica 
una nueva oferta 
de trabajo
F6
El usuario quiere 
convertirse en un 
afiliado
F7
Un usuario afiliado 
obtiene la lista de 
ofertas de trabajo 
activas
B1
El administrador configura el sitio web

B2
El administrador gestiona las ofertas de 
trabajo
B3
El administrador gestiona los afiliados
Capítulo 3

El modelo de 
datos
El modelo 
relacional
relacional objetos

ORM
1. Describir la base de datos
2. Generar las clases PHP
3. Trabajar con objetos en vez 
de SQL
El formato YAML
YAML
Formato para serializar datos que 
es fácil de leer por las personas y es 
compatible con todos los lenguajes 
de programación
$casa = array(
'familia' => array(
'apellido' => 'García',
'padres' => array('Antonio', 'María'),   
'hijos' => array('Jose', 'Manuel')
),
'direccion' => array(
'numero' => 34,
'calle' => 'Gran Vía',
'ciudad' => 'Cualquiera',
'codigopostal' => '12345'
)
);
casa:
familia:
apellido: García
padres:
‐ Antonio
‐ María
hijos:
‐ Jose
‐ Manuel
direccion:
numero: 34
calle: Gran Vía
ciudad: Cualquiera
codigopostal: "12345"
casa:
familia: { apellido: García, padres: [Antonio, 
María], hijos: [Jose, Manuel] }
direccion: { numero: 34, direccion: Gran Vía, 
ciudad: Cualquiera, codigopostal: "12345" }
Sintaxis
clave: clave:
clave: valor
clave: valor
clave:
clave: valor
clave:
‐ valor
2 espacios 
‐ valor
en blanco
Arrays normales
clave:
‐ valor1
‐ valor2
‐ valor3

clave:[valor1, valor2, valor3]
Arrays asociativos
clave:
clave1: valor1
clave2: valor2
clave3: valor3
clave: { clave1: valor1, 
clave2: valor2, clave3: valor3}
<?xml version="1.0"?>
<club>
XML YAML
<players> players:
<player id="kramnik" name="Vladimir Vladimir Kramnik: &kramnik
Kramnik" rating="2700" status="GM" />  rating: 2700
<player id="fritz" name="Deep status: GM
Fritz" rating="2700" status="Computer"  Deep Fritz: &fritz
/> rating: 2700
<player id="mertz" name="David 
status: Computer
Mertz" rating="1400" status="Amateur" 
/> David Mertz: &mertz
</players> rating: 1400
<matches> status: Amateur
<match> matches:
<Date>2002‐10‐04</Date> ‐
<White refid="fritz" />  Date: 2002‐10‐04
<Black refid="kramnik" />  White: *fritz
<Result>Draw</Result> 
Black: *kramnik
</match>
<match> Result: Draw
<Date>2002‐10‐06</Date> ‐
<White refid="kramnik" /> Date: 2002‐10‐06
<Black refid="fritz" /> White: *kramnik
<Result>White</Result> Black: *fritz
</match> Result: White
</matches>
</club> 
El esquema
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 }
config/ schema.yml
propel:
jobeet_category:
id:   ~
name: { type: varchar(255),
required: true,
index: unique
}
jobeet_job:
config/ schema.yml
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:   ~
config/ schema.yml

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: ~
config/ schema.yml
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
}
config/ schema.yml
• type: boolean, tinyint, smallint, integer, bigint, double, float, 
real, decimal, char, varchar(size), longvarchar, date, time, 
timestamp, blob, clob

• required: true, false
• index: true, false
• primaryKey: true, false
• foreignKey, foreignReference
La base de datos
$ mysqladmin ‐uroot ‐p create jobeet

$ symfony configure:database
“mysql:host=localhost;dbname=jobeet”
root ConTraSenA

config/databases.yml
El ORM
$ symfony propel:build‐sql
data/sql/

$ symfony propel:insert‐sql ‐‐no‐confirmation

$ symfony propel:build‐model
lib/model/
extends
• JobeetJob
• BaseJobeetJob
• JobeetJobPeer extends

• BaseJobeetJobPeer
$job = new JobeetJob();
$job‐>setPosition('Web developer');
$job‐>save();

echo $job‐>getPosition();

$job‐>delete();
$category = new JobeetCategory(); 
$category‐>setName('Programming');

$job = new JobeetJob();


$job‐>setCategory($category);
$ symfony propel:build‐all ‐‐no‐confirmation
$ symfony propel:build‐sql
$ symfony propel:insert‐sql
$ symfony propel:build‐model
$ symfony propel:build‐forms
+ $ symfony propel:build‐filters

$ symfony propel:build‐all
$ symfony cc
• Borra la caché de Symfony
• Ejecutar siempre que añades 
clases (autoload)
• La solución de casi todos los 
errores de los principiantes
$ symfony cache:clear
$ symfony cache:cl
$ symfony ca:c
$ symfony cc
Los datos iniciales
data/fixtures/

• Datos iniciales
• Datos de prueba
• Datos de usuarios
data/fixtures/ 010_categories.yml

JobeetCategory:
design:        { name: Design }
programming:   { name: Programming }
manager:       { name: Manager }
administrator: { name: Administrator }
data/fixtures/ 020_jobs.yml
JobeetJob:
job_sensio_labs:
category_id:  programming
type:         full‐time
company:      Sensio Labs
logo:         sensio‐labs.gif
url:          http://www.sensiolabs.com/
position:     Web Developer
location:     Paris, France
description:  |
You have already developed websites with symfony and you want
to work with Open‐Source technologies. You have a minimum of 
3 years experience in web development with PHP or Java and
you wish to participate to development of Web 2.0 sites using
the best frameworks available.
how_to_apply: |
Send your resume to fabien.potencier [at] sensio.com
is_public:    true
is_activated: true
token:        job_sensio_labs
email:        job@example.com
expires_at:   2010‐10‐10
$ symfony propel:data‐load
$ symfony propel:build‐sql
$ symfony propel:insert‐sql
$ symfony propel:build‐model
$ symfony propel:build‐forms
$ symfony propel:build‐filters
+ $ symfony propel:data‐load

$ symfony propel:build‐all‐load
Probando la 
aplicación en el 
navegador
proyecto
aplicación jobeet

frontend backend

job
módulo
$ symfony propel:generate‐module
‐‐with‐show ‐‐non‐verbose‐templates
frontend job JobeetJob

frontend/modules/job
actions/
templates/
frontend/modules/job/actions/actions.class.php

index edit
show update
new delete
create
http://jobeet.localhost/frontend_dev.php/job

frontend
_dev
job
Objeto Representación 
textual

Categoría
_ _toString()
lib/model/ JobeetCategory.php

class JobeetCategory extends BaseJobeetCategory


{
public function __toString()
{
return $this‐>getName();
}
}
lib/model/ JobeetJob.php
class JobeetJob extends BaseJobeetJob
{
public function __toString()
{
return sprintf(
'%s at %s (%s)',
$this‐>getPosition(),
$this‐>getCompany(),
$this‐>getLocation()
);
}
}
lib/model/ JobeetAffiliate.php

class JobeetAffiliate extends BaseJobeetAffiliate


{
public function __toString()
{
return $this‐>getUrl();
}
}
http://jobeet.localhost/frontend_dev.php/job
Capítulo 4

El controlador y 
la vista
La arquitectura MVC
¿Cómo se programaba con PHP en 
el siglo pasado?

1 página del  1 archivo PHP 


sitio web = diferente
¿Cómo se programaba con PHP en 
el siglo pasado?
inicialización y 
configuración
lógica de 
negocio

acceso a BBDD

generar 
código HTML

pagina.php
Modelo
Vista
Controlador
Modelo
Directorio /lib/model
Vista
Directorios templates/
Controlador
Archivos index.php y frontend_dev.php
Archivos actions.class.php
El layout
patrón de diseño decorator

apps/frontend/templates/layout.php
apps/frontend/templates/ layout.php
<!DOCTYPE html PUBLIC "‐//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1‐transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Jobeet ‐ Your best job board</title>
<link rel="shortcut icon" href="/favicon.ico" />
<?php include_javascripts() ?>
<?php include_stylesheets() ?>
</head>
<body>
...
<div class="content">
<?php echo $sf_content ?>
</div>
</body>
</html>
Plantillas Symfony

• Archivos PHP 
normales
• Existe un plugin 
para Smarty
• Symfony 2.0 podría 
incluir plantillas
Las hojas de estilos, 
imágenes y archivos 
JavaScript
helpers
<head>
...
<?php include_stylesheets() ?>
</head>
apps/frontend/config/ view.yml
default:
http_metas:
content‐type: text/html
metas:
#title: symfony project
#description: symfony project
#keywords: symfony, project
#language: en
#robots: index, follow

stylesheets: [main.css]

javascripts: []

has_layout: on
layout: layout
apps/frontend/config/ view.yml
default:
...
stylesheets:  [main.css, jobs.css, job.css]
...

<link rel="stylesheet" type="text/css" 
media="screen" href="/css/main.css" />
<link rel="stylesheet" type="text/css" 
media="screen" href="/css/jobs.css" />
<link rel="stylesheet" type="text/css" 
media="screen" href="/css/job.css" />
apps/frontend/config/ view.yml
default:
...
stylesheets:  [main.css, jobs.css, job]
...

<link rel="stylesheet" type="text/css" 
media="screen" href="/css/main.css" />
<link rel="stylesheet" type="text/css" 
media="screen" href="/css/jobs.css" />
<link rel="stylesheet" type="text/css" 
media="screen" href="/css/job.css" />
apps/frontend/config/ view.yml
default:
...
stylesheets:  [main.css, /css/v2/jobs.css]
...

<link rel="stylesheet" type="text/css" 
media="screen" href="/css/main.css" />
<link rel="stylesheet" type="text/css" 
media="screen" href="/css/v2/jobs.css" />
apps/frontend/config/ view.yml
default:
...
stylesheets: [main.css, jobs: { media: print } ]
...

<link rel="stylesheet" type="text/css" 
media="screen" href="/css/main.css" />
<link rel="stylesheet" type="text/css" 
media="print" href="/css/jobs.css" />
metas:
title: El título 1 Symfony
metas:
title: El título 2 Proyecto
metas:
title: El título 3 Aplicación
metas:
title: El título 4 Módulo

view.yml
Symfony
lib/vendor/symfony/lib/config/config/view.yml
Proyecto
config/view.yml
Aplicación
apps/frontend/config/view.yml
Módulo
apps/frontend/modules/job/config/view.yml
metas:
stylesheets: [job]

<?php
use_stylesheet(‘job.css’) view.yml
?>

plantilla
plantilla
La portada del módulo 
de las ofertas de 
trabajo
apps/
frontend/
modules/
job/
actions/
actions.class.php
templates/
indexSuccess.php
acción
= +
plantilla
http://jobeet.localhost/frontend_dev.php/job/index

frontend (aplicación)
_dev (entorno)
job (módulo)
index (acción executeIndex y 
plantilla indexSuccess)
apps/frontend/modules/job/actions/ actions.class.php

class jobActions extends sfActions


{
public function executeIndex(sfWebRequest $request)
{
$this‐>jobeet_job_list =
JobeetJobPeer::doSelect(new Criteria());
}

// ...
}
SELECT
[ALL | DISTINCT | DISTINCTROW ]
[HIGH_PRIORITY]
[STRAIGHT_JOIN]
[SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]
[SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS]
select_expr [, select_expr ...]
[FROM table_references
[WHERE where_condition]
[GROUP BY {col_name | expr | position}
[ASC | DESC], ... [WITH ROLLUP]]
[HAVING where_condition]
[ORDER BY {col_name | expr | position}
[ASC | DESC], ...]
[LIMIT {[offset,] row_count | row_count OFFSET offset}]
[PROCEDURE procedure_name(argument_list)]
[INTO OUTFILE 'file_name' export_options
| INTO DUMPFILE 'file_name'
| INTO var_name [, var_name]]
[FOR UPDATE | LOCK IN SHARE MODE]]
apps/frontend/modules/job/templates/ indexSuccess.php

<?php foreach ($jobeet_job_list as $jobeet_job): ?>


...
<td>
<a href="...">
<?php echo $jobeet_job‐>getId() ?>
</a>
</td>
...
<?php endforeach; ?> 
La plantilla de la página 
de una oferta de 
trabajo
Slots
<title>Jobeet</title> <title>

layout plantilla
<title>             </title> Título de la página

layout plantilla
apps/frontend/templates/ layout.php
<title>
<?php include_slot('title') ?>
</title>

apps/frontend/modules/job/templates/ indexSuccess.php
<?php slot('title', 'Título de la página') ?> 

<?php slot(
'title',
sprintf('%s is looking for a %s',
$job‐>getCompany(),
$job‐>getPosition()
)
) ?> 
La acción de la página 
de una oferta de 
trabajo
apps/frontend/modules/job/actions/ actions.class.php

public function executeShow(sfWebRequest $request)


{
$this‐>job = JobeetJobPeer::retrieveByPk(
$request‐>getParameter('id')
);

$this‐>forward404Unless($this‐>job);
}
La petición y la 
respuesta
objeto sfWebRequest

class jobActions extends sfActions


{
public function executeShow(sfWebRequest $request)
{
$peticion = $request;
$origen = $peticion‐>getReferer();
$metodo = $peticion‐>getMethod();
}

// ...
}
Nombre del método Equivalente de PHP
getMethod() $_SERVER['REQUEST_METHOD']

getUri() $_SERVER['REQUEST_URI']

getReferer() $_SERVER['HTTP_REFERER']

getHost() $_SERVER['HTTP_HOST']

getLanguages() $_SERVER['HTTP_ACCEPT_LANGUAGE']

getCharsets() $_SERVER['HTTP_ACCEPT_CHARSET']

isXmlHttpRequest() $_SERVER['X_REQUESTD_WITH'] == 'XMLHttpRequest'

getHttpHeader() $_SERVER

getCookie() $_COOKIE

isSecure() $_SERVER['HTTPS']

getFiles() $_FILES

getGetParameter() $_GET

getPostParameter() $_POST

getUrlParameter() $_SERVER['PATH_INFO']

getRemoteAddress() $_SERVER['REMOTE_ADDR']
public function executeShow(sfWebRequest $request)
{
...
$request‐>getParameter('id');

...

/ruta1/ruta2/ruta3?id=3&clave1=
valor1&clave2=valor2
objeto sfWebResponse

class jobActions extends sfActions


{
public function executeShow(sfWebRequest $request)
{
$respuesta = $this‐>getResponse();
$respuesta‐>setStatusCode(404);
$respuesta‐>addStyleSheet('/css/job.css');
$respuesta‐>setTitle('Título de la página');
}

// ...
}
archivo de configuración
metas:
stylesheets: [job]

plantilla
<?php use_stylesheet('job.css') ?>

acción
$this‐>getResponse()‐>
addStyleSheet('/css/job.css');
Capítulo 5

El sistema de 
enrutamiento
URL
internet symfony

URL URI
sistema de 
enrutamiento
URI 'job/show?id='.$job‐>getId()

url_for()

URL job/show/id/1
URI

modulo/accion?clave1=
valor1&clave2=valor2&
...
Configurando el 
enrutamiento
apps/frontend/config/ routing.yml
homepage:
url: /
param: { module: default, action: index }

default_index:
url: /:module
param: { action: index }

default:
url: /:module/:action/*
nombre
default_index: patrón
url: /:module
param: { action: index }

parámetros
homepage:
url: /
param: { module: default, action: index }

default_index:
url: /:module
param: { action: index }

default:
url: /:module/:action/* 

/job
1 /frontend_dev.php/job
aplicación entorno ???

¿módulo? ¿acción?
2 apps/frontend/config/routing.yml
default_index:
/job url: /:module
param: { action: index }

:module = job = módulo
3 apps/frontend/config/routing.yml
default_index:
url: /:module acción = index
param: { action: index }

4 /frontend_dev.php/job
aplicación = frontend módulo = job
entorno = dev acción = index
URI url_for() URL

url_for('job/show?id='.$job‐>getId())

/job/show/id/1
URI url_for() URL

url_for('@default?id='.$job‐>getId())
Personalizando el 
enrutamiento
apps/frontend/config/ routing.yml
homepage:
url: /
param: { module: job, action: index }

default_index:
url: /:module
param: { action: index }

default:
url: /:module/:action/* 
<h1>
<a href="<?php echo url_for('@homepage') ?>">
<img src="/images/jobeet.gif" alt="Jobeet" />
</a>
</h1>
/job/sensio‐labs/paris‐france/1/web‐developer

1. Identificar el patrón de la URL

2. Incluir la ruta a routing.yml

3. Añadir las restricciones adecuadas
/job/sensio‐labs/paris‐france/1/web‐developer

1. Identificar el patrón de la URL

/job/:company/:location/:id/:position
/job/sensio‐labs/paris‐france/1/web‐developer

2. Incluir la ruta en routing.yml

job_show_user:
url:   /job/:company/:location/:id/:position
param: { module: job, action: show }
url_for('job/show?'.
'id='.$job‐>getId().
'&company='.$job‐>getCompany().
'&location='.$job‐>getLocation().
'&position='.$job‐>getPosition()
)
url_for(array(
'module' => 'job',
'action' => 'show',
'id' => $job‐>getId(),
'company' => $job‐>getCompany(),
'location' => $job‐>getLocation(),
'position' => $job‐>getPosition(), 
))
Requisitos
/job/sensio‐labs/paris‐france/1/web‐developer

3. Añadir las restricciones adecuadas

job_show_user:
url:   /job/:company/:location/:id/:position
param: { module: job, action: show }
requirements:
id: \d+
La clase sfRoute
HTTP     Navegadores      Symfony
GET
POST
HEAD
PUT
DELETE
job_show_user:
url:     /job/:company/:location/:id/:position
class: sfRequestRoute
param:   { module: job, action: show }
requirements:
id: \d+
sf_method: [get]
La clase para las 
rutas basadas en 
objetos
url_for('job/show?'.
'id='.$job‐>getId().
'&company='.$job‐>getCompany().
'&location='.$job‐>getLocation().
'&position='.$job‐>getPosition()
)
job_show_user:
url:      /job/:company/:location/:id/:position
class:  sfPropelRoute
options:
model: JobeetJob
type:  object
param:     { module: job, action: show }
requirements:
id: \d+
sf_method: [get]
url_for('job/show?'.
'id='.$job‐>getId().
'&company='.$job‐>getCompany().
'&location='.$job‐>getLocation().
'&position='.$job‐>getPosition()
)

url_for('job_show_user', $job)

url_for(array(
'sf_route' => 'job_show_user',
'sf_subject' => $job
))
Lo que queremos…
/job/sensio‐labs/paris‐france/1/web‐developer

Lo que tenemos…
/job/Sensio+Labs/Paris%2C+France/1/Web+Developer
getId()
id
name getName()
description
... Job getDescription()

getSlug()
schema.yml getShortDescription()
getters
virtuales
slug

Comienza el curso de Symfony en Vitoria‐Gasteiz

www.symfony.es/2009/01/29/comienza‐el‐curso‐de‐symfony‐en‐vitoria‐gasteiz

Twitto, el framework PHP más pequeño

www.symfony.es/2009/01/11/twitto‐el‐framework‐php‐mas‐pequeno/
getId()
id
name getName()
description
... Job getDescription()
getCompanySlug()

schema.yml getPositionSlug()
getLocationSlug()
getters
virtuales
lib/model/ JobeetJob.php
public function getCompanySlug() {
return Jobeet::slugify($this‐>getCompany());
}

public function getPositionSlug() {


return Jobeet::slugify($this‐>getPosition());
}

public function getLocationSlug() {


return Jobeet::slugify($this‐>getLocation());
}
lib/ Jobeet.class.php
class Jobeet
{
static public function slugify($text)
{
// replace all non letters or digits by ‐
$text = preg_replace('/\W+/', '‐', $text);

// trim and lowercase


$text = strtolower(trim($text, '‐'));

return $text;
}
}
job_show_user:
url: /job/:company_slug/:location_slug/:id/:position_slug
class:   sfPropelRoute
options: { model: JobeetJob, type:  object }
param:   { module: job, action: show }
requirements:
id: \d+
sf_method: [get]
class jobActions extends sfActions
{
public function executeShow(sfWebRequest $request)
{
$this‐>job = JobeetJobPeer::retrieveByPk($request‐>getParameter('id'));
$this‐>forward404Unless($this‐>job);
}

// ...
}

class jobActions extends sfActions


{
public function executeShow(sfWebRequest $request)
{
$this‐>job = $this‐>getRoute()‐>getObject(); 
}

// ...
}
Enrutamiento en 
acciones y 
plantillas
<?php echo link_to(
"Texto del enlace",
'job_show_user',
$job
) ?>

<a href="
<?php echo url_for(
'job_show_user',
$job,
true
); ?>">
Texto del enlace
</a>
class jobActions extends sfActions
{
public function executeIndex(sfWebRequest $request)
{
// ...

$this‐>redirect(
$this‐>generateUrl('job_show_user', $job)
);
}

// ...
}
La clase de las 
colecciones de 
rutas
job:
class:   sfPropelRouteCollection
options: { model: JobeetJob }

job_show_user:
url: /job/:company_slug/:location_slug/:id/:position_slug
class: sfPropelRoute
options: { model: JobeetJob, type:  object }
param: { module: job, action: show }
requirements:
id: \d+
sf_method: [get]
$ php symfony app:routes frontend

Вам также может понравиться