Curso Symfony Clase 2

  • Uploaded by: Julio Cesar Brizuela
  • 0
  • 0
  • June 2020
  • PDF

This document was uploaded by user and they confirmed that they have the permission to share it. If you are author or own the copyright of this book, please report to us by using this DMCA report form. Report DMCA


Overview

Download & View Curso Symfony Clase 2 as PDF for free.

More details

  • Words: 2,431
  • Pages: 135
Frameworks de desarrollo

Symfony Clase 2

Javier Eguíluz [email protected]

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 6

Profundizando en  el modelo

El objeto Criteria de Propel

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

class jobActions extends sfActions { public function executeIndex(sfWebRequest $request) { $this‐>listado = 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]]

SELECT * FROM JobeetJob WHERE created_at > time() ‐ 86400 * 30

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

public function executeIndex(sfWebRequest $request) { $criteria = new Criteria(); $criteria‐>add( WHERE JobeetJobPeer::CREATED_AT, condición time() ‐ 86400 * 30, Criteria::GREATER_THAN ); $this‐>listado =

}

JobeetJobPeer::doSelect($criteria);

FROM JobeetJob

SELECT *

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

public function executeIndex(sfWebRequest { $criteria = new Criteria(); $criteria‐>add( JobeetJobPeer::COMPANY, 'Empresa ACME' ); $this‐>listado =

}

$request)

JobeetJobPeer::doSelect($criteria);

Depurando el código  SQL generado

log/frontend_dev.log Dec 6 15:47:12 symfony [debug] {sfPropelLogger} exec: SET NAMES 'utf8‘ Dec 6 15:47:12 symfony [debug] {sfPropelLogger} prepare: SELECT  jobeet_job.ID, jobeet_job.CATEGORY_ID, jobeet_job.TYPE,  jobeet_job.COMPANY, jobeet_job.LOGO, jobeet_job.URL,  jobeet_job.POSITION, jobeet_job.LOCATION, jobeet_job.DESCRIPTION,  jobeet_job.HOW_TO_APPLY, jobeet_job.TOKEN, jobeet_job.IS_PUBLIC,  jobeet_job.CREATED_AT, jobeet_job.UPDATED_AT FROM ''jobeet_job''  WHERE jobeet_job.CREATED_AT>:p1

SQL Injection

Dec 6 15:47:12 symfony [debug] {sfPropelLogger} Binding '2008‐11‐06  15:47:12' at position :p1 w/ PDO type PDO::PARAM_STR

Serializando objetos

lib/model/JobeetJob.php

class JobeetJob extends BaseJobeetJob { public function save(PropelPDO $con = null) { if ($this‐>isNew() && !$this‐>getExpiresAt()) { $now = $this‐>getCreatedAt() ? $this‐>getCreatedAt('U') : time(); $this‐>setExpiresAt($now + 86400 * 30);  } return parent::save($con); } }

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

public function executeIndex(sfWebRequest $request) { $criteria = new Criteria(); $criteria‐>add( JobeetJobPeer::CREATED_AT EXPIRES_AT, time(), Criteria::GREATER_THAN ); $this‐>listado = JobeetJobPeer::doSelect( $criteria ); }

Personalizando la  configuración

¿Dónde está el problema? public function executeIndex(sfWebRequest $request) { $criteria = new Criteria(); $criteria‐>add( JobeetJobPeer::CREATED_AT, mejor como opción  time() ‐ 86400 * 30, de configuración Criteria::GREATER_THAN ); $this‐>listado =

}

JobeetJobPeer::doSelect($criteria);

apps/frontend/config/app.yml

all: dias_activa:  30 sfConfig::get('app_dias_activa')

Refactorización

¿Dónde está el problema? Controlador (MVC) public function executeIndex(sfWebRequest $request) { $criteria = new Criteria(); $criteria‐>add( JobeetJobPeer::CREATED_AT, Modelo (MVC) time() ‐ 86400 * 30, Criteria::GREATER_THAN ); $this‐>listado =

}

JobeetJobPeer::doSelect($criteria);

Modelo

lib/model/JobeetJobPeer.php

class JobeetJobPeer extends BaseJobeetJobPeer { static public function getActiveJobs() { $criteria = new Criteria(); $criteria‐>add( self::EXPIRES_AT, time(), Criteria::GREATER_THAN ); return self::doSelect($criteria); } }

Controlador

apps/frontend/modules/job/actions/

actions.class.php

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

static public function getActiveJobs() { $criteria = new Criteria(); $criteria‐>add( self::EXPIRES_AT, time(), Criteria::GREATER_THAN );

$criteria‐>addDescendingOrderByColumn( self::EXPIRES_AT ORDER BY ___ DESC ); return self::doSelect($criteria); }

Mostrando las  categorías en la  portada

lib/model/JobeetCategoryPeer.php class JobeetCategoryPeer extends BaseJobeetCategoryPeer { static public function getWithJobs() { $criteria = new Criteria(); $criteria‐>addJoin(self::ID, JobeetJobPeer::CATEGORY_ID); $criteria‐>add( JobeetJobPeer::EXPIRES_AT, time(), Criteria::GREATER_THAN );

$criteria‐>setDistinct();

SELECT DISTINCT

return self::doSelect($criteria); } }

apps/frontend/modules/job/actions/actions.class.php public function executeIndex(sfWebRequest $request) { $this‐>categories = JobeetCategoryPeer::getWithJobs(); }

apps/frontend/modules/job/templates/indexSuccess.php ...

... getActiveJobs() as $i => $job): ?> ... ...  

Controlador      Vista             Modelo getWithJobs()

1

JobeetCategoryPeer.php

3 executeIndex()

getActiveJobs()

indexSuccess.php

$categories

2

JobeetCategory.php

4

getActiveJobs()

JobeetJobPeer.php

Limitando los  resultados

lib/model/JobeetJobPeer.php class JobeetJobPeer extends BaseJobeetJobPeer { static public function getActiveJobs($max = 10) { $criteria = new Criteria(); $criteria‐>add( mejor en un archivo  self::EXPIRES_AT, de configuración time(), Criteria::GREATER_THAN ); $criteria‐>setLimit($max);  return self::doSelect($criteria); } }

apps/frontend/modules/job/templates/indexSuccess.php

getActiveJobs( sfConfig::get('app_max_jobs_on_homepage') ) as $i => $job): ?>  apps/frontend/config/app.yml

all: active_days:          30 max_jobs_on_homepage: 10

Archivos de datos  dinámicos

data/fixtures/020_jobs.yml JobeetJob: job_: category_id: programming company: Company position: Web Developer location: Paris, France description: | Lorem ipsum dolor sit amet, consectetur adipisicing elit. how_to_apply: | Send your resume to lorem.ipsum [at] company_.sit is_public: true is_activated: true token: job_ email: [email protected]

Restringir el acceso a  una oferta de trabajo

apps/frontend/config/routing.yml job_show_user: url: /job/:company_slug/:location_slug/:id/:position_slug class: sfPropelRoute options: model: JobeetJob type:  object

method_for_criteria: doSelectActive param: { module: job, action: show } requirements: id: \d+ sf_method: [get]

lib/model/JobeetJobPeer.php class JobeetJobPeer extends BaseJobeetJobPeer { static public function doSelectActive(Criteria $criteria) { $criteria‐>add( JobeetJobPeer::EXPIRES_AT, time(), Criteria::GREATER_THAN ); return self::doSelectOne($criteria); } }

Capítulo 7

La página de cada  categoría

La ruta de la  categoría

apps/frontend/config/routing.yml category: url:      /category/:slug class:    sfPropelRoute param:    { module: category, action: show } options:  { model: JobeetCategory, type: object }

lib/model/JobeetCategory.php public function getSlug() { return Jobeet::slugify($this‐>getName()); }

El enlace a la página  de cada categoría

apps/frontend/modules/job/templates/indexSuccess.php



$total = $category‐>countActiveJobs() ‐ sfConfig::get('app_max_jobs_on_homepage')  0): ?> ... echo link_to($count, 'category', $category) ...

DRY (Don’t Repeat Yourself) A process philosophy aimed at reducing duplication, particularly in computing. […] When the DRY principle is applied successfully, a modification of  any single element of a system does not change other logically‐ unrelated elements. Additionally, elements that are logically  related all change predictably and uniformly, and are thus kept  in sync.

xxxPeer::doSelect() xxxPeer::doSelectOne() xxxPeer::doSelectRS() xxxPeer::retrieveByPK() xxxPeer::retrieveByPKs() xxxPeer::doCount() xxxPeer::doInsert() xxxPeer::doDelete() xxxPeer::doUpdate()

Creando el módulo  de las categorías

$ ./symfony propel:generate‐module frontend category

actions/

templates/

index

edit

indexSuccess

show

update

editSuccess

new

delete

newSuccess

create

$ ./symfony generate:module frontend category

actions/ index

templates/ indexSuccess

nombre

slug

Actualizando la base  de datos

config/schema.yml propel: jobeet_category: id:        ~ name: { type: varchar(255), required: true } slug: type: varchar(255) required: true index: unique

getSlug()

lib/model/JobeetCategory.php public function setName($name) { parent::setName($name); $this‐>setSlug(Jobeet::slugify($name)); }

$ ./symfony propel:build‐all‐load

apps/frontend/modules/category/actions/actions.class.php class categoryActions extends sfActions { public function executeShow(sfWebRequest $request) { $this‐>category = $this‐>getRoute()‐>getObject(); } }

apps/frontend/modules/category/templates/showSuccess.php

... getActiveJobs() as $i => $job): ?> ...

Elementos parciales

elementos parciales “trozos de código de plantilla que se  pueden reutilizar en varias plantillas”

Son iguales que las plantillas en todo salvo que  su nombre empieza por un guión bajo (_)

apps/frontend/modules/job/templates/_list.php  $job): ?>
getLocation() ?> getPosition(), 'job_show_user', $job) ?> getCompany() ?>


apps/frontend/modules/job/templates/indexSuccess.php  $category‐>getActiveJobs( sfConfig::get('app_max_jobs_on_homepage') )) ) ?> apps/frontend/modules/job/templates/showSuccess.php  $category‐>getActiveJobs()) ) ?> 

Paginación

apps/frontend/modules/category/actions/actions.class.php public function executeShow(sfWebRequest $request) { $this‐>category = $this‐>getRoute()‐>getObject(); $this‐>pager = new sfPropelPager( 'JobeetJob', sfConfig::get('app_max_jobs_on_category') ); $this‐>pager‐>setCriteria( $this‐>category‐>getActiveJobsCriteria() ); $this‐>pager‐>setPage($request‐>getParameter('page', 1));  $this‐>pager‐>init();

app.yml

}

getResults() getNbResults() haveToPaginate() getLinks() getPage() getPreviousPage() getNextPage() getLastPage()

Capítulo 8

Pruebas unitarias

test/ unit/ Prueban funciones y  métodos individualmente

functional/ Prueban la aplicación en  su conjunto

El framework de  pruebas lime

require_once dirname(__FILE__).'/../bootstrap/unit.php'; $t = new lime_test(1, new lime_output_color());

número de pruebas  esperadas

ok($condicion) is($valor1, $valor2) isnt($valor1, $valor2) like($cadena, $expresionRegular) unlike($cadena, $expresionRegular) is_deeply($array1, $array2)

Ejecutando pruebas  unitarias

test/unit/JobeetTest.php require_once dirname(__FILE__).'/../bootstrap/unit.php'; $t = new lime_test(1, new lime_output_color()); $t‐>pass('This test always passes.');

$ ./symfony test:unit Jobeet

Probando el método  slugify()

Sensio Labs Paris, France

sensio‐labs paris‐france test/unit/JobeetTest.php

require_once dirname(__FILE__).'/../bootstrap/unit.php';  $t = new lime_test(6, new lime_output_color());  $t‐>is(Jobeet::slugify('Sensio'), 'sensio');  $t‐>is(Jobeet::slugify('sensio labs'), 'sensio‐labs');  $t‐>is(Jobeet::slugify('sensio labs'), 'sensio‐labs');  $t‐>is(Jobeet::slugify('paris,france'), 'paris‐france');  $t‐>is(Jobeet::slugify(' sensio'), 'sensio');  $t‐>is(Jobeet::slugify('sensio '), 'sensio');

test/unit/JobeetTest.php require_once dirname(__FILE__).'/../bootstrap/unit.php';  $t = new lime_test(6, new lime_output_color());  $t‐>comment('::slugify()'); $t‐>is(Jobeet::slugify('Sensio'), 'sensio', '::slugify() pasa la cadena de texto a minúsculas'); $t‐>is(Jobeet::slugify('sensio labs'), 'sensio‐labs', '::slugify() sustituye los espacios en blanco por ‐'); ...

Pruebas unitarias  para Propel

$ mysqladmin ‐uroot ‐p create jobeet_test $ symfony configure:database ‐‐env=test "mysql:host=localhost;dbname=jobeet_test" root ConTraSenA config/databases.yml

dev: propel: class: sfPropelDatabase param: classname: DebugPDO

config/databases.yml

test: propel: class: sfPropelDatabase param: classname: DebugPDO dsn:       'mysql:host=localhost;dbname=jobeet_test' all: propel: class: sfPropelDatabase param: dsn:      'mysql:host=localhost;dbname=jobeet' username: root password: null

test/bootstrap/propel.php include(dirname(__FILE__).'/unit.php'); $configuration = ProjectConfiguration::getApplicationConfiguration(

'frontend', 'test', true ); new sfDatabaseManager($configuration); $loader = new sfPropelData(); $loader‐>loadData(sfConfig::get('sf_test_dir').'/fixtures');

test/unit/model/JobeetJobTest.php include(dirname(__FILE__).'/../../bootstrap/propel.php'); $t = new lime_test(1, new lime_output_color()); $t‐>comment('‐>getCompanySlug()'); $job = JobeetJobPeer::doSelectOne(new Criteria()); $t‐>is( $job‐>getCompanySlug(), Jobeet::slugify($job‐>getCompany()), '‐>getCompanySlug() devuelve el slug del nombre de la empresa' );

Conjuntos de  pruebas unitarias

$ ./symfony test:unit

Capítulo 9

Pruebas  funcionales

La clase sfBrowser

sfBrowser

servidor web

aplicación  Symfony

aplicación  Symfony

get()

reload()

setHttpHeader()

post()

click()

setAuth()

call()

select()

setCookie()

back()

deselect() removecookie()

forward()

restart()

clearCookie() followRedirect()

$browser = new sfBrowser(); $browser‐> get('/')‐> click('Design')‐> get('/category/programming?page=2')‐> get('/category/programming', array('page' => 2))‐> post('search', array('keywords' => 'php')) ;

La clase  sfTestFunctional

sfBrowser sfTestFunctional

request

user

response

test/functional/frontend/

categoryActionsTest.php

include(dirname(__FILE__).'/../../bootstrap/functional.php'); $browser = new sfTestFunctional(new sfBrowser()); $browser‐> get('/category/index')‐> with('request')‐>begin()‐> isParameter('module', 'category')‐> isParameter('action', 'index')‐> end()‐> with('response')‐>begin()‐> isStatusCode(200)‐> checkElement('body', '!/This is a temporary page/')‐> end() ;

interfaz fluída ___()

___()

___()

___()

request

response

isParameter()

checkElement()

isFormat()

isHeader()

isMethod()

isStatusCode()

hasCookie()

isRedirected()

isCookie()

Ejecutando pruebas  funcionales

$ ./symfony test:functional frontend categoryActions

Datos de prueba

lib/test/JobeetTestFunctional.class.php class JobeetTestFunctional extends sfTestFunctional { public function loadData() { $loader = new sfPropelData(); $loader‐>loadData( sfConfig::get('sf_test_dir').'/fixtures' ); return $this; } }

Conjuntos de  pruebas funcionales

$ ./symfony test:functional frontend

Conjuntos de  pruebas

+

$ symfony test:unit $ symfony test:functional frontend $ symfony test:functional backend $ symfony test:functional ......

$ symfony test:all

Capítulo 10

Los formularios

1.

Crear código HTML del formulario

2.

Definir reglas de validación para los datos

3.

Procesar valores enviados por el usuario

4.

Guardar la información en la base de datos

5.

Mostrar posibles mensajes de error

6.

Volver a mostrar los datos en el formulario

Symfony ya incluye... • Validación (para cada campo) • Widgets (campos del formulario) • Formularios (widgets + validación)

Formularios

class ContactForm extends sfForm { public function configure() { $this‐>setWidgets(array( 'email' => new sfWidgetFormInput(), 'message' => new sfWidgetFormTextarea(), )); $this‐>setValidators(array( 'email' => new sfValidatorEmail(), 'message' => new sfValidatorString(array( 'max_length' => 255) ), )); } }

sfWidgetFormChoice

sfWidgetFormInputHidden

sfWidgetFormChoiceMany

sfWidgetFormInputPassword

sfWidgetFormDate

sfWidgetFormPropelChoice

sfWidgetFormDateRange

sfWidgetFormPropelChoiceMany

sfWidgetFormDateTime

sfWidgetFormPropelSelect

sfWidgetFormFilterDate

sfWidgetFormPropelSelectMany

sfWidgetFormFilterInput

sfWidgetFormSchema

sfWidgetFormI18nDate

sfWidgetFormSchemaDecorator

sfWidgetFormI18nDateTime

sfWidgetFormSchemaForEach

sfWidgetFormI18nSelectCountry

sfWidgetFormSchemaFormatter

sfWidgetFormI18nSelectCurrency

sfWidgetFormSelect

sfWidgetFormI18nSelectLanguage

sfWidgetFormSelectCheckbox

sfWidgetFormI18nTime

sfWidgetFormSelectMany

sfWidgetFormInput

sfWidgetFormSelectRadio

sfWidgetFormInputCheckbox

sfWidgetFormTextarea

sfWidgetFormInputFile

sfWidgetFormTime

sfWidgetFormInputFileEditable

$this‐>mergeForm(new OtroForm()); $this‐>embedForm('name', new OtroForm());

Formularios de  Propel

schema.yml $ ./symfony propel:build‐forms

JobeetJobForm

JobeetCategoryForm

lib/form/

JobeetAffiliateForm

class JobeetJobForm extends BaseJobeetJobForm { public function configure() { unset( $this['created_at'], $this['updated_at'], $this['expires_at'], $this['is_activated'] ); } }

class JobeetJobForm extends BaseJobeetJobForm { public function configure() { ... $this‐>validatorSchema['email'] =  new sfValidatorEmail();  } }

class JobeetJobForm extends BaseJobeetJobForm { public function configure() { ... $this‐>widgetSchema['type'] = new sfWidgetFormChoice(array( 'choices' => JobeetJobPeer::$types, 'expanded' => true, )); } class JobeetJobPeer extends BaseJobeetJobPeer { static public $types = array( } 'full‐time' => 'Full time', 'part‐time' => 'Part time', 'freelance' => 'Freelance', ); // ... }

sfWidgetFormChoice multiple

expanded

false

false

true

false

false

true

true

true

widget

class JobeetJobForm extends BaseJobeetJobForm { public function configure() { ... $this‐>validatorSchema['type'] =  new sfValidatorChoice(array( 'choices' => array_keys(JobeetJobPeer::$types), ));

} }

class JobeetJobForm extends BaseJobeetJobForm { public function configure() { ... $this‐>widgetSchema‐>setLabels(array( 'category_id' => 'Category', 'is_public' => 'Public?', 'how_to_apply' => 'How to apply?', )); } }

class JobeetJobForm extends BaseJobeetJobForm { public function configure() { ... $this‐>widgetSchema['logo'] =  new sfWidgetFormInputFile(array( 'label' => 'Company logo', )); $this‐>validatorSchema['logo'] =  new sfValidatorFile(array( 'required' => false, 'label' => sfConfig::get('sf_upload_dir').'/jobs', 'mime_types' => 'web_images', )); } }

sfValidatorFile 1.

Valida que el archivo subido sea una  imagen

2.

Cambia el nombre del archivo por un  valor único

3.

Guarda el archivo en la ruta indicada

4.

Actualiza el valor de la columna logo

class JobeetJobForm extends BaseJobeetJobForm { public function configure() { ... $this‐>widgetSchema‐>setHelp( 'is_public', 'Indica si la oferta de trabajo se puede publicar en sitios web de afiliados' ); } }

apps/frontend/modules/job/templates/

newSuccess.php

Post a Job

 $form)) ?>

parcial  _form

apps/frontend/modules/job/templates/

_form.php



method, enctype

 


Formulario

Widgets

render()

renderRow()

renderHiddenFields()

render()

hasErrors()

renderLabel()

hasGlobalErrors()

renderError()

getGlobalErrors()

renderHelp()

renderGlobalErrors()



renderRow() ?>  

apps/frontend/modules/job/actions/ public function

executeNew(sfWebRequest

actions.class.php

$request) {

... } public function

executeCreate(sfWebRequest

$request) {

... } public function

executeEdit(sfWebRequest

$request) {

... } public function

executeUpdate(sfWebRequest

$request) {

executeDelete(sfWebRequest

$request) {

... } public function

... } protected function

{  ... }

processForm(sfWebRequest

$request, sfForm $form)

apps/frontend/modules/job/actions/

actions.class.php

public function executeNew(sfWebRequest $request) { $job = new JobeetJob(); $job‐>setType('full‐time'); $this‐>form = new JobeetJobForm($job); }

lib/model/

JobeetJob.php

public function save(PropelPDO $con = null) { // ... if (!$this‐>getToken()) { $this‐>setToken( sha1($this‐>getEmail().rand(11111, 99999)) ); } return parent::save($con); } lib/form/

JobeetJobForm.class.php

class JobeetJobForm extends BaseJobeetJobForm { public function configure() { unset( $this['token'] ); } }

apps/frontend/config/

routing.yml

job: class:        sfPropelRouteCollection options:      { model: JobeetJob, column: token } requirements: { token: \w+ }

http://localhost.jobeet/job/TOKEN/edit

La página de  previsualización

apps/frontend/modules/category/templates/showSuccess.php getParameter('token') == $job‐>getToken()): ?>

 $job)) ?>

apps/frontend/modules/job/templates/_admin.php

Admin

    getIsActivated()): ?>
  •  
  • ... isExpired()): ?> Expired Expires in <strong> getDaysBeforeExpires() ?> days ...

    Activando y  publicando las  ofertas

    apps/frontend/config/

    routing.yml

    job: class:   sfPropelRouteCollection options: model:          JobeetJob column:         token

    object_actions: { publish: put } requirements: token: \w+

    apps/frontend/modules/job/actions/actions.class.php public function executePublish(sfWebRequest $request) { $request‐>checkCSRFProtection(); $job = $this‐>getRoute()‐>getObject(); $job‐>publish(); $this‐>getUser()‐>setFlash( 'notice', sprintf('Your job is now online for %s days.',  sfConfig::get('app_active_days')) ); $this‐>redirect($this‐>generateUrl('job_show_user', $job)); }

    Capítulo 11

    Probando los  formularios

    Enviando un  formulario

    test/functional/frontend/jobActionsTest.php $browser‐>info('3 ‐ Post a Job page')‐> info(' 3.1 ‐ Submit a Job')‐> get('/job/new')‐> with('request')‐>begin()‐> isParameter('module', 'job')‐> isParameter('action', 'new')‐> end()‐>

    Preview your job

    click('Preview your job', array('job' => array( 'company' => 'Sensio Labs', 'url' => 'http://www.sensio.com/', 'logo' => sfConfig::get('sf_upload_dir').'/jobs/sensio‐labs.gif',  'position' => 'Developer', 'location' => 'Atlanta, USA', 'is_public' => false, )))‐> with('request')‐>begin()‐> isParameter('module', 'job')‐> isParameter('action', 'create')‐> end()‐> ;

    Seguridad

    $ symfony generate:app jobeet ‐‐escaping‐strategy=on ‐‐csrf‐secret=secreto frontend

    XSS

    Soy un usuario  malvado

    y voy a meter JS  <script  type="text/javascript ">document.write("Hol a!")

    <p>Soy un  usuario  malvado</p> y voy a meter JS <script type="text/javas cript">docume nt.write("Hola!& quot;)</script> 

    $ symfony generate:app jobeet ‐‐escaping‐strategy=on ‐‐csrf‐secret=secreto frontend

    CSRF



    ...


    value="..." />  ...

    Tareas de  mantenimiento

    $ php lib/vendor/symfony/data/bin/symfony

    lib/task/JobeetCleanupTask.class.php class JobeetCleanupTask extends sfBaseTask { protected function configure() { $this‐>addOptions(array( new sfCommandOption('env', null, sfCommandOption::PARAMETER_REQUIRED,  'The environement', 'prod'), new sfCommandOption('days', null, sfCommandOption::PARAMETER_REQUIRED,  '', 90), )); $this‐>namespace = 'jobeet'; $this‐>name = 'cleanup'; $this‐>briefDescription = 'Cleanup Jobeet database'; $this‐>detailedDescription = <<<EOF The [jobeet:cleanup|INFO] task cleans up the Jobeet database:  jobeet:cleanup ‐‐env=prod ‐‐days=90|INFO] EOF; }

    [./symfony 

    protected function execute($arguments = array(), $options = array()) { $databaseManager = new sfDatabaseManager($this‐>configuration); $nb = JobeetJobPeer::cleanup($options['days']); $this‐>logSection('propel', sprintf('Removed %d stale jobs', $nb)); } }

Related Documents


More Documents from ""

Blender - Tutorial Casa
October 2019 12
December 2019 15
Curso Symfony Clase 2
June 2020 12
Curso Symfony Clase 4
June 2020 12
Blender - Tutorial Ginger
October 2019 20