Frameworks de desarrollo

Symfony
Clase 1

                       Javier Eguíluz
                       javier.eguiluz@gma...
Esta obra dispone de una licencia de tipo Creative
Commons Reconocimiento‐No comercial‐ Compartir 
             bajo la mi...
This work is licensed under a Creative Commons
  Attribution‐Noncommercial‐Share Alike 3.0 




    The use of these slide...
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...
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                jobeet
aplicación




                                 backend
             frontend
$ symfony generate:project jobeet

    apps/            log/
    cache/           plugins/
    config/          test/
    ...
frontend/
$ symfony                       config/
generate:app
                                lib/
jobeet
‐‐escaping‐stra...
‐‐escaping‐strategy   XSS
      ‐‐csrf‐secret   CSRF
config/ProjectConfiguration.class.php


require_once dirname(__FILE__).
  '/../lib/vendor/'.
  'symfony/lib/autoload/'.
  ...
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 = 
Pr...
Configurar bien el 
  servidor web
<VirtualHost 127.0.0.1:80>
 ServerName jobeet.localhost
 DocumentRoot quot;/home/sfprojects/jobeet/webquot;
 DirectoryInde...
/etc/hosts
  c:windowssystem32driversetchosts



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 gesti...
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 
     ...
$casa = array(
   'familia' => array(
      'apellido' => 'García',
      'padres'   => array('Antonio', 'María'),   
    ...
casa:
  familia:
    apellido: García
    padres:
      ‐ Antonio
      ‐ María
    hijos:
      ‐ Jose
      ‐ Manuel
  d...
casa:
  familia: { apellido: García, padres: [Antonio, 
María], hijos: [Jose, Manuel] }
  direccion: { numero: 34, direcci...
Sintaxis
clave:             clave:
  clave: valor
                     clave: valor
  clave:
    clave: valor
    clave:
 ...
Arrays normales
clave:
  ‐ valor1
  ‐ valor2
  ‐ valor3

clave:[valor1, valor2, valor3]
Arrays asociativos
clave:
  clave1: valor1
  clave2: valor2
  clave3: valor3
clave: { clave1: valor1, 
clave2: valor2, cla...
<?xml version=quot;1.0quot;?>
                                XML                                YAML
<club>
             ...
El esquema
config/schema.yml
propel:
  jobeet_category:
    id:   ~
    name: { type: varchar(255), required: true, index: unique }
 ...
config/schema.yml


propel:
  jobeet_category:
    id:   ~
    name: { type: varchar(255),
            required: true,
   ...
config/schema.yml
jobeet_job:
    id:           ~
    category_id:  { type: integer, foreignTable: jobeet_category, 
forei...
config/schema.yml



jobeet_affiliate:
    id:         ~
    url:        { type: varchar(255), required: true }
    email:...
config/schema.yml
jobeet_category_affiliate:
    category_id:  {
      type: integer,
      foreignTable: jobeet_category,...
config/schema.yml


    type: boolean, tinyint, smallint, integer, bigint, double, float, 
•
    real, decimal, char, varc...
La base de datos
$ mysqladmin ‐uroot ‐p create jobeet


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

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

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

$ symfony propel...
extends
    JobeetJob
•
    BaseJobeetJob
•
                          extends
    JobeetJobPeer
•
    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‐for...
$ symfony cc
   Borra la caché de Symfony
•
• Ejecutar siempre que añades 
  clases (autoload)
• La solución de casi todos...
$ 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: Programmin...
data/fixtures/020_jobs.yml
JobeetJob:
  job_sensio_labs:
    category_id:  programming
    type:         full‐time
    com...
$ symfony propel:data‐load
$ symfony propel:build‐sql
    $ symfony propel:insert‐sql
    $ symfony propel:build‐model
    $ symfony propel:build‐for...
Probando la 
aplicación en el 
  navegador
proyecto                jobeet
aplicación




                                 backend
             frontend



          ...
$ symfony propel:generate‐module
‐‐with‐show ‐‐non‐verbose‐templates
frontend job JobeetJob

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



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



 frontend
 _dev
 job
Representación 
    Objeto       textual



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


class JobeetCategory extends BaseJobeetCategory
{
  public function __toString()
  {
    re...
lib/model/JobeetJob.php

class JobeetJob extends BaseJobeetJob
{
  public function __toString()
  {
    return sprintf(
  ...
lib/model/JobeetAffiliate.php



class JobeetAffiliate extends BaseJobeetAffiliate
{
  public function __toString()
  {
  ...
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 
                =
  siti...
¿Cómo se programaba con PHP en 
            el siglo pasado?
                                inicialización y 
           ...
Modelo
Vista
Controlador
Modelo
 Directorio /lib/model
Vista
 Directorios templates/
Controlador
 Archivos index.php y frontend_dev.php
 Archivos a...
El layout
patrón de diseño decorator




apps/frontend/templates/layout.php
apps/frontend/templates/layout.php

<!DOCTYPE html PUBLIC quot;‐//W3C//DTD XHTML 1.0 Transitional//ENquot;
quot;http://www...
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
    ...
apps/frontend/config/view.yml
default:
  ...
  stylesheets:  [main.css, jobs.css, job.css]
 ...



<link rel=quot;styleshe...
apps/frontend/config/view.yml
default:
  ...
  stylesheets:  [main.css, jobs.css, job]
 ...



<link rel=quot;stylesheetqu...
apps/frontend/config/view.yml
default:
  ...
  stylesheets:  [main.css, /css/v2/jobs.css]
 ...



<link rel=quot;styleshee...
apps/frontend/config/view.yml
default:
 ...
stylesheets: [main.css, jobs: { media: print } ]
...



<link rel=quot;stylesh...
metas:
                                       Symfony
 title: El título 1
  metas:
                                       ...
Symfony
 lib/vendor/symfony/lib/config/config/view.yml
Proyecto
 config/view.yml
Aplicación
 apps/frontend/config/view.yml...
metas:
                               stylesheets: [job]

<?php
use_stylesheet(‘job.css’)                           view.y...
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ó...
apps/frontend/modules/job/actions/actions.class.php



class jobActions extends sfActions
{
  public function executeIndex...
SELECT
    [ALL | DISTINCT | DISTINCTROW ]
      [HIGH_PRIORITY]
      [STRAIGHT_JOIN]
      [SQL_SMALL_RESULT] [SQL_BIG_R...
apps/frontend/modules/job/templates/indexSuccess.php



<?php foreach ($jobeet_job_list as $jobeet_job): ?>
  ...
  <td>
 ...
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/t...
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 =...
La petición y la 
   respuesta
objeto sfWebRequest

class jobActions extends sfActions
{
  public function executeShow(sfWebRequest   $request)
  {
    $...
Nombre del método                  Equivalente de PHP
getMethod()           $_SERVER['REQUEST_METHOD']

getUri()          ...
public function executeShow(sfWebRequest $request)
{
  ...
  $request‐>getParameter('id');

    ...

}


/ruta1/ruta2/ruta...
objeto sfWebResponse

class jobActions extends sfActions
{
  public function executeShow(sfWebRequest $request)
  {
    $r...
archivo de configuración
 metas:
   stylesheets: [job]

plantilla
         use_stylesheet('job.css')
 <?php               ...
Capítulo 5

El sistema de 
enrutamiento
URL
internet     symfony




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

           url_for()

      job/show/id/1
URL
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: /...
nombre
                   patrón
default_index:
  url: /:module
  param: { action: index }

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

default_index:
  url: /:module
  param: { action: index }
...
/frontend_dev.php/job
1
                          entorno
        aplicación                     ???

                    ...
3    apps/frontend/config/routing.yml
default_index:
                             acción = index
  url: /:module
  param: ...
url_for()
URI                           URL

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


          /job/show/id/1
url_for()
URI                           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: /:modu...
<h1>
 <a href=quot;<?php echo url_for('@homepage') ?>quot;>
  <img src=quot;/images/jobeet.gifquot; alt=quot;Jobeetquot; /...
/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...
/job/sensio‐labs/paris‐france/1/web‐developer


1. Identificar el patrón de la URL


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


 2. Incluir la ruta en routing.yml

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


 3. Añadir las restricciones adecuadas

job_show_user:
 url:   /job/:compa...
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: ...
La clase para las 
rutas basadas en 
     objetos
url_for('job/show?'.
  'id='.$job‐>getId().
  '&company='.$job‐>getCompany().
  '&location='.$job‐>getLocation().
  '&posi...
job_show_user:
  url:      /job/:company/:location/:id/:position
  class:  sfPropelRoute
  options:
   model: JobeetJob
  ...
url_for('job/show?'.
  'id='.$job‐>getId().
  '&company='.$job‐>getCompany().
  '&location='.$job‐>getLocation().
  '&posi...
Lo que queremos…
/job/sensio‐labs/paris‐france/1/web‐developer


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

         ...
slug

Comienza el curso de Symfony en Vitoria‐Gasteiz

www.symfony.es/2009/01/29/comienza‐el‐curso‐de‐symfony‐en‐vitoria‐g...
getId()
id
name                       getName()
description
                Job        getDescription()
...

             ...
lib/model/JobeetJob.php

public function getCompanySlug() {
  return Jobeet::slugify($this‐>getCompany());
}

public funct...
lib/Jobeet.class.php

class Jobeet
{
  static public function slugify($text)
  {
    // replace all non letters or digits ...
job_show_user:
 url: /job/:company_slug/:location_slug/:id/:position_slug
 class:   sfPropelRoute
 options: { model: Jobee...
class jobActions extends sfActions
{
  public function executeShow(sfWebRequest $request)
  {
    $this‐>job = JobeetJobPe...
Enrutamiento en 
   acciones y 
    plantillas
<?php echo link_to(
  quot;Texto del enlacequot;,
  'job_show_user',
  $job
) ?>

<a href=quot;
  <?php echo url_for(
    ...
class jobActions extends sfActions
{
    public function executeIndex(sfWebRequest   $request)
    {
        // ...

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

job_show_user:
 url: /job/:company_slug/:location...
$ php symfony app:routes frontend
Curso Symfony - Clase 1
Curso Symfony - Clase 1
Curso Symfony - Clase 1
Curso Symfony - Clase 1
Curso Symfony - Clase 1
Curso Symfony - Clase 1
Curso Symfony - Clase 1
Curso Symfony - Clase 1
Curso Symfony - Clase 1
Upcoming SlideShare
Loading in …5
×

Curso Symfony - Clase 1

21,114 views

Published on

Presentación de la primera clase de un curso sobre el framework Symfony
--
Slides used in the first class of a symfony framework training.

Published in: Technology
3 Comments
39 Likes
Statistics
Notes
No Downloads
Views
Total views
21,114
On SlideShare
0
From Embeds
0
Number of Embeds
9,418
Actions
Shares
0
Downloads
0
Comments
3
Likes
39
Embeds 0
No embeds

No notes for slide
  • http://xkcd.com/285/
  • http://www.ibm.com/developerworks/xml/library/x-matters23.html
  • Curso Symfony - Clase 1

    1. 1. Frameworks de desarrollo Symfony Clase 1 Javier Eguíluz javier.eguiluz@gmail.com
    2. 2. 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/
    3. 3. 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/
    4. 4. Capítulo 1 Comenzando el  proyecto
    5. 5. ¿Qué es  Symfony?
    6. 6. Framework para el  desarrollo de aplicaciones  web con PHP
    7. 7. • El más profesional • El más documentado • El mejor
    8. 8. PHP      Frameworks Productividad Calidad programación Mantenimiento Rendimiento aplicación
    9. 9. Curva de aprendizaje  de Symfony aprendizaje tiempo
    10. 10. ¿Qué es Jobeet?
    11. 11. 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
    12. 12. La mejor forma de aprender  Symfony 1.2 a través de 24 tutoriales de 1 hora
    13. 13. Un tutorial diferente
    14. 14. • Serio • Profesional • Completo
    15. 15. Prerrequisitos
    16. 16. 5.2.4
    17. 17. Instalación de  Symfony
    18. 18. http://www.symfony‐project.org/installation/1_2 symfony‐1.2.4.tgz
    19. 19. check_configuration.php
    20. 20. $ php lib/vendor/symfony/data/bin/symfony
    21. 21. Preparar el  proyecto
    22. 22. frontend backend
    23. 23. proyecto jobeet aplicación backend frontend
    24. 24. $ symfony generate:project jobeet apps/ log/ cache/ plugins/ config/ test/ lib/ web/
    25. 25. frontend/ $ symfony config/ generate:app lib/ jobeet ‐‐escaping‐strategy=on modules/ ‐‐csrf‐secret=UniqueSecret frontend templates/
    26. 26. ‐‐escaping‐strategy XSS ‐‐csrf‐secret CSRF
    27. 27. config/ProjectConfiguration.class.php require_once dirname(__FILE__). '/../lib/vendor/'. 'symfony/lib/autoload/'. 'sfCoreAutoload.class.php';
    28. 28. Los entornos
    29. 29. • Entorno de desarrollo (dev) • Entorno de pruebas • Entorno intermedio • Entorno de producción (prod)
    30. 30. Errores en el entorno de desarrollo (dev)
    31. 31. Errores en el entorno de producción (prod)
    32. 32. web/index.php <?php require_once(dirname(__FILE__). '/../config/ProjectConfiguration.class.php'); $configuration =  ProjectConfiguration::getApplicationConfiguration( 'frontend', 'prod', false ); sfContext::createInstance($configuration)‐>dispatch();
    33. 33. Configurar bien el  servidor web
    34. 34. <VirtualHost 127.0.0.1:80> ServerName jobeet.localhost DocumentRoot quot;/home/sfprojects/jobeet/webquot; DirectoryIndex index.php <Directory quot;/home/sfprojects/jobeet/webquot;> AllowOverride All Allow from All </Directory> Alias /sf /home/sfprojects/jobeet/lib/vendor/symfony/data/web/sf <Directory quot;/home/sfprojects/jobeet/lib/vendor/symfony/data/web/sfquot;> AllowOverride All Allow from All </Directory> </VirtualHost>
    35. 35. /etc/hosts c:windowssystem32driversetchosts 127.0.0.1    jobeet.localhost
    36. 36. http://jobeet.localhost/ prod
    37. 37. http://jobeet.localhost/frontend_dev.php dev
    38. 38. Versionado de  código
    39. 39. Capítulo 2 El proyecto
    40. 40. La idea del  proyecto
    41. 41. Aplicación de software  libre que permite crear  sitios web de búsqueda  de empleo
    42. 42. características • Completo y personalizable • Multilingüe • AJAX, RSS y API
    43. 43. Los escenarios del  proyecto
    44. 44. • administrador (admin) • usuario (user) • publicador (poster) • afiliado (affiliate)
    45. 45. F1 El usuario accede a  la portada y ve las  últimas ofertas de  trabajo activas
    46. 46. F2 El usuario puede  visualizar todas  las ofertas de  trabajo de una  categoría
    47. 47. F3 El usuario refina el  listado mediante  palabras clave
    48. 48. F4 El usuario pincha  sobre una oferta de  trabajo para ver  más información
    49. 49. F5 El usuario publica  una nueva oferta  de trabajo
    50. 50. F6 El usuario quiere  convertirse en un  afiliado
    51. 51. F7 Un usuario afiliado  obtiene la lista de  ofertas de trabajo  activas
    52. 52. B1 El administrador configura el sitio web B2 El administrador gestiona las ofertas de  trabajo B3 El administrador gestiona los afiliados
    53. 53. Capítulo 3 El modelo de  datos
    54. 54. El modelo  relacional
    55. 55. relacional objetos ORM
    56. 56. 1. Describir la base de datos 2. Generar las clases PHP 3. Trabajar con objetos en vez  de SQL
    57. 57. El formato YAML
    58. 58. YAML Formato para serializar datos que  es fácil de leer por las personas y es  compatible con todos los lenguajes  de programación
    59. 59. $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' ) );
    60. 60. casa: familia: apellido: García padres: ‐ Antonio ‐ María hijos: ‐ Jose ‐ Manuel direccion: numero: 34 calle: Gran Vía ciudad: Cualquiera codigopostal: quot;12345quot;
    61. 61. casa: familia: { apellido: García, padres: [Antonio,  María], hijos: [Jose, Manuel] } direccion: { numero: 34, direccion: Gran Vía,  ciudad: Cualquiera, codigopostal: quot;12345quot; }
    62. 62. Sintaxis clave: clave: clave: valor clave: valor clave: clave: valor clave: 2 espacios  ‐ valor en blanco ‐ valor
    63. 63. Arrays normales clave: ‐ valor1 ‐ valor2 ‐ valor3 clave:[valor1, valor2, valor3]
    64. 64. Arrays asociativos clave: clave1: valor1 clave2: valor2 clave3: valor3 clave: { clave1: valor1,  clave2: valor2, clave3: valor3}
    65. 65. <?xml version=quot;1.0quot;?> XML YAML <club> players: <players> Vladimir Kramnik: &kramnik <player id=quot;kramnikquot; name=quot;Vladimir rating: 2700 Kramnikquot; rating=quot;2700quot; status=quot;GMquot; />  <player id=quot;fritzquot; name=quot;Deep status: GM Fritzquot; rating=quot;2700quot; status=quot;Computerquot;  Deep Fritz: &fritz /> rating: 2700 <player id=quot;mertzquot; name=quot;David  status: Computer Mertzquot; rating=quot;1400quot; status=quot;Amateurquot;  David Mertz: &mertz /> rating: 1400 </players> status: Amateur <matches> matches: <match> <Date>2002‐10‐04</Date> ‐ <White refid=quot;fritzquot; />  Date: 2002‐10‐04 <Black refid=quot;kramnikquot; />  White: *fritz <Result>Draw</Result>  Black: *kramnik </match> Result: Draw <match> ‐ <Date>2002‐10‐06</Date> Date: 2002‐10‐06 <White refid=quot;kramnikquot; /> White: *kramnik <Black refid=quot;fritzquot; /> <Result>White</Result> Black: *fritz </match> Result: White </matches> </club> 
    66. 66. El esquema
    67. 67. 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 }
    68. 68. config/schema.yml propel: jobeet_category: id:   ~ name: { type: varchar(255), required: true, index: unique }
    69. 69. config/schema.yml 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:   ~
    70. 70. 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: ~
    71. 71. 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 }
    72. 72. 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 •
    73. 73. La base de datos
    74. 74. $ mysqladmin ‐uroot ‐p create jobeet $ symfony configure:database “mysql:host=localhost;dbname=jobeet” root ConTraSenA config/databases.yml
    75. 75. El ORM
    76. 76. $ symfony propel:build‐sql data/sql/ $ symfony propel:insert‐sql ‐‐no‐confirmation $ symfony propel:build‐model lib/model/
    77. 77. extends JobeetJob • BaseJobeetJob • extends JobeetJobPeer • BaseJobeetJobPeer •
    78. 78. $job = new JobeetJob(); $job‐>setPosition('Web developer'); $job‐>save(); echo $job‐>getPosition(); $job‐>delete();
    79. 79. $category = new JobeetCategory();  $category‐>setName('Programming'); $job = new JobeetJob(); $job‐>setCategory($category);
    80. 80. $ symfony propel:build‐all ‐‐no‐confirmation
    81. 81. $ symfony propel:build‐sql $ symfony propel:insert‐sql $ symfony propel:build‐model $ symfony propel:build‐forms + $ symfony propel:build‐filters $ symfony propel:build‐all
    82. 82. $ 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
    83. 83. $ symfony cache:clear $ symfony cache:cl $ symfony ca:c $ symfony cc
    84. 84. Los datos iniciales
    85. 85. data/fixtures/ Datos iniciales • Datos de prueba • Datos de usuarios •
    86. 86. data/fixtures/010_categories.yml JobeetCategory: design:        { name: Design } programming:   { name: Programming } manager:       { name: Manager } administrator: { name: Administrator }
    87. 87. 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
    88. 88. $ symfony propel:data‐load
    89. 89. $ 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
    90. 90. Probando la  aplicación en el  navegador
    91. 91. proyecto jobeet aplicación backend frontend job módulo
    92. 92. $ symfony propel:generate‐module ‐‐with‐show ‐‐non‐verbose‐templates frontend job JobeetJob frontend/modules/job actions/ templates/
    93. 93. frontend/modules/job/actions/actions.class.php index edit show update delete new create
    94. 94. http://jobeet.localhost/frontend_dev.php/job frontend _dev job
    95. 95. Representación  Objeto textual _ _toString() Categoría
    96. 96. lib/model/JobeetCategory.php class JobeetCategory extends BaseJobeetCategory { public function __toString() { return $this‐>getName(); } }
    97. 97. lib/model/JobeetJob.php class JobeetJob extends BaseJobeetJob { public function __toString() { return sprintf( '%s at %s (%s)', $this‐>getPosition(), $this‐>getCompany(), $this‐>getLocation() ); } }
    98. 98. lib/model/JobeetAffiliate.php class JobeetAffiliate extends BaseJobeetAffiliate { public function __toString() { return $this‐>getUrl(); } }
    99. 99. http://jobeet.localhost/frontend_dev.php/job
    100. 100. Capítulo 4 El controlador y  la vista
    101. 101. La arquitectura MVC
    102. 102. ¿Cómo se programaba con PHP en  el siglo pasado? 1 página del  1 archivo PHP  = sitio web diferente
    103. 103. ¿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
    104. 104. Modelo Vista Controlador
    105. 105. Modelo Directorio /lib/model Vista Directorios templates/ Controlador Archivos index.php y frontend_dev.php Archivos actions.class.php
    106. 106. El layout
    107. 107. patrón de diseño decorator apps/frontend/templates/layout.php
    108. 108. apps/frontend/templates/layout.php <!DOCTYPE html PUBLIC quot;‐//W3C//DTD XHTML 1.0 Transitional//ENquot; quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1‐transitional.dtdquot;> <html xmlns=quot;http://www.w3.org/1999/xhtmlquot; xml:lang=quot;enquot; lang=quot;enquot;> <head> <title>Jobeet ‐ Your best job board</title> <link rel=quot;shortcut iconquot; href=quot;/favicon.icoquot; /> <?php include_javascripts() ?> <?php include_stylesheets() ?> </head> <body> ... <div class=quot;contentquot;> <?php echo $sf_content ?> </div> </body> </html>
    109. 109. Plantillas Symfony • Archivos PHP  normales • Existe un plugin  para Smarty • Symfony 2.0 podría  incluir plantillas
    110. 110. Las hojas de estilos,  imágenes y archivos  JavaScript
    111. 111. helpers <head> ... <?php include_stylesheets() ?> </head>
    112. 112. 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
    113. 113. apps/frontend/config/view.yml default: ... stylesheets:  [main.css, jobs.css, job.css] ... <link rel=quot;stylesheetquot; type=quot;text/cssquot;  media=quot;screenquot; href=quot;/css/main.cssquot; /> <link rel=quot;stylesheetquot; type=quot;text/cssquot;  media=quot;screenquot; href=quot;/css/jobs.cssquot; /> <link rel=quot;stylesheetquot; type=quot;text/cssquot;  media=quot;screenquot; href=quot;/css/job.cssquot; />
    114. 114. apps/frontend/config/view.yml default: ... stylesheets:  [main.css, jobs.css, job] ... <link rel=quot;stylesheetquot; type=quot;text/cssquot;  media=quot;screenquot; href=quot;/css/main.cssquot; /> <link rel=quot;stylesheetquot; type=quot;text/cssquot;  media=quot;screenquot; href=quot;/css/jobs.cssquot; /> <link rel=quot;stylesheetquot; type=quot;text/cssquot;  media=quot;screenquot; href=quot;/css/job.cssquot; />
    115. 115. apps/frontend/config/view.yml default: ... stylesheets:  [main.css, /css/v2/jobs.css] ... <link rel=quot;stylesheetquot; type=quot;text/cssquot;  media=quot;screenquot; href=quot;/css/main.cssquot; /> <link rel=quot;stylesheetquot; type=quot;text/cssquot;  media=quot;screenquot; href=quot;/css/v2/jobs.cssquot; />
    116. 116. apps/frontend/config/view.yml default: ... stylesheets: [main.css, jobs: { media: print } ] ... <link rel=quot;stylesheetquot; type=quot;text/cssquot;  media=quot;screenquot; href=quot;/css/main.cssquot; /> <link rel=quot;stylesheetquot; type=quot;text/cssquot;  media=quot;printquot; href=quot;/css/jobs.cssquot; />
    117. 117. metas: Symfony title: El título 1 metas: Proyecto title: El título 2 metas: Aplicación title: El título 3 metas: Módulo title: El título 4 view.yml
    118. 118. 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
    119. 119. metas: stylesheets: [job] <?php use_stylesheet(‘job.css’) view.yml ?> plantilla plantilla
    120. 120. La portada del módulo  de las ofertas de  trabajo
    121. 121. apps/ frontend/ modules/ job/ actions/ actions.class.php templates/ indexSuccess.php
    122. 122. acción + = plantilla
    123. 123. http://jobeet.localhost/frontend_dev.php/job/index frontend (aplicación) _dev (entorno) job (módulo) index (acción executeIndex y  plantilla indexSuccess)
    124. 124. 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()); } // ... }
    125. 125. 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]]
    126. 126. apps/frontend/modules/job/templates/indexSuccess.php <?php foreach ($jobeet_job_list as $jobeet_job): ?> ... <td> <a href=quot;...quot;> <?php echo $jobeet_job‐>getId() ?> </a> </td> ... <?php endforeach; ?> 
    127. 127. La plantilla de la página  de una oferta de  trabajo
    128. 128. Slots
    129. 129. <title>Jobeet</title> <title> layout plantilla
    130. 130. <title>             </title> Título de la página layout plantilla
    131. 131. 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() ) ) ?> 
    132. 132. La acción de la página  de una oferta de  trabajo
    133. 133. apps/frontend/modules/job/actions/actions.class.php public function executeShow(sfWebRequest $request) { $this‐>job = JobeetJobPeer::retrieveByPk( $request‐>getParameter('id') ); $this‐>forward404Unless($this‐>job); }
    134. 134. La petición y la  respuesta
    135. 135. objeto sfWebRequest class jobActions extends sfActions { public function executeShow(sfWebRequest $request) { $peticion = $request; $origen = $peticion‐>getReferer(); $metodo = $peticion‐>getMethod(); } // ... }
    136. 136. 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']
    137. 137. public function executeShow(sfWebRequest $request) { ... $request‐>getParameter('id'); ... } /ruta1/ruta2/ruta3?id=3&clave1= valor1&clave2=valor2
    138. 138. 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'); } // ... }
    139. 139. archivo de configuración metas: stylesheets: [job] plantilla use_stylesheet('job.css') <?php ?> acción $this‐>getResponse()‐> addStyleSheet('/css/job.css');
    140. 140. Capítulo 5 El sistema de  enrutamiento
    141. 141. URL
    142. 142. internet symfony URL URI sistema de  enrutamiento
    143. 143. URI 'job/show?id='.$job‐>getId() url_for() job/show/id/1 URL
    144. 144. URI modulo/accion?clave1= valor1&clave2=valor2& ...
    145. 145. Configurando el  enrutamiento
    146. 146. apps/frontend/config/routing.yml homepage: url: / param: { module: default, action: index } default_index: url: /:module param: { action: index } default: url: /:module/:action/*
    147. 147. nombre patrón default_index: url: /:module param: { action: index } parámetros
    148. 148. homepage: url: / param: { module: default, action: index } default_index: url: /:module param: { action: index } default: url: /:module/:action/*  /job
    149. 149. /frontend_dev.php/job 1 entorno aplicación ??? ¿acción? ¿módulo? apps/frontend/config/routing.yml 2 default_index: /job url: /:module param: { action: index } :module = job = módulo
    150. 150. 3 apps/frontend/config/routing.yml default_index: acción = index url: /:module param: { action: index } /frontend_dev.php/job 4 aplicación = frontend módulo = job entorno = dev acción = index
    151. 151. url_for() URI URL url_for('job/show?id='.$job‐>getId()) /job/show/id/1
    152. 152. url_for() URI URL url_for('@default?id='.$job‐>getId())
    153. 153. Personalizando el  enrutamiento
    154. 154. apps/frontend/config/routing.yml homepage: url: / param: { module: job, action: index } default_index: url: /:module param: { action: index } default: url: /:module/:action/* 
    155. 155. <h1> <a href=quot;<?php echo url_for('@homepage') ?>quot;> <img src=quot;/images/jobeet.gifquot; alt=quot;Jobeetquot; /> </a> </h1>
    156. 156. /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
    157. 157. /job/sensio‐labs/paris‐france/1/web‐developer 1. Identificar el patrón de la URL /job/:company/:location/:id/:position
    158. 158. /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 }
    159. 159. url_for('job/show?'. 'id='.$job‐>getId(). '&company='.$job‐>getCompany(). '&location='.$job‐>getLocation(). '&position='.$job‐>getPosition() )
    160. 160. url_for(array( 'module' => 'job', 'action' => 'show', 'id' => $job‐>getId(), 'company' => $job‐>getCompany(), 'location' => $job‐>getLocation(), 'position' => $job‐>getPosition(),  ))
    161. 161. Requisitos
    162. 162. /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+
    163. 163. La clase sfRoute
    164. 164. HTTP     Navegadores      Symfony GET POST HEAD PUT DELETE
    165. 165. job_show_user: url:     /job/:company/:location/:id/:position class: sfRequestRoute param:   { module: job, action: show } requirements: id: d+ sf_method: [get]
    166. 166. La clase para las  rutas basadas en  objetos
    167. 167. url_for('job/show?'. 'id='.$job‐>getId(). '&company='.$job‐>getCompany(). '&location='.$job‐>getLocation(). '&position='.$job‐>getPosition() )
    168. 168. 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]
    169. 169. 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 ))
    170. 170. Lo que queremos… /job/sensio‐labs/paris‐france/1/web‐developer Lo que tenemos… /job/Sensio+Labs/Paris%2C+France/1/Web+Developer
    171. 171. getId() id name getName() description Job getDescription() ... getSlug() schema.yml getShortDescription() getters virtuales
    172. 172. 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/
    173. 173. getId() id name getName() description Job getDescription() ... getCompanySlug() getPositionSlug() schema.yml getLocationSlug() getters virtuales
    174. 174. 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()); }
    175. 175. 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; } }
    176. 176. 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]
    177. 177. 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();  } // ... }
    178. 178. Enrutamiento en  acciones y  plantillas
    179. 179. <?php echo link_to( quot;Texto del enlacequot;, 'job_show_user', $job ) ?> <a href=quot; <?php echo url_for( 'job_show_user', $job, true ); ?>quot;> Texto del enlace </a>
    180. 180. class jobActions extends sfActions { public function executeIndex(sfWebRequest $request) { // ... $this‐>redirect( $this‐>generateUrl('job_show_user', $job) ); } // ... }
    181. 181. La clase de las  colecciones de  rutas
    182. 182. 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]
    183. 183. $ php symfony app:routes frontend

    ×