symfony: simplify your professional web development with php (ipc frankfurt 2007)

86
International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com symfony Simplify your professional web development with PHP Fabien Potencier http://www.symfony-project.com/ http://www.sensiolabs.com/

Upload: fabien-potencier

Post on 06-May-2015

5.079 views

Category:

Technology


3 download

TRANSCRIPT

Page 1: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

symfonySimplify your professional

web development with PHP

Fabien Potencierhttp://www.symfony-project.com/

http://www.sensiolabs.com/

Page 2: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

Sensio• French Web Agency, founded in 1998

– 150 people– 30 people dedicated to Web technologies

Webmarketing

Open SourceTechnologies

(Framework PHP)

WebTechnologies

SENSIOWeb Agency

Page 3: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

Sensio Labs• Open-Source technologies

– Linux– Apache– MySQL / PostgreSQL– PHP / Perl / Python

• Open-Source dedicated team• Big company customers

– Web Consulting– Audit / Training– Web Development

symfony PHP Framework

Page 4: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

The symfony Framework• PHP 5 Web Framework• Based on 9 years of Sensio experience• Based on well-known projets (Mojavi, Propel, Prado)

• Open-Source• Built for :

– Professional Websites– Complex needs– Demanding environments Licence

MIT

Page 5: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

The symfony Goals

• Bring together the « Entreprise World »and the Open-Source World

• Develop Faster

• Don’t Reinvent the Wheel

Page 6: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

Develop Faster• Each line of code has a cost

– To write the line– To test it– To maintain it

• Write less code– Architecture : controller, ORM, …– Configuration– Autoloading– Generators– Helpers

• More time for business rules, edge cases, …

less code

less complexity

less bugs

more productivity

more time

Page 7: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

Don’t Reinvent the Wheel• Follow best practices• MVC Pattern : Model / View / Controller

• Unit and functional test framework

• Environment and deployment support• Configurability• Security (XSS and CSRF protection by default)• Extensible (plugin system)• Admin Generator Simplify

your Dev. Life

Page 8: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

Main Selling Points• symfony is about good code but also …

• Documentation– GFDL book (450p)– The askeet tutorial (250p)

• 1.0 maintained for a long time– 1 release a month (only bug fixes)– Commercial support

1.0

Page 9: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

Let’s see some features

Page 10: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

Controller# apps/frontend/modules/blog/actions/actions.class.phpclass blogActions extends sfActions{ function executeShow() { $id = $this->getRequestParameter('id'); $this->post = PostPeer::retrieveByPk($id);

$this->forward404Unless($this->post); }}

Shortcut

Controller blog/show

For the View

Model call (Propel)

Page 11: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

Controllerclass blogActions extends sfActions{ function executeShow() { $this->forward404Unless( $this->post = PostPeer::retrieveByPk($this->getRequestParameter('id')) ); }}

class blogActions extends sfActions{ function showAction($request) { $this->forward404Unless( $this->post = PostPeer::retrieveByPk($request->getParameter('id')) ); }}

1.0

1.1

Page 12: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

Controller (Doctrine)# apps/frontend/modules/blog/actions/actions.class.phpclass blogActions extends sfActions{ function executeShow() { $id = $this->getRequestParameter('id'); $this->post = Doctrine::getTable('Post')->find($id);

$this->forward404Unless($this->post); }}

Page 13: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

Model (Propel)// lib/model/Author.phpclass Author extends BaseAuthor{ function getFullName() { return $this->getFirstName().' '.$this->getLastName(); }}

$author = new Author();$author->setFirstName('Fabien');$author->setLastName('Potencier');$author->save();

$post = new Post();$post->setAuthor($author);$post->setPublishedOn('tomorrow 12:00');$post->isPublished(true);$post->save();

$posts = PostPeer::doSelect(new Criteria());

Page 14: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

Model (Doctrine)// lib/model/doctrine/lib/Author.phpclass Author extends BaseAuthor{ function getFullName() { return $this->getFirstName().' '.$this->getLastName(); }}

$author = new Author();$author->setFirstName('Fabien');$author->setLastName('Potencier');$author->save();

$post = new Post();$post->setAuthor($author);$post->setPublishedOn('tomorrow 12:00');$post->isPublished(true);$post->save();

$posts = Doctrine::getTable('Post')->findAll();

$post = Doctrine::getTable('Post')->find($request->getParameter('id'));

Same as in Propel

Page 15: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

View / Template# apps/frontend/modules/post/templates/showSuccess.php<h1 class="title"> <?php echo $post->getTitle() ?></h1>

<h2> par <?php echo $post->getAuthor()->getFullName() ?></h2>

<p> <?php echo $post->getHtmlContent(ESC_RAW) ?></p>

Raw Value

Escaped Escaped

Page 16: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

Routing

link_to( $post->getTitle(), '@post?id='.$post->getId())

post: param: { module: blog, action: show } requirements: id: \d+ url: /blog/:id

url_for('@homepage')homepage: param: { module: blog, action: recent } url: /

/blog/1

/

homepage: param: { module: blog, action: list } url: /recent: param: { module: blog, action: recent } url: /recent

/

/recent

Page 17: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

Routing in a Template<?php echo link_to($post->getTitle(), '@post?id='.$post->getId()) ?>

<a href="<?php echo url_for('@post?id='.$post->getId()) ?>">Next Post</a>

<?php echo link_to('Google', 'http://www.google.com/') ?>

Be pragmatic

<a href="http://www.google.com/">Google</a>

Page 18: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

Tests: Database Fixtures• Test data # data/fixtures/data.yml Author: fabien: first_name: Fabien last_name: Potencier Post: first_post: author_id: fabien title: IPC 2007 Conference

$ ./symfony propel-load-data frontend

Page 19: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

Functional Tests• Navigation simulation // test/functional/frontend/blogActionsTest.php $browser = new sfTestBrowser(); $browser->initialize(); $browser-> get('/blog/1')-> isStatusCode(200)-> checkResponseElement('h1.title', '/IPC 2007 Conference/');

TDDTest Driven Development

The power of CSS selectors

FluentInterface

Page 20: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

Be Happy… or not$ ./symfony test-functional frontend# get /ok 1 - status code is 200not ok 2 - response selector h1 does not match regex /IPC 2007 Conference/1..2 Looks like you failed 1 tests of 2.

$ ./symfony test-functional frontend# get /ok 1 - status code is 200ok 2 - response selector h1 matches regex /IPC 2007 Conference/1..2 Looks like everything went fine.

Page 21: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

Functional Tests# simple CSS selectorscheckResponseElement('h1.title', '/IPC 2007 Conference/')checkResponseElement('#title', '/IPC 2007 Conference/')

# attribute selectorscheckResponseElement('ul li a[class~="title"]', '/IPC 2007 Conference/')

# combinators: > and +checkResponseElement('ul > li', '/IPC 2007 Conference/')

# some CSS3 selectorscheckResponseElement('#list li:first-child', '/IPC 2007 Conference/')checkResponseElement('#list li:nth-child(3)', '/IPC 2007 Conference/')checkResponseElement('#list li:contains("IPC 2007 Conference")')

Page 22: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

Functional Testsclass ApplicationBrowser extends sfTestBrowser{ public function signin($user, $password) { return $this-> post('/signin', array('username' => $user, 'password' => $password))-> isRedirect()-> followRedirect()-> checkResponseElement('div.username', 'Welcome back Fabien'); }

public function signout() { return $this->get('/signout'); }}

DSLYour own specific browser

Page 23: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

Admin Generator: Backend Creation• Automatic generation of an Administration

Backend, ready for production usage– Lists– Pagination– Sorting

$ ./symfony propel-init-admin frontend post Post

1) Creates a post module2) Generates configuration

– Filters– Validation– CRUD

Page 24: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

Admin Generator• Generated code is MVC and customizable

– Configuration file (generator.yml)– Extend the Controller– Override some Templates / Partials

Page 25: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

Admin Generator: Configurability# apps/frontend/modules/post/config/generator.yml generator: class: sfPropelAdminGenerator param: model_class: Post list: display: [=title, author, created_at] filters: [title, author_id, published_on] max_per_page: 5

Page 26: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

Admin Generator• List

Page 27: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

Admin Generator• Edition

__toString()

widgets m2m relationship

Page 28: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

Admin Generator: Extensibility• Module extension class postActions extends autoPostActions { protected function addFiltersCriteria($c) { parent::addFiltersCriteria($c); $c->add(PostPeer::IS_PUBLISHED, true); } }

• Template customization

Generatedmodule

_edit_* : actions, footer, form, header, messages_list_* : footer, header, messages, td_actions, t(d|h)_stacked, t(d|h)_tabular_filters, editSuccess, listSuccess

Page 29: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

Debugging Tools• Web Debug Toolbar

Page 30: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

Debugging Tools• Error messages

Page 31: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

What’s New in symfony 1.1?• A new task framework• Decoupling

– Remove singletons– Remove dependencies between core classes– New Event Dispatcher system

• Form / Validation framework

Page 32: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

New Task Framework• Easier to extend the symfony tasks• Task namespaces• Built-in help system• Tasks are decoupled from the CLI

– Can be called from the CLI– … or from your own code… easily

Page 33: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

Task Namespacesgenerate :app Generates a new application (init-app) :batch Generates a new batch (init-batch) :controller Generates a new controller (init-controller) :module Generates a new module (init-module) :project Generates a new project (init-project)

test :all Launches all tests :functional Launches functional tests :unit Launches unit tests

i18n :extract Extracts i18n strings from php files :find Finds non "i18n ready" strings in an application

Page 34: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

Task Help$ ./symfony help plugin:install

Usage: symfony plugin:install [--stability|-s="..."] [--release|-r="..."] [--channel|-

c="..."] [--install_deps|-d] name

Aliases: plugin-install

Arguments: name The plugin name

Options: --stability (-s) The preferred stability (stable, beta, alpha) --release (-r) The preferred version --channel (-c) The PEAR channel name --install_deps (-d) Whether to force installation of required dependencies

Description: …

Page 35: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

Task HelpDescription: The plugin:install task installs a plugin:

./symfony plugin:install sfGuargPlugin

By default, it installs the latest stable release.

If you want to install a plugin that is not stable yet, use the stability option:

./symfony plugin:install --stability=beta sfGuargPlugin ./symfony plugin:install -s beta sfGuargPlugin

You can also force the installation of a specific version:

./symfony plugin:install --release=1.0.0 sfGuargPlugin ./symfony plugin:install -r 1.0.0 sfGuargPlugin

To force installation of all required dependencies, use the install_deps flag:

./symfony plugin:install --install-deps sfGuargPlugin ./symfony plugin:install -d sfGuargPlugin

By default, the PEAR channel used is symfony-plugins (plugins.symfony-project.org).

You can specify another channel with the channel option:

./symfony plugin:install --channel=mypearchannel sfGuargPlugin ./symfony plugin:install -c mypearchannel sfGuargPlugin…

Page 36: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

Task Calls in your Code# Somewhere in your code

$task = new sfCacheClearTask($dispatcher);$task->run();

Page 37: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

symfony 1.0 Dependencies

CleanupDependencies

sfRequest

sfResponse

sfContext

sfUsersfStorage

sfRouting

sfI18NsfLogger

sfView

singleton dependency

Page 38: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

symfony 1.1 Dependencies

CleanupDependencies

sfRequestsfResponse

sfContext

sfUser

sfStorage

sfRouting

sfI18N

sfLogger

sfEventDispatcher

sfView

singleton dependency

Page 39: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

sfEventDispatcher• Based on Cocoa Notification Center// sfUser$event = new sfEvent($this, 'user.change_culture', array('culture' => $culture));$dispatcher->notify($event);

// sfI18N$callback = array($this, 'listenToChangeCultureEvent');$dispatcher->connect('user.change_culture', $callback);

• sfI18N and sfUser are decoupled• « Anybody » can listen to any event• You can notify existing events or create new ones

Page 40: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

Form & Validation Framework• Not a refactoring• A different approach• Almost no shared code• Symfony 1.1 can still use the old system

– set compat_10: on in settings.yml (off by default)– you can use the new and the old system in the same

application– symfony 1.0 sfValidator class has been renamed to

sfValidatorBase to avoid class name conflicts

Page 41: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

The New Approach• Form as a first class object• Widget classes for form helpers• Validators validate arrays (it doesn’t care if it

comes from a request, an XML file or a modelobject)

• A decoupled system– Can be used without any other symfony class– 3 differents sub-systems

• Validators: can be used by themselves• Widgets: can be used by themselves• Form: glue between validators and widgets

Page 42: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

Validators• Every validator extends sfValidator• A validator cleans and validates input values• sfValidator provides some common features

– required (validation) > true by default– trim (cleaning) > false by default

• Each validator can have options:– sfValidatorString: max_length, min_length

Page 43: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

Validators// create a new string validator$v = new sfValidatorString(array('min_length' => 4));

// clean and validate data$value = $v->clean('Fabien');

// returns the input value$value == 'Fabien'

// change some option$v->setOption('trim', true);

$value = $v->clean(' Fabien ');

// trims the input value$value == 'Fabien' Validator objects

are stateless

Page 44: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

Custom Validatorclass CustomValidator extends sfValidator{ protected function configure($options = array(), $messages = array()) { $this->setOption('min_length', null); $this->setMessage('min_length', 'Too short.'); }

protected function doClean($value) { if (strlen($value) < $this->getOption('min_length')) { throw sfValidatorError($this, 'min_length', array('value' => $value)); }

return $value; }}

Page 45: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

Validators$v = new sfValidatorString(array('min_length' => 4));

// throws a sfValidatorError$v->clean('Jon');

$e->getCode() == 'min_length'$e->getMessage() == '"Jon" is too short (4 characters min).'

$v->setMessage('min_length', 'Too short (%name%).');$e->getMessage() == 'Too short (Jon).'

Use error codesor error messages

Page 46: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

Errors Internationalization$v = new sfValidatorString(array('min_length' => 4));

try{ $value = $v->clean('Jon');}catch (sfValidatorError $e){ echo $i18n->__($e->getMessageFormat(), $e->getArguments())."\n"; // or echo $i18n->__($e->getCode(), $e->getArguments())."\n";}

Error messagesare i18n ready

Page 47: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

sfValidator(All|Any)• You can aggregate validators to create a new validator:

– sfValidatorAll: All validators must pass– sfValidatorAny: At least one validator must pass

$v1 = new sfValidatorString(array('min_length' => 4));$v2 = new sfValidatorString(array('max_length' => 10));

$v = new sfValidatorAll(array($v1, $v2));

// values must validate both validators$v->clean('Fabien');

Page 48: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

sfValidator(All|Any)• As they are validators themselves, you can create

complex logic to validate your values:

// v1 && (v2 || v3) $v = new sfValidatorAll( array($v1, sfValidatorAny($v2, $v3)) );

Page 49: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

sfValidatorSchema• A validator schema is composed of fields• A field is a named validator

$v1 = new sfValidatorString(array('min_length' => 4));

$v = new sfValidatorSchema(array( 'first_name' => $v1, 'last_name' => $v1, ));

Page 50: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

sfValidatorSchema• The clean() method takes an array of named

values and returns an array:

$v->clean(array( 'first_name' => 'Fabien', 'last_name' => 'Potencier', ));

Page 51: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

sfValidatorSchema

• It collects all errors for all fields• It throws an exception with all errors

sfValidatorErrorSchema: first_name: "Jon" is too short (4 characters min). last_name: "Jon" is too short (4 characters min). in ….php on line …

Page 52: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

sfValidatorSchema• A named validator does not have access to the

whole array of inputs, just its named value• Two special validators:

– _pre_validator and _post_validator– They takes the array of values as input– They throw « global » errors

Isolation

Page 53: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

sfValidatorSchema$v2 = new sfValidatorSchemaCompare( 'password', '==', 'password_bis');

$v = new sfValidatorSchema(array( 'password' => $v1, 'password_bis' => $v1,

'_post_validator' => $v2,));

sfValidatorErrorSchema:   "pass" does not match "word". in ….php on line …

Page 54: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

sfValidatorSchema• sfValidatorSchema is a sfValidator, so you can nest them

$authorValidator = new sfValidatorSchema(array( 'first_name' => $v1, 'last_name' => $v1,));

$bookValidator = new sfValidatorSchema(array( 'title' => $v1, 'sub_title' => $v1, 'author' => $authorValidator,));

Page 55: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

sfValidatorSchema$bookValidator->clean(array( 'title' => 'The symfony book', 'sub_title' => 'The definitive guide', 'author' => array( 'first_name' => 'Fabien', 'last_name' => 'Potencier', ),));

Page 56: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

sfValidatorSchema• Secure by default

– allow_extra_fields (false by default)– filter_extra_fields (true by default)

• If you pass a value with no matching validator, sfValidatorSchemawill throw an error

• If you switch allow_extra_fields to true, then extra fields won’ttrigger an error but will be removed from the cleaned values

• If you also switch filter_extra_fields to false, then extra fields won’tbe removed from the cleaned values

Page 57: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

sfValidatorSchemaForEach$choiceValidator = new sfValidatorSchema(array( 'choice' => $v1,));

$choicesValidator = new sfValidatorSchemaForEach($choiceValidator, 3);

$pollValidator = new sfValidatorSchema(array( 'question' => $v1, 'choices' => $choicesValidator,));

Page 58: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

sfValidatorSchemaForEach$pollValidator->clean(array( 'question' => 'Do you like symfony?', 'choices' => array( array('choice' => 'Yes'), array('choice' => 'This is the best'), array('choice' => 'A lot'), ),));

Page 59: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

Validators as Strings$postValidator = new sfValidatorOr(array( new sfValidatorSchemaFilter('age', new sfValidatorInteger(array('min' => 18))), new sfValidatorAll(array( new sfValidatorSchemaFilter('age', new sfValidatorInteger(array('max' => 18))), new sfValidatorSchemaFilter('is_young', new sfValidatorBoolean(array('required' => true))), )),));

$string = $postValidator->asString();' age:Integer({min: 18}) or age:Integer({max: 18}) and is_young:Boolean({required: true})'

$postValidator = new sfValidatorFromDescription($string);

$postValidator->asPhp();

Page 60: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

Available Validators• Boolean• Choice• ChoiceMany• Date• DateTime• Email• Integer• Number• Regex• String• Time• Url

• All• Any• Callback• Decorator• Pass• FromDescription

• Schema• SchemaForEach• SchemaCompare• SchemaFilter

Page 61: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

Widgets• Every widget extends sfWidget• A widget is an object that can be rendered as an HTML

string• sfWidget provides some common features

– renderTag()– renderContentTag()– Charset support– XHTML or HTML closing tags

• Each widget can have HTML attributes:– Takes care of escaping– Fixes double escaping problems

Page 62: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

sfWidgetForm• Base class for all form widgets• Some more properties like isHidden()• Generates an id if none provided and the widget

has a name– Default id is the widget name– Can be customized

$w = new sfWidgetFormInput(); $w->setIdFormat('id_%s');

Page 63: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

sfWidgetForm classes// create a new input widget$w = new sfWidgetFormInput();

// render widgetecho $w->render('first_name', 'Fabien');

// returns the widget as HTML<input type="text" name="first_name" value="Fabien" id="first_name" />

// change some attributes$w->setAttribute('class', 'foo');

<input … class="foo" /> Widget objectsare stateless

Page 64: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

sfWidgetForm classes// add default HTML attributes$w = new sfWidgetFormInput(array('class' => 'foo'));

// render widget with some HTML attributesecho $w->render('first_name', 'Fabien', array('class' => 'foo'));

Page 65: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

sfWidgetFormSchema• A widget schema is composed of fields• A field is a named widget

$w1 = new sfWidgetFormInput();

$w = new sfWidgetFormSchema(array( 'first_name' => $w1, 'last_name' => $w1, ));

Page 66: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

sfWidgetFormSchema• The render() method takes an array of named

values and returns an HTML string:

$w->render(null, array( 'first_name' => 'Fabien', 'last_name' => 'Potencier', ));

• You can also render individual fields

Page 67: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

sfWidgetFormSchema• sfWidgetFormSchema is a sfWidget, so you can nest

them

$authorWidget = new sfWidgetFormSchema(array( 'first_name' => $w1, 'last_name' => $w1,));

$bookWidget = new sfWidgetFormSchema(array( 'title' => $w1, 'sub_title' => $w1, 'author' => $authorValidator,));

Page 68: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

sfWidgetFormSchema$bookWidget->render(null, array( 'title' => 'The symfony book', 'sub_title' => 'The definitive guide', 'author' => array( 'first_name' => 'Fabien', 'last_name' => 'Potencier', ),));

Page 69: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

sfWidgetFormSchema• The render() method can also render

– Errors– Nested form schema

• The render() method uses a formatter class– sfWidgetFormSchemaFormatterList– sfWidgetFormSchemaFormatterTable– Or build your own

Page 70: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

Forms• A sfForm is the glue between

– A validator schema– A widget schema

$validator = new sfValidatorSchema();$widget = new sfWidgetFormSchema();

$form = new sfForm();$form->setValidatorSchema($validator);$form->setWidgetSchema($widget);

Page 71: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

sfForm• You can also create your own form class

class BookForm extends sfForm{ public function configure() { $validator = new BookValidatorSchema(); $widget = new BookWidgetFormSchema();

$this->setValidatorSchema($validator); $this->setWidgetSchema($widget); }}

Page 72: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

A Form in a Form$authorForm = new AuthorForm();

$bookForm->embedForm($authorForm);

$choiceForm = new ChoiceForm();

$pollForm->embedFormForEach($choiceForm, 4);

Page 73: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

sfForm$form = new AuthorForm();

$input = array('first_name' => 'Fabien', 'last_name' => 'Potencier');

$form->bind($input);if ($form->isValid()){ // do something with the cleaned values $form->getValues();}else{ // do something with the errors $form->getErrorSchema();}

Page 74: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

sfForm• sfForm can take default values

$form = new AuthorForm(array('first_name' => 'Fabien'));

• sfFormField objects are widgets bound to theinput or default values

echo $form->getFormField('first_name')->render();

Page 75: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

sfForm

$form = new AuthorForm();

echo $form->getFormField('first_name')->render();// ===echo $form['first_name']->render();// ===echo $form['first_name'];

// name and value are bound to the sfFormField object<input type="text" name="first_name" value="Fabien" id="first_name" />

// add some HTML attributesecho $form['first_name']->render(array('class' => 'foo'));

Page 76: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

For the laziest

echo $form

Page 77: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

Customize your Forms<table>

<tr> <th>

<label for="book_author_first_name">First Name</label>

</th> <td> <ul class="error_list"> <li>Required.</li> </ul> <input type="text" name="book[author][first_name]" id="book_author_first_name" />

</td> </tr> ...</table>

$bookForm['author']

$bookForm['author']['first_name']->renderLabel()

$bookForm['author']['first_name']->renderLabelName()

$bookForm['author']['first_name']->renderError()

$bookForm['author']['first_name']

$bookForm['author']['first_name']->renderRow()

Page 78: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

Forms: In a symfony Actionclass bookActions extends sfActions{ public function executeEdit($request) { $this->form = new AuthorForm();

if ($request->isMethod('post')) { $this->form->bind($request->getParameter('book')); if ($this->form->isValid()) { $values = $this->form->getValues();

$this->redirect('@homepage'); } } }}

Page 79: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

sfFormPropel• Generated forms for Propel objects• Fully customizable• Introspects the Propel schema

– Maps Propel/Creole types to symfony validators andwidgets

– Foreign keys– Many to many relationships– Internationalized tables

Page 80: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

sfFormPropelclass bookActions extends sfActions{ public function executeEdit($request) { $this->book = BookPeer::retrieveByPk($request->getParameter('id')); $this->form = new AuthorForm($this->book);

if ($request->isMethod('post')) { $this->form->bind($request->getParameter('book'); if ($this->form->isValid()) { $book = $this->form->save();

$this->redirect('@book?id='.$book->getId()); } } }}

Page 81: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

Customize Propel Formsclass BookForm extends BaseBookForm{ public function configure() { $this->embedI18n(array('en', 'fr'));

$this->widgetSchema['en']->setLabel('en', 'English');

unset($this['created_at']);

$this->validatorSchema['foo'] = new sfValidatorPass(); $this->widgetSchema['foo'] = new sfWidgetIdentity();

$this->setDefault('published_on', time()); }}

Page 82: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

A Professional Web Framework

• Built from experience• 1.0 stable, maintained with commercial support• Growing community

– Developers in more than 80 countries– 200 000 visitors per month on symfony-project.com– 200 plugins in just 8 months

• Open-Source Documentation– The book (450 pages - GFDL)– Askeet Tutorial (250 pages)

Page 83: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

Yahoo! uses symfony• Yahoo! Bookmarks

– 20 millions users– Web 2.0 / AJAX

• del.icio.us– New beta on symfony– preview.delicious.com

Page 84: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

Next symfony Workshops

En français : Paris, France - Dec 05, 2007

In English : Paris, France - Feb 13, 2008

More info on www.sensiolabs.com

Page 85: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

Join Us• Sensio Labs is recruiting in France

– project managers– web developers

• You have a passion for the web?– Web Developer : You have a minimum of 3 years experience in

web development with Open-Source projects and you wish toparticipate to development of Web 2.0 sites using the bestframeworks available.

– Project Manager : You have more than 5 years experience as adeveloper and/or a project manager and you want to managecomplex Web projects for prestigious clients.

Page 86: symfony: Simplify your professional web development with PHP (IPC Frankfurt 2007)

International PHP 2007 Conference www.symfony-project.com [email protected] www.sensiolabs.com

SENSIO S.A.26, rue Salomon de Rothschild

92 286 SURESNES cedexFRANCE

Tél. : +33 1 40 99 80 80Fax : +33 1 40 99 83 34

ContactFabien Potencier

[email protected]

http://www.sensiolabs.com/ http://www.symfony-project.com/