Frameworks de desarrollo

Symfony
Clase 3

                       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 12

El generador de 
la parte de 
administración
Creando la aplicación 
     backend
backend/
                                 config/
$ symfony
                                 lib/
generate:app
‐‐escaping‐...
Controladores frontales

frontend_dev.php     frontend |  desarrollo

index.php            frontend |  producción

backend...
propel:data‐load


JobeetJob::save()   apps/frontend/config/app.yml




   app.yml


   backend/
                         ...
Los módulos de la 
aplicación backend
$ symfony propel:generate‐admin
backend JobeetJob ‐‐module=job

       backend/modules/job
          actions/
          co...
apps/backend/config/routing.yml

jobeet_job:
  class: sfPropelRouteCollection
  options:
    model:                JobeetJ...
El aspecto de la 
aplicación backend
http://jobeet.localhost/backend_dev.php/job

• Listado con paginación, 
ordenación y filtrado
• Crear, modificar y borrar ...
La cache de Symfony
apps/backend/modules/job/actions/actions.class.php
require_once dirname(__FILE__).'/../lib/jobGeneratorConfiguration.class...
apps/backend/modules/job/config/generator.yml
generator:
  class: sfPropelGenerator
  param:
    model_class:           Jo...
Configuración del 
      título
apps/backend/modules/category/config/generator.yml
config:
  actions: ~
  fields:  ~
  list:    
    title: Gestión de cat...
Configuración de los 
      campos
apps/backend/modules/job/config/generator.yml
config:
  fields:
    is_activated: { label: Activated?, help: Whether the u...
fields


filter                     list
            form


                     new
     edit
Configuración de la 
    página list
apps/backend/modules/category/config/generator.yml
config:
  list:
    title:   Category Management
    display: [=name, s...
apps/backend/modules/job/config/generator.yml
config:
  list:
    title:   Job Management
    display: [company, position,...
apps/backend/modules/job/config/generator.yml
config:
  list:
    sort: [expires_at, desc]
    max_per_page: 10
apps/backend/modules/category/config/generator.yml
config:
  list:
    batch_actions: {}
apps/backend/modules/job/config/generator.yml
config:
  list:
    batch_actions:
      _delete:    ~
      extend:     ~

...
apps/backend/modules/category/config/generator.yml
config:
  list:
    object_actions: {}


                      apps/bac...
apps/backend/modules/job/config/generator.yml
config:
  list:
    actions:
      deleteNeverActivated: { label: Borrar ofe...
apps/backend/modules/job/config/generator.yml
config:
  list:
    peer_method: doSelectJoinJobeetCategory
Configuración de la 
    página de 
   formularios
apps/backend/modules/job/config/generator.yml
config:
  form:
    display:
      Content: [category_id, type, company,
   ...
BaseJobeetJobForm


   JobeetJobForm


BackendJobeetJobForm
lib/form/BackendJobeetJobForm.php

$this‐>widgetSchema['logo'] = new sfWidgetFormInputFileEditable(array(
    'label'     ...
Configuración de los 
       filtros
$ ./symfony propel:build‐filters

 $ ./symfony propel:build‐all
$ ./symfony propel:build‐filters


                      JobeetCategoryFormFilter
JobeetJobFormFilter                     ...
apps/backend/modules/category/config/generator.yml
config:
  filter:
    class: false


                   apps/backend/mo...
Modificando las 
  acciones
executeIndex()         getFilters()
listexecuteFilter()    setFilters()
executeNew()           getPager()
executeCreate() ...
Personalizando las 
    plantillas
_assets.php               _list_field_boolean.php
_filters.php              _list_footer.php
_filters_field.php        _li...
Capítulo 13

El usuario
sfUser
Mensajes flash
Mensaje temporal que se almacena en la sesión 
 del usuario y que se borra automáticamente 
       después de la siguiente...
apps/frontend/modules/job/actions/actions.class.php

public function executeExtend(sfWebRequest $request)
{
    ...
    $t...
Atributos del usuario
quot;para facilitar la navegación por las ofertas 
  de trabajo, en el menú se muestran los 
enlaces a las tres últimas of...
apps/frontend/modules/job/actions/actions.class.php
class jobActions extends sfActions
{
  public function executeShow(sfW...
apps/frontend/modules/job/actions/actions.class.php
class jobActions extends sfActions
{
  public function executeShow(sfW...
La seguridad de la 
    aplicación
apps/backend/config/security.yml

default:
  is_secure: on
apps/backend/config/settings.yml
 all:
   .actions:
      login_module: default
      login_action: login



if (!$this‐>g...
Plugins
http://www.symfony‐project.org/plugins
sfGuardPlugin
$ ./symfony plugin:install sfGuardPlugin




$ apt‐get install php‐pear
$ pear channel‐discover pear.symfony‐project.com
La seguridad de la 
aplicación backend
$ ./symfony propel:build‐all ‐‐no‐confirmation

$ ./symfony cc
                            apps/backend/lib/myUser.class.p...
$ ./symfony guard:create‐user usuario contrasena

$ ./symfony guard:promote usuario
$ ./symfony list guard
apps/backend/templates/layout.php
<?php if ($sf_user‐>isAuthenticated()): ?>
<div id=quot;menuquot;>
  <ul>
    <li>
     ...
apps/backend/config/settings.yml
all:
  .settings:
     enabled_modules: [default, sfGuardAuth, sfGuardUser]



          ...
Probando los 
  usuarios
test/functional/frontend/jobActionsTest.php
$browser‐>
  info('4 ‐ User job history')‐>

  loadData()‐>
  restart()‐>

  i...
Capítulo 14

El día de 
descanso
CC by‐nc‐sa StockVault
Capítulo 15

Canales Atom
Formatos
plantilla1




petición   plantilla2




           plantilla3
$request‐>setRequestFormat('xml');

         txt      xml
         js       rdf
         css      atom
         json
http://jobeet.localhost/frontend_dev.php/job



http://jobeet.localhost/frontend_dev.php/job.html
Canales Atom
apps/frontend/modules/job/templates/indexSuccess.atom.php

<?xml version=quot;1.0quot; encoding=quot;utf‐8quot;?>
<feed xm...
indexSuccess.php
          indexSuccess.html.php

                         indexSuccess.php
return sfView::SUCCESS
       ...
apps/frontend/templates/layout.php


<li class=quot;feedquot;>
  <a href=quot;<?php echo url_for('@job?sf_format=atom') ?>...
apps/frontend/modules/job/templates/indexSuccess.atom.php

<title>Jobeet</title>
<subtitle>Latest Jobs</subtitle>
<link hr...
apps/frontend/modules/job/templates/indexSuccess.atom.php

<?php use_helper('Text') ?>
<?php foreach ($categories as $cate...
apps/frontend/config/routing.yml
category:
  url:     /category/:slug.:sf_format
  class:   sfPropelRoute
  param:   { mod...
apps/frontend/modules/job/templates/_list.atom.php
<?php use_helper('Text') ?>
<?php foreach ($jobs as $job): ?>
  <entry>...
Curso Symfony - Clase 3
Curso Symfony - Clase 3
Upcoming SlideShare
Loading in …5
×

Curso Symfony - Clase 3

5,647 views

Published on

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

Published in: Technology

Curso Symfony - Clase 3

  1. 1. Frameworks de desarrollo Symfony Clase 3 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 12 El generador de  la parte de  administración
  5. 5. Creando la aplicación  backend
  6. 6. backend/ config/ $ symfony lib/ generate:app ‐‐escaping‐strategy=on modules/ ‐‐csrf‐secret=UniqueSecret1 backend templates/
  7. 7. Controladores frontales frontend_dev.php frontend |  desarrollo index.php frontend |  producción backend_dev.php backend |  desarrollo backend.php backend |  producción
  8. 8. propel:data‐load JobeetJob::save() apps/frontend/config/app.yml app.yml backend/ config/app.yml
  9. 9. Los módulos de la  aplicación backend
  10. 10. $ symfony propel:generate‐admin backend JobeetJob ‐‐module=job backend/modules/job actions/ config/ lib/ templates/
  11. 11. apps/backend/config/routing.yml jobeet_job: class: sfPropelRouteCollection options: model:                JobeetJob module:               job prefix_path:          job column:               id with_wildcard_routes: true
  12. 12. El aspecto de la  aplicación backend
  13. 13. http://jobeet.localhost/backend_dev.php/job • Listado con paginación,  ordenación y filtrado • Crear, modificar y borrar  objetos • Borrar varios objetos a la  vez • Formularios con validación • Mensajes flash para  feedback • ...y mucho más
  14. 14. La cache de Symfony
  15. 15. apps/backend/modules/job/actions/actions.class.php require_once dirname(__FILE__).'/../lib/jobGeneratorConfiguration.class.php'; require_once dirname(__FILE__).'/../lib/jobGeneratorHelper.class.php'; class jobActions extends autoJobActions { } cache/backend/dev/modules/autoJob/actions/actions.class.php class autoJobActions extends sfActions { public function preExecute() { $this‐>configuration = new jobGeneratorConfiguration(); ... apps/backend/modules/job/config/generator.yml
  16. 16. apps/backend/modules/job/config/generator.yml generator: class: sfPropelGenerator param: model_class:           JobeetJob theme:                 admin non_verbose_templates: true with_show:             false singular:              ~ plural:                ~ route_prefix:          jobeet_job with_propel_route:     1 config: actions: ~ fields:  ~ list:    ~ filter:  ~ form:    ~ edit:    ~ new:     ~
  17. 17. Configuración del  título
  18. 18. apps/backend/modules/category/config/generator.yml config: actions: ~ fields:  ~ list:     title: Gestión de categorías filter:  ~ form:    ~ edit: title: Editando la categoría quot;%%name%%quot; new: title: Nueva categoría
  19. 19. Configuración de los  campos
  20. 20. apps/backend/modules/job/config/generator.yml config: fields: is_activated: { label: Activated?, help: Whether the user  has activated the job, or not } is_public:    { label: Public? } config: list: fields: is_public:    { label: quot;Public? (label for the list)quot; }
  21. 21. fields filter list form new edit
  22. 22. Configuración de la  página list
  23. 23. apps/backend/modules/category/config/generator.yml config: list: title:   Category Management display: [=name, slug] enlace
  24. 24. apps/backend/modules/job/config/generator.yml config: list: title:   Job Management display: [company, position, location, url, is_activated, email] layout:  stacked params:  | %%jobeet_category%% %%is_activated%% <small>%%category_id%%</small> ‐ %%company%% (<em>%%email%%</em>) is looking for a %%=position%% (%%location%%)
  25. 25. apps/backend/modules/job/config/generator.yml config: list: sort: [expires_at, desc] max_per_page: 10
  26. 26. apps/backend/modules/category/config/generator.yml config: list: batch_actions: {}
  27. 27. apps/backend/modules/job/config/generator.yml config: list: batch_actions: _delete:    ~ extend:     ~ apps/backend/modules/job/actions/actions.class.php class jobActions extends autoJobActions { public function executeBatchExtend(sfWebRequest $request) { $ids = $request‐>getParameter('ids'); $jobs = JobeetJobPeer::retrieveByPks($ids); foreach ($jobs as $job) { $job‐>extend(true); } ... } }
  28. 28. apps/backend/modules/category/config/generator.yml config: list: object_actions: {} apps/backend/modules/job/config/generator.yml config: list: object_actions: extend:     ~ _edit:      ~ _delete:    ~
  29. 29. apps/backend/modules/job/config/generator.yml config: list: actions: deleteNeverActivated: { label: Borrar ofertas inactivas } apps/backend/modules/job/actions/actions.class.php class jobActions extends autoJobActions { public function executeListDeleteNeverActivated(sfWebRequest $request) { $nb = JobeetJobPeer::cleanup(60); ... $this‐>redirect('@jobeet_job'); }
  30. 30. apps/backend/modules/job/config/generator.yml config: list: peer_method: doSelectJoinJobeetCategory
  31. 31. Configuración de la  página de  formularios
  32. 32. apps/backend/modules/job/config/generator.yml config: form: display: Content: [category_id, type, company, logo, url, position, location, description, how_to_apply,  is_public, email] Admin:   [_generated_token, is_activated,  expires_at] apps/backend/modules/job/templates/_generated_token.php <div class=quot;sf_admin_form_rowquot;> <label>Token</label> <?php echo $form‐>getObject()‐>getToken() ?> </div>
  33. 33. BaseJobeetJobForm JobeetJobForm BackendJobeetJobForm
  34. 34. lib/form/BackendJobeetJobForm.php $this‐>widgetSchema['logo'] = new sfWidgetFormInputFileEditable(array( 'label' => 'Company logo', 'file_src' => '/uploads/jobs/'.$this‐>getObject()‐>getLogo(), 'is_image' => true, 'edit_mode' => !$this‐>isNew(), 'template' => '<div>%file%<br />%input%<br />%delete% %delete_label%</div>',  )); 
  35. 35. Configuración de los  filtros
  36. 36. $ ./symfony propel:build‐filters $ ./symfony propel:build‐all
  37. 37. $ ./symfony propel:build‐filters JobeetCategoryFormFilter JobeetJobFormFilter JobeetAffiliateFormFilter lib/filter/
  38. 38. apps/backend/modules/category/config/generator.yml config: filter: class: false apps/backend/modules/job/config/generator.yml filter: display: [category_id, company, position,  description, is_activated, is_public, email, expires_at]
  39. 39. Modificando las  acciones
  40. 40. executeIndex() getFilters() listexecuteFilter() setFilters() executeNew() getPager() executeCreate() getPage() executeEdit() setPage() executeUpdate() buildCriteria() executeDelete() addSortCriteria() executeBatch() getSort() executeBatchDelete() setSort() processForm()
  41. 41. Personalizando las  plantillas
  42. 42. _assets.php _list_field_boolean.php _filters.php _list_footer.php _filters_field.php _list_header.php _flashes.php _list_td_actions.php _form.php _list_td_batch_actions.php _form_actions.php _list_td_stacked.php _form_field.php _list_td_tabular.php _form_fieldset.php _list_th_stacked.php _form_footer.php _list_th_tabular.php _form_header.php _pagination.php _list.php editSuccess.php _list_actions.php indexSuccess.php _list_batch_actions.php newSuccess.php
  43. 43. Capítulo 13 El usuario
  44. 44. sfUser
  45. 45. Mensajes flash
  46. 46. Mensaje temporal que se almacena en la sesión  del usuario y que se borra automáticamente  después de la siguiente petición
  47. 47. apps/frontend/modules/job/actions/actions.class.php public function executeExtend(sfWebRequest $request) { ... $this‐>getUser()‐>setFlash( 'notice', 'La oferta se ha actualizado' ); ... } apps/frontend/templates/layout.php <?php if ($sf_user‐>hasFlash('notice')): ?> <div class=quot;flash_noticequot;> <?php echo $sf_user‐>getFlash('notice') ?> </div> <?php endif; ?>
  48. 48. Atributos del usuario
  49. 49. quot;para facilitar la navegación por las ofertas  de trabajo, en el menú se muestran los  enlaces a las tres últimas ofertas de trabajo  vistas por el usuarioquot;
  50. 50. apps/frontend/modules/job/actions/actions.class.php class jobActions extends sfActions { public function executeShow(sfWebRequest $request) { $this‐>job = $this‐>getRoute()‐>getObject(); // obtener las ofertas del historial $jobs = $this‐>getUser()‐>getAttribute( 'historial', array() ); // añadir la oferta al historial array_unshift($jobs, $this‐>job‐>getId()); // guardar de nuevo el historial $this‐>getUser()‐>setAttribute('historial', $jobs); } // ... }
  51. 51. apps/frontend/modules/job/actions/actions.class.php class jobActions extends sfActions { public function executeShow(sfWebRequest $request) { $this‐>job = $this‐>getRoute()‐>getObject(); $this‐>getUser()‐>addJobToHistory($this‐>job); } // ... } apps/frontend/lib/myUser.class.php class myUser extends sfBasicSecurityUser { public function addJobToHistory(JobeetJob $job) { ... } $sf_user }
  52. 52. La seguridad de la  aplicación
  53. 53. apps/backend/config/security.yml default: is_secure: on
  54. 54. apps/backend/config/settings.yml all: .actions: login_module: default login_action: login if (!$this‐>getUser()‐>isAuthenticated()) { $this‐>getUser()‐>setAuthenticated(true); }
  55. 55. Plugins
  56. 56. http://www.symfony‐project.org/plugins
  57. 57. sfGuardPlugin
  58. 58. $ ./symfony plugin:install sfGuardPlugin $ apt‐get install php‐pear $ pear channel‐discover pear.symfony‐project.com
  59. 59. La seguridad de la  aplicación backend
  60. 60. $ ./symfony propel:build‐all ‐‐no‐confirmation $ ./symfony cc apps/backend/lib/myUser.class.php class myUser extends sfGuardSecurityUser { } apps/backend/config/settings.yml all: .settings: enabled_modules: [default, sfGuardAuth] # ... .actions: login_module: sfGuardAuth login_action: signin
  61. 61. $ ./symfony guard:create‐user usuario contrasena $ ./symfony guard:promote usuario
  62. 62. $ ./symfony list guard
  63. 63. apps/backend/templates/layout.php <?php if ($sf_user‐>isAuthenticated()): ?> <div id=quot;menuquot;> <ul> <li> <?php echo link_to('Jobs', '@jobeet_job') ?> </li> <li> <?php echo link_to('Categories', '@jobeet_category') ?> </li> <li> <?php echo link_to('Logout', '@sf_guard_signout') ?> </li>  </ul> </div> $ ./symfony app:routes <?php endif; ?> 
  64. 64. apps/backend/config/settings.yml all: .settings: enabled_modules: [default, sfGuardAuth, sfGuardUser] apps/backend/templates/layout.php <li> <?php echo link_to('Users', '@sf_guard_user') ?> </li>
  65. 65. Probando los  usuarios
  66. 66. test/functional/frontend/jobActionsTest.php $browser‐> info('4 ‐ User job history')‐> loadData()‐> restart()‐> info(' 4.1 ‐ When the user access a job, it is added to its history')‐> get('/')‐> click('Web Developer', array(), array('position' => 1))‐> get('/')‐> with('user')‐>begin()‐> isAttribute('job_history', array($browser‐>getMostRecentProgrammingJob()‐>getId()))‐> end()‐> info(' 4.2 ‐ A job is not added twice in the history')‐> click('Web Developer', array(), array('position' => 1))‐> get('/')‐> with('user')‐>begin()‐> isAttribute('job_history', array($browser‐>getMostRecentProgrammingJob()‐>getId()))‐> end() ; 
  67. 67. Capítulo 14 El día de  descanso
  68. 68. CC by‐nc‐sa StockVault
  69. 69. Capítulo 15 Canales Atom
  70. 70. Formatos
  71. 71. plantilla1 petición plantilla2 plantilla3
  72. 72. $request‐>setRequestFormat('xml'); txt xml js rdf css atom json
  73. 73. http://jobeet.localhost/frontend_dev.php/job http://jobeet.localhost/frontend_dev.php/job.html
  74. 74. Canales Atom
  75. 75. apps/frontend/modules/job/templates/indexSuccess.atom.php <?xml version=quot;1.0quot; encoding=quot;utf‐8quot;?> <feed xmlns=quot;http://www.w3.org/2005/Atomquot;> <title>Jobeet</title> <subtitle>Latest Jobs</subtitle> <link href=quot;quot; rel=quot;selfquot;/> <link href=quot;quot;/> <updated></updated> <author><name>Jobeet</name></author> <id>Unique Id</id> <entry> <title>Job title</title> <link href=quot;quot; /> <id>Unique id</id> <updated></updated> <summary>Job description</summary> <author><name>Company</name></author> </entry> </feed>
  76. 76. indexSuccess.php indexSuccess.html.php indexSuccess.php return sfView::SUCCESS indexError.php return sfView::ERROR indexHola.php return quot;Holaquot; indexPlantilla.php return quot;Plantillaquot;
  77. 77. apps/frontend/templates/layout.php <li class=quot;feedquot;> <a href=quot;<?php echo url_for('@job?sf_format=atom') ?>quot;> Full feed </a> </li> application/atom+xml; charset=utf‐8 has_layout: off <link rel=quot;alternatequot; type=quot;application/atom+xmlquot; title=quot;Latest Jobsquot; href=quot;<?php echo url_for('@job?sf_format=atom', true) ?>quot;  />
  78. 78. apps/frontend/modules/job/templates/indexSuccess.atom.php <title>Jobeet</title> <subtitle>Latest Jobs</subtitle> <link href=quot;<?php echo url_for('@job?sf_format=atom', true) ?>quot; rel=quot;selfquot;/> <link href=quot;<?php echo url_for('@homepage', true) ?>quot;/> <updated><?php echo gmstrftime('%Y‐%m‐%dT%H:%M:%SZ',  JobeetJobPeer::getLatestPost()‐>getCreatedAt('U')) ?></updated> <author> <name>Jobeet</name> </author> <id><?php echo sha1(url_for('@job?sf_format=atom', true)) ?></id>
  79. 79. apps/frontend/modules/job/templates/indexSuccess.atom.php <?php use_helper('Text') ?> <?php foreach ($categories as $category): ?> <?php foreach ($category‐>getActiveJobs( as $job): ?> sfConfig::get('app_max_jobs_on_homepage')) <entry> <title> <?php echo $job‐>getPosition() ?> (<?php echo $job‐>getLocation() ?>) </title> <link href=quot;<?php echo url_for('job_show_user', $job, true) ?>quot; /> <id><?php echo sha1($job‐>getId()) ?></id> ...
  80. 80. apps/frontend/config/routing.yml category: url:     /category/:slug.:sf_format class:   sfPropelRoute param:   { module: category, action: show, sf_format: html } options: { model: JobeetCategory, type: object } requirements: sf_format: (?:html|atom) apps/frontend/modules/job/templates/indexSuccess.php <div class=quot;feedquot;> <a href=quot;<?php echo url_for('category', array('sf_subject'  => $category, 'sf_format' => 'atom')) ?>quot;>Feed</a> </div>  apps/frontend/modules/job/templates/showSuccess.php <div class=quot;feedquot;> <a href=quot;<?php echo url_for('category', array('sf_subject'  => $category, 'sf_format' => 'atom')) ?>quot;>Feed</a> </div> 
  81. 81. apps/frontend/modules/job/templates/_list.atom.php <?php use_helper('Text') ?> <?php foreach ($jobs as $job): ?> <entry> <title><?php echo $job‐>getPosition() ?> (<?php echo $job‐ >getLocation() ?>)</title> <link href=quot;<?php echo url_for('job_show_user', $job,  true) ?>quot; /> <id><?php echo sha1($job‐>getId()) ?></id> ... apps/frontend/modules/job/templates/indexSuccess.atom.php <?php foreach ($categories as $category): ?> <?php include_partial( 'job/list', array('jobs' => $category‐>getActiveJobs(sfConfig::get('app_max_jobs_on_homepage')) )) ?> <?php endforeach; ?>

×