Advanced symfony Techniques

Advanced symfony Techniques
          Kris Wallsmith
@kriswallsmith
•   Release Manager for symfony 1.3 & 1.4

•   On Symfony and Doctrine teams

•   Senior Software Engineer at

•   10 years experience with PHP and web development

•   Open source evangelist and international speaker

•   Hopeless plugin developer…
•   DbFinderPlugin                         •   sfPropelActAsPolymorphicBehaviorPlugin

•   sfControlPanelPlugin                   •   sfSimpleBlogPlugin

•   sfDoctrineDynamicFormRelationsPlugin   •   sfSimpleCMSPlugin

•   sfDoctrineMasterSlavePlugin            •   sfSimpleForumPlugin

•   sfFeed2Plugin                          •   sfSpyPlugin

•   sfFormYamlEnhancementsPlugin           •   sfSslRequirementPlugin

•   sfGoogleAnalyticsPlugin                •   sfStatsPlugin

•   sfGoogleWebsiteOptimizerPlugin         •   sfTaskExtraPlugin

•   sfModerationPlugin                     •   sfWebBrowserPlugin

•   sfPagerNavigationPlugin
Please see me if you want to
   help with or take over
   a plugin's maintenance.

Lots to choose from!
#phpmatsuri
  October 2-3, 2010
       Tokyo
#phpmatsuri
•   Around 90 attendees


•   CakePHP, Symfony, & Lithium
    were represented


•   Most folks were CakePHP users


•   CakePHP documentation was
    translated early, so…


•   Please help translate Symfony2 &
    Doctrine2 documentation!
Advanced symfony Techniques
CAUTION

PSEUDO CODE
   AHEAD
Host Aware Routing
domain.com
foobar.domain.com
barfoo.domain.com
homepage:
  url:   /
  param: { module: main, action: indexOrDash }
homepage:
  url:   /
  param: { module: main, action: indexOrDash }


       if (preg_match('/.../', $r->getHost(), $m))
class sfRoute

•   ->matchesUrl(...)
    Does the supplied URL match this route?


    GET / HTTP/1.0
    Host: foobar.domain.com
class sfRoute
                                                   Ver y slow

•   ->matchesUrl(...)
    url_for('main/dashboard?username=foobar')
    Does the supplied URL match this route?

•   ->matchesParameters(...)
    Do the supplied parameters match this route?
class sfRoute

 •   ->matchesUrl(...)
     Does the supplied URL match this route?

 • ->matchesParameters(...)
url_for('@dashboard?username=foobar')
   Do the supplied parameters match this route?

 •   ->generate(...)
     Generate a URL using this route and these parameters.
->matchesUrl(...)

•   $url
    The current URI

•   $context
    An array of contextual information, including the current host

•   Returns false or an array of parameters extracted from the URI
->matchesParameters(...)

•   $params
    An associative array of parameter names and values

•   $context
    An array of contextual information, including the current host

•   Returns true or false
->generate(...)
•   $params
    An associative array of parameter names and values

•   $context
    An array of contextual information, including the current host

•   $absolute
    Whether to generate an absolute URL

•   Returns the generated URL
Process the host string with a
   second, internal route
public function __construct(...)
{
  list($host, $pattern) = explode('/', $pattern, 2);

    $hostRoute = $this->createHostRoute($host, ...);

    parent::__construct(...);
}
public function matchesUrl($url, $c)
{
  // check parent::matchesUrl() first

    $hp = $hostRoute->matchesUrl('/'.$c['host'], $c);

    // include host parameters in return
}
public function matchesParameters($p, $c)
{
  $hp = $this->extractHostParams($p);

    return
      parent::matchesParameters($p, $c)
      &&
      $hostRoute->matchesParameters($hp, $c);
}
public function generate($p, $c, $abs)
{
  $hp = $this->extractHostParams($p);

    // protocol, prefix...

    $host = $hostRoute->generate($hp, $c, false);
    $uri = parent::generate($p, $c, false);

    return $protocol.':/'.$host.$prefix.$uri;
}
homepage:
  url:   /
  param: { module: main, action: indexOrDash }
Hard
                         co d
homepage:                     e
                              d F
                                  TL
  url:   domain.com/                  :(
  class: sfHostAwareRoute
  param: { module: main, action: index }

dashboard:
  url:   :username.domain.com/
  class: sfHostAwareRoute
  param: { module: main, action: dashboard }
homepage:
  url:   %APP_HOST%/
  class: sfHostAwareRoute
  param: { module: main, action: index }

dashboard:
  url:   :username.%APP_HOST%/
  class: sfHostAwareRoute
  param: { module: main, action: dashboard }
Custom Config Handler
class sfHostAwareRoutingConfigHandler
    extends sfRoutingConfigHandler
{
  protected function parse($configFiles)
  {
    return array_map(
      array($this, 'filterRoute'),
      parent::parse($configFiles)
    );
  }

    // ...
}
FTW!
                                         Free

protected function filterRoute($route)
{
  list($class, $args) = $route;

    $args[0] = $this->replaceConstants($args[0]);

    return array($class, $args);
}
# config_handlers.yml
config/routing.yml:
  class: sfHostAwareRoutingConfigHandler
  file: %SF_LIB_DIR%/sfHostAwareRout...
sfHostAwareRoutingPlugin
    Add subdomains to your routing rules.
Graceful POST Authentication
An example…
Advanced symfony Techniques
Advanced symfony Techniques
CENSORED




CENSORED
Advanced symfony Techniques
W here's my
            blog pos t!?
                        !




 AIL
F
Extend the security filter
class GracefulSecurityFilter
    extends sfBasicSecurityFilter
{
  protected function forwardToLoginAction()
  {
    // stash the interrupted request
    $attr->add(array(
      'module' => $context->getActionName(),
      'action' => $context->getModuleName(),
      'method' => $request->getMethod(),
      'params' => $requestParams->getAll(),
    ), 'stash');

        parent::forwardToLoginAction();
    }
}
# filters.yml
security:
  class: GracefulSecurityFilter
Replay the stashed request
        after login
// called after authentication
protected function replayStashedRequest()
{
  if ($s = $attr->removeNamespace('stash'))
  {
    $request->setMethod($s['method']);

        $params->clear();
        $params->add($s['params']);

        $this->forward($s['module'], $s['action']);
    }
}
Extra Security
An example…
Advanced symfony Techniques
Advanced symfony Techniques
# security.yml
acceptInvitation:
  is_secure: true
  extra_credentials:
    account: { lifetime: 300 }
Events to the rescue!
controller.change_action
// connect to the event
$ed->connect('controller.change_action', $cb)
// check security.yml
$action->getSecurityValue('extra_credentials')
// check current user
$u->getAttribute('extra_credentials', array())
// remove any expired credentials
$now = time();
foreach ($creds as $name => $attr)
{
  if ($now > $attr['expires_at'])
  {
    unset($creds[$name]);
  }
}
// stash credentials and referer
$u->setAttribute('challenge_credentials', ...)
$u->setAttribute('challenge_referer', ...)
// forward to challenge form
$controller->forward('security', 'challenge')
throw new sfStopException();
// add the granted credentials
$now = time();
foreach ($new as $name => $attr)
{
  $creds[$name] = array(
    'expires_at' => $now + $attr['lifetime'],
  );
}
$u->setAttribute('extra_credentials', $creds);
// send them on their way
$this->redirect($referer);
sfExtraSecurityPlugin
 Re-prompt your users for authentication.
Javascript Compression
<script src="http://domain.com/widget.js"></script>
class jsActions extends sfActions
{
  public function executeWidget(sfWebRequest $req)
  {
    $this->lightbox = $req->hasParameter('lb');
    $this->debug    = $req->hasParameter('debug');
  }
}
<?php if ($debug): ?>
console.log("embedding mootools");
<?php endif; ?>

var e = document.createElement("script");
e.src = "<?php echo public_path('js/moo.js', true) ?>";
e.async = true;
document.body.appendChild(e);

// etc...
Custom View Class
# module.yml
all:
  view_class: Javascript

        JavascriptView
class JavascriptView extends sfPHPView
{
  public function render()
  {
    return $this->compress(parent::render());
  }

    protected function compress()
    {
      // ...
    }
}
$i = tempnam(sys_get_temp_dir(), __CLASS__);
$o = tempnam(sys_get_temp_dir(), __CLASS__);

file_put_contents($i, $content);

shell_exec(vsprintf(
  'java -jar %s --type js -o %s %s',
  array_map('escapeshellarg', array($yui, $o, $i))
));

return file_get_contents($o);
Standard Caching
# cache.yml
widget:
  enabled:     true
  with_layout: true
developer.yahoo.com/yui/compressor/
A Few Apache Tricks
rm web/.htaccess
AllowOverride None
<Directory /path/to/web>
  Include /path/to/.htaccess
</Directory>
Core Assets
Missing Asset
              s #FAIL :(
AliasMatch /sf/(.*)
  /path/to/symfony/data/web/sf/$1

AliasMatch /sfDoctrinePlugin/(.*)
  /path/to/sfDoctrinePlugin/web/$1

NameVirtualHost *:80
<VirtualHost _default_:80>
  # ...
Assets Fo u nd FTW!
The Dreaded Trailing Slash…
Advanced symfony Techniques
AIL
#F
RewriteEngine On
RewriteRule ^(.*)/$ /$1 [R=301,L]
GET /about/ HTTP/1.1
Host: domain.com

HTTP/1.1 301 Moved Permanently
Location: http://domain.com/about
Embedded Forms
Book


          One book has many authors,
Authors   one author has many books.


Person
Book:
  columns:
    title:       string(255)
  relations:
    authors:     { class: Person, refClass: BookAuthor }
BookAuthor:
  columns:
    book_id:     integer
    author_id:   integer
  relations:
    book:        { local: book_id }
    author:      { class: Person, local: author_id }
Person:
  columns:
    name:        string(255)
Advanced symfony Techniques
// embed related forms
$this->embedRelation('authors');
unset($this['authors_list']);
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
// embed related forms dynamically!
$this->embedDynamicRelation('authors');
form.method_not_found

 form.filter_values
// called when a form is configured
public function embedDynamicRelation($name)
{
  $rel = $table->getRelation($name);
  $this->rels[] = $rel;

    $this->doEmbed($name, $obj->get($rel->getAlias()));
}
// called when a form is bound
public function filterValues(sfEvent $event, $values)
{
  foreach ($this->rels as $rel)
  {
    $name = $rel->getName();
    $this->doEmbed($name, $values[$name]);
  }

    $obj->addListener(new DeleteListener($form));
}
$parent = new BaseForm();
foreach ($values as $i => $value) {
  if (is_object($value)) {
    // create form with object
  } elseif ($value['id']) {
    // find previously embedded form
  } else {
    // create a new form
  }

    $parent->embedForm($i, $child);
}

$form->embedForm($rel->getName(), $parent);
// extract existing objects from embedded forms
// and compare to the current object collection
public function preSave(Doctrine_Event $event)
{
  foreach ($coll as $i => $obj)
  {
    $pos = array_search($obj, $existing, true);
    if (false === $pos) $coll->remove($i);

        if ($column['notnull']) $obj->delete();
    }
}
sfDoctrineDynamicFormRelationsPlugin
          Common sense embedded forms.
Questions?
•   Host aware routing

•   Graceful POST authentication

•   Extra security

•   Javascript compression

•   Apache tricks

•   Embedded forms
OpenSky is Hiring!
  http://engineering.shopopensky.com

 Please contact me if you're interested.
Thank you!
1 of 106

Recommended

Introducing Assetic (NYPHP) by
Introducing Assetic (NYPHP)Introducing Assetic (NYPHP)
Introducing Assetic (NYPHP)Kris Wallsmith
4K views125 slides
Doctrine MongoDB ODM (PDXPHP) by
Doctrine MongoDB ODM (PDXPHP)Doctrine MongoDB ODM (PDXPHP)
Doctrine MongoDB ODM (PDXPHP)Kris Wallsmith
2.1K views49 slides
News of the Symfony2 World by
News of the Symfony2 WorldNews of the Symfony2 World
News of the Symfony2 WorldFabien Potencier
3.5K views38 slides
Symfony 2.0 on PHP 5.3 by
Symfony 2.0 on PHP 5.3Symfony 2.0 on PHP 5.3
Symfony 2.0 on PHP 5.3Fabien Potencier
3.5K views118 slides
The Zen of Lithium by
The Zen of LithiumThe Zen of Lithium
The Zen of LithiumNate Abele
2.6K views118 slides
New Symfony Tips & Tricks (SymfonyCon Paris 2015) by
New Symfony Tips & Tricks (SymfonyCon Paris 2015)New Symfony Tips & Tricks (SymfonyCon Paris 2015)
New Symfony Tips & Tricks (SymfonyCon Paris 2015)Javier Eguiluz
23.6K views204 slides

More Related Content

What's hot

Speed up your developments with Symfony2 by
Speed up your developments with Symfony2Speed up your developments with Symfony2
Speed up your developments with Symfony2Hugo Hamon
4.5K views71 slides
Building Lithium Apps by
Building Lithium AppsBuilding Lithium Apps
Building Lithium AppsNate Abele
5.7K views57 slides
Electrify your code with PHP Generators by
Electrify your code with PHP GeneratorsElectrify your code with PHP Generators
Electrify your code with PHP GeneratorsMark Baker
3.7K views49 slides
New in php 7 by
New in php 7New in php 7
New in php 7Vic Metcalfe
1.1K views53 slides
Design Patterns avec PHP 5.3, Symfony et Pimple by
Design Patterns avec PHP 5.3, Symfony et PimpleDesign Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et PimpleHugo Hamon
6.1K views68 slides
Nubilus Perl by
Nubilus PerlNubilus Perl
Nubilus PerlFlavio Poletti
614 views51 slides

What's hot(20)

Speed up your developments with Symfony2 by Hugo Hamon
Speed up your developments with Symfony2Speed up your developments with Symfony2
Speed up your developments with Symfony2
Hugo Hamon4.5K views
Building Lithium Apps by Nate Abele
Building Lithium AppsBuilding Lithium Apps
Building Lithium Apps
Nate Abele5.7K views
Electrify your code with PHP Generators by Mark Baker
Electrify your code with PHP GeneratorsElectrify your code with PHP Generators
Electrify your code with PHP Generators
Mark Baker3.7K views
Design Patterns avec PHP 5.3, Symfony et Pimple by Hugo Hamon
Design Patterns avec PHP 5.3, Symfony et PimpleDesign Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et Pimple
Hugo Hamon6.1K views
Symfony2, creare bundle e valore per il cliente by Leonardo Proietti
Symfony2, creare bundle e valore per il clienteSymfony2, creare bundle e valore per il cliente
Symfony2, creare bundle e valore per il cliente
Leonardo Proietti1.3K views
Silex meets SOAP & REST by Hugo Hamon
Silex meets SOAP & RESTSilex meets SOAP & REST
Silex meets SOAP & REST
Hugo Hamon14.8K views
Forget about Index.php and build you applications around HTTP - PHPers Cracow by Kacper Gunia
Forget about Index.php and build you applications around HTTP - PHPers CracowForget about Index.php and build you applications around HTTP - PHPers Cracow
Forget about Index.php and build you applications around HTTP - PHPers Cracow
Kacper Gunia3.2K views
Lithium: The Framework for People Who Hate Frameworks, Tokyo Edition by Nate Abele
Lithium: The Framework for People Who Hate Frameworks, Tokyo EditionLithium: The Framework for People Who Hate Frameworks, Tokyo Edition
Lithium: The Framework for People Who Hate Frameworks, Tokyo Edition
Nate Abele1.6K views
Rich domain model with symfony 2.5 and doctrine 2.5 by Leonardo Proietti
Rich domain model with symfony 2.5 and doctrine 2.5Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5
Leonardo Proietti12K views
The Origin of Lithium by Nate Abele
The Origin of LithiumThe Origin of Lithium
The Origin of Lithium
Nate Abele8.4K views
SPL: The Missing Link in Development by jsmith92
SPL: The Missing Link in DevelopmentSPL: The Missing Link in Development
SPL: The Missing Link in Development
jsmith92733 views
Scaling Symfony2 apps with RabbitMQ - Symfony UK Meetup by Kacper Gunia
Scaling Symfony2 apps with RabbitMQ - Symfony UK MeetupScaling Symfony2 apps with RabbitMQ - Symfony UK Meetup
Scaling Symfony2 apps with RabbitMQ - Symfony UK Meetup
Kacper Gunia25.5K views

Viewers also liked

Upgrading to php 5.6 by
Upgrading to php 5.6Upgrading to php 5.6
Upgrading to php 5.6Luka Skupnjak
938 views15 slides
Trick or Tip - Symfony Edition by
Trick or Tip - Symfony EditionTrick or Tip - Symfony Edition
Trick or Tip - Symfony EditionDionyshs Tsoumas
617 views15 slides
Deployment talk dpc 13 by
Deployment talk dpc 13Deployment talk dpc 13
Deployment talk dpc 13Robbert van den Bogerd
1.4K views76 slides
Symfony2: Get your project started by
Symfony2: Get your project startedSymfony2: Get your project started
Symfony2: Get your project startedRyan Weaver
19.1K views70 slides
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later by
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years laterSymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years laterHaehnchen
1.7K views56 slides
Keeping the frontend under control with Symfony and Webpack by
Keeping the frontend under control with Symfony and WebpackKeeping the frontend under control with Symfony and Webpack
Keeping the frontend under control with Symfony and WebpackIgnacio Martín
6.4K views90 slides

Viewers also liked(10)

Symfony2: Get your project started by Ryan Weaver
Symfony2: Get your project startedSymfony2: Get your project started
Symfony2: Get your project started
Ryan Weaver19.1K views
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later by Haehnchen
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years laterSymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later
Haehnchen1.7K views
Keeping the frontend under control with Symfony and Webpack by Ignacio Martín
Keeping the frontend under control with Symfony and WebpackKeeping the frontend under control with Symfony and Webpack
Keeping the frontend under control with Symfony and Webpack
Ignacio Martín6.4K views
TechLeads meetup: Евгений Потапов, ITSumma by Badoo Development
TechLeads meetup: Евгений Потапов, ITSumma TechLeads meetup: Евгений Потапов, ITSumma
TechLeads meetup: Евгений Потапов, ITSumma
Badoo Development7.8K views
TechLeads meetup: Макс Лапшин, Erlyvideo by Badoo Development
TechLeads meetup: Макс Лапшин, ErlyvideoTechLeads meetup: Макс Лапшин, Erlyvideo
TechLeads meetup: Макс Лапшин, Erlyvideo
TechLeads meetup: Алексей Рыбак, Badoo by Badoo Development
TechLeads meetup: Алексей Рыбак, BadooTechLeads meetup: Алексей Рыбак, Badoo
TechLeads meetup: Алексей Рыбак, Badoo
Badoo Development8.5K views
TechLeads meetup: Андрей Шелёхин, Tinkoff.ru by Badoo Development
TechLeads meetup: Андрей Шелёхин, Tinkoff.ruTechLeads meetup: Андрей Шелёхин, Tinkoff.ru
TechLeads meetup: Андрей Шелёхин, Tinkoff.ru

Similar to Advanced symfony Techniques

関西PHP勉強会 php5.4つまみぐい by
関西PHP勉強会 php5.4つまみぐい関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐいHisateru Tanaka
2.6K views81 slides
Aura Project for PHP by
Aura Project for PHPAura Project for PHP
Aura Project for PHPHari K T
6K views63 slides
Nashvile Symfony Routes Presentation by
Nashvile Symfony Routes PresentationNashvile Symfony Routes Presentation
Nashvile Symfony Routes PresentationBrent Shaffer
1.2K views12 slides
Be RESTful (Symfony Camp 2008) by
Be RESTful (Symfony Camp 2008)Be RESTful (Symfony Camp 2008)
Be RESTful (Symfony Camp 2008)Fabien Potencier
1.2K views50 slides
Resource Routing in ExpressionEngine by
Resource Routing in ExpressionEngineResource Routing in ExpressionEngine
Resource Routing in ExpressionEngineMichaelRog
3K views47 slides
symfony on action - WebTech 207 by
symfony on action - WebTech 207symfony on action - WebTech 207
symfony on action - WebTech 207patter
1.9K views33 slides

Similar to Advanced symfony Techniques(20)

関西PHP勉強会 php5.4つまみぐい by Hisateru Tanaka
関西PHP勉強会 php5.4つまみぐい関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい
Hisateru Tanaka2.6K views
Aura Project for PHP by Hari K T
Aura Project for PHPAura Project for PHP
Aura Project for PHP
Hari K T6K views
Nashvile Symfony Routes Presentation by Brent Shaffer
Nashvile Symfony Routes PresentationNashvile Symfony Routes Presentation
Nashvile Symfony Routes Presentation
Brent Shaffer1.2K views
Resource Routing in ExpressionEngine by MichaelRog
Resource Routing in ExpressionEngineResource Routing in ExpressionEngine
Resource Routing in ExpressionEngine
MichaelRog3K views
symfony on action - WebTech 207 by patter
symfony on action - WebTech 207symfony on action - WebTech 207
symfony on action - WebTech 207
patter1.9K views
Keeping it Small: Getting to know the Slim Micro Framework by Jeremy Kendall
Keeping it Small: Getting to know the Slim Micro FrameworkKeeping it Small: Getting to know the Slim Micro Framework
Keeping it Small: Getting to know the Slim Micro Framework
Jeremy Kendall1.8K views
Practical PHP 5.3 by Nate Abele
Practical PHP 5.3Practical PHP 5.3
Practical PHP 5.3
Nate Abele7K views
Keeping it small: Getting to know the Slim micro framework by Jeremy Kendall
Keeping it small: Getting to know the Slim micro frameworkKeeping it small: Getting to know the Slim micro framework
Keeping it small: Getting to know the Slim micro framework
Jeremy Kendall111.2K views
Keeping It Small with Slim by Raven Tools
Keeping It Small with SlimKeeping It Small with Slim
Keeping It Small with Slim
Raven Tools593 views
What mom never told you about bundle configurations - Symfony Live Paris 2012 by D
What mom never told you about bundle configurations - Symfony Live Paris 2012What mom never told you about bundle configurations - Symfony Live Paris 2012
What mom never told you about bundle configurations - Symfony Live Paris 2012
D 18.1K views
第49回Php勉強会@関東 Datasource by Kaz Watanabe
第49回Php勉強会@関東 Datasource第49回Php勉強会@関東 Datasource
第49回Php勉強会@関東 Datasource
Kaz Watanabe1.4K views
What's new in the Drupal 7 API? by Alexandru Badiu
What's new in the Drupal 7 API?What's new in the Drupal 7 API?
What's new in the Drupal 7 API?
Alexandru Badiu1.5K views
Symfony components in the wild, PHPNW12 by Jakub Zalas
Symfony components in the wild, PHPNW12Symfony components in the wild, PHPNW12
Symfony components in the wild, PHPNW12
Jakub Zalas2.4K views
PHP 5.3 Overview by jsmith92
PHP 5.3 OverviewPHP 5.3 Overview
PHP 5.3 Overview
jsmith92492 views
Perforce Object and Record Model by Perforce
Perforce Object and Record Model  Perforce Object and Record Model
Perforce Object and Record Model
Perforce256 views
What's New In Laravel 5 by Darren Craig
What's New In Laravel 5What's New In Laravel 5
What's New In Laravel 5
Darren Craig2.2K views
Apostrophe (improved Paris edition) by tompunk
Apostrophe (improved Paris edition)Apostrophe (improved Paris edition)
Apostrophe (improved Paris edition)
tompunk3.3K views
Apostrophe by tompunk
ApostropheApostrophe
Apostrophe
tompunk5.4K views

More from Kris Wallsmith

Matters of State by
Matters of StateMatters of State
Matters of StateKris Wallsmith
16.4K views87 slides
The View From Inside by
The View From InsideThe View From Inside
The View From InsideKris Wallsmith
2.5K views22 slides
How kris-writes-symfony-apps-london by
How kris-writes-symfony-apps-londonHow kris-writes-symfony-apps-london
How kris-writes-symfony-apps-londonKris Wallsmith
3.7K views75 slides
Drupal, meet Assetic by
Drupal, meet AsseticDrupal, meet Assetic
Drupal, meet AsseticKris Wallsmith
9.1K views114 slides
How Kris Writes Symfony Apps by
How Kris Writes Symfony AppsHow Kris Writes Symfony Apps
How Kris Writes Symfony AppsKris Wallsmith
13.5K views106 slides
Love and Loss: A Symfony Security Play by
Love and Loss: A Symfony Security PlayLove and Loss: A Symfony Security Play
Love and Loss: A Symfony Security PlayKris Wallsmith
12.6K views77 slides

More from Kris Wallsmith(14)

How kris-writes-symfony-apps-london by Kris Wallsmith
How kris-writes-symfony-apps-londonHow kris-writes-symfony-apps-london
How kris-writes-symfony-apps-london
Kris Wallsmith3.7K views
How Kris Writes Symfony Apps by Kris Wallsmith
How Kris Writes Symfony AppsHow Kris Writes Symfony Apps
How Kris Writes Symfony Apps
Kris Wallsmith13.5K views
Love and Loss: A Symfony Security Play by Kris Wallsmith
Love and Loss: A Symfony Security PlayLove and Loss: A Symfony Security Play
Love and Loss: A Symfony Security Play
Kris Wallsmith12.6K views
How Kris Writes Symfony Apps by Kris Wallsmith
How Kris Writes Symfony AppsHow Kris Writes Symfony Apps
How Kris Writes Symfony Apps
Kris Wallsmith17.1K views
Assetic (Symfony Live Paris) by Kris Wallsmith
Assetic (Symfony Live Paris)Assetic (Symfony Live Paris)
Assetic (Symfony Live Paris)
Kris Wallsmith4.9K views
Introducing Assetic: Asset Management for PHP 5.3 by Kris Wallsmith
Introducing Assetic: Asset Management for PHP 5.3Introducing Assetic: Asset Management for PHP 5.3
Introducing Assetic: Asset Management for PHP 5.3
Kris Wallsmith33.7K views
A Practical Introduction to Symfony2 by Kris Wallsmith
A Practical Introduction to Symfony2A Practical Introduction to Symfony2
A Practical Introduction to Symfony2
Kris Wallsmith4.4K views

Recently uploaded

Cencora Executive Symposium by
Cencora Executive SymposiumCencora Executive Symposium
Cencora Executive Symposiummarketingcommunicati21
159 views14 slides
The Power of Heat Decarbonisation Plans in the Built Environment by
The Power of Heat Decarbonisation Plans in the Built EnvironmentThe Power of Heat Decarbonisation Plans in the Built Environment
The Power of Heat Decarbonisation Plans in the Built EnvironmentIES VE
79 views20 slides
CloudStack and GitOps at Enterprise Scale - Alex Dometrius, Rene Glover - AT&T by
CloudStack and GitOps at Enterprise Scale - Alex Dometrius, Rene Glover - AT&TCloudStack and GitOps at Enterprise Scale - Alex Dometrius, Rene Glover - AT&T
CloudStack and GitOps at Enterprise Scale - Alex Dometrius, Rene Glover - AT&TShapeBlue
152 views34 slides
Hypervisor Agnostic DRS in CloudStack - Brief overview & demo - Vishesh Jinda... by
Hypervisor Agnostic DRS in CloudStack - Brief overview & demo - Vishesh Jinda...Hypervisor Agnostic DRS in CloudStack - Brief overview & demo - Vishesh Jinda...
Hypervisor Agnostic DRS in CloudStack - Brief overview & demo - Vishesh Jinda...ShapeBlue
161 views13 slides
Initiating and Advancing Your Strategic GIS Governance Strategy by
Initiating and Advancing Your Strategic GIS Governance StrategyInitiating and Advancing Your Strategic GIS Governance Strategy
Initiating and Advancing Your Strategic GIS Governance StrategySafe Software
176 views68 slides
Why and How CloudStack at weSystems - Stephan Bienek - weSystems by
Why and How CloudStack at weSystems - Stephan Bienek - weSystemsWhy and How CloudStack at weSystems - Stephan Bienek - weSystems
Why and How CloudStack at weSystems - Stephan Bienek - weSystemsShapeBlue
238 views13 slides

Recently uploaded(20)

The Power of Heat Decarbonisation Plans in the Built Environment by IES VE
The Power of Heat Decarbonisation Plans in the Built EnvironmentThe Power of Heat Decarbonisation Plans in the Built Environment
The Power of Heat Decarbonisation Plans in the Built Environment
IES VE79 views
CloudStack and GitOps at Enterprise Scale - Alex Dometrius, Rene Glover - AT&T by ShapeBlue
CloudStack and GitOps at Enterprise Scale - Alex Dometrius, Rene Glover - AT&TCloudStack and GitOps at Enterprise Scale - Alex Dometrius, Rene Glover - AT&T
CloudStack and GitOps at Enterprise Scale - Alex Dometrius, Rene Glover - AT&T
ShapeBlue152 views
Hypervisor Agnostic DRS in CloudStack - Brief overview & demo - Vishesh Jinda... by ShapeBlue
Hypervisor Agnostic DRS in CloudStack - Brief overview & demo - Vishesh Jinda...Hypervisor Agnostic DRS in CloudStack - Brief overview & demo - Vishesh Jinda...
Hypervisor Agnostic DRS in CloudStack - Brief overview & demo - Vishesh Jinda...
ShapeBlue161 views
Initiating and Advancing Your Strategic GIS Governance Strategy by Safe Software
Initiating and Advancing Your Strategic GIS Governance StrategyInitiating and Advancing Your Strategic GIS Governance Strategy
Initiating and Advancing Your Strategic GIS Governance Strategy
Safe Software176 views
Why and How CloudStack at weSystems - Stephan Bienek - weSystems by ShapeBlue
Why and How CloudStack at weSystems - Stephan Bienek - weSystemsWhy and How CloudStack at weSystems - Stephan Bienek - weSystems
Why and How CloudStack at weSystems - Stephan Bienek - weSystems
ShapeBlue238 views
State of the Union - Rohit Yadav - Apache CloudStack by ShapeBlue
State of the Union - Rohit Yadav - Apache CloudStackState of the Union - Rohit Yadav - Apache CloudStack
State of the Union - Rohit Yadav - Apache CloudStack
ShapeBlue297 views
Live Demo Showcase: Unveiling Dell PowerFlex’s IaaS Capabilities with Apache ... by ShapeBlue
Live Demo Showcase: Unveiling Dell PowerFlex’s IaaS Capabilities with Apache ...Live Demo Showcase: Unveiling Dell PowerFlex’s IaaS Capabilities with Apache ...
Live Demo Showcase: Unveiling Dell PowerFlex’s IaaS Capabilities with Apache ...
ShapeBlue126 views
DRBD Deep Dive - Philipp Reisner - LINBIT by ShapeBlue
DRBD Deep Dive - Philipp Reisner - LINBITDRBD Deep Dive - Philipp Reisner - LINBIT
DRBD Deep Dive - Philipp Reisner - LINBIT
ShapeBlue180 views
What’s New in CloudStack 4.19 - Abhishek Kumar - ShapeBlue by ShapeBlue
What’s New in CloudStack 4.19 - Abhishek Kumar - ShapeBlueWhat’s New in CloudStack 4.19 - Abhishek Kumar - ShapeBlue
What’s New in CloudStack 4.19 - Abhishek Kumar - ShapeBlue
ShapeBlue263 views
Backup and Disaster Recovery with CloudStack and StorPool - Workshop - Venko ... by ShapeBlue
Backup and Disaster Recovery with CloudStack and StorPool - Workshop - Venko ...Backup and Disaster Recovery with CloudStack and StorPool - Workshop - Venko ...
Backup and Disaster Recovery with CloudStack and StorPool - Workshop - Venko ...
ShapeBlue184 views
CloudStack Object Storage - An Introduction - Vladimir Petrov - ShapeBlue by ShapeBlue
CloudStack Object Storage - An Introduction - Vladimir Petrov - ShapeBlueCloudStack Object Storage - An Introduction - Vladimir Petrov - ShapeBlue
CloudStack Object Storage - An Introduction - Vladimir Petrov - ShapeBlue
ShapeBlue138 views
Developments to CloudStack’s SDN ecosystem: Integration with VMWare NSX 4 - P... by ShapeBlue
Developments to CloudStack’s SDN ecosystem: Integration with VMWare NSX 4 - P...Developments to CloudStack’s SDN ecosystem: Integration with VMWare NSX 4 - P...
Developments to CloudStack’s SDN ecosystem: Integration with VMWare NSX 4 - P...
ShapeBlue194 views
GDG Cloud Southlake 28 Brad Taylor and Shawn Augenstein Old Problems in the N... by James Anderson
GDG Cloud Southlake 28 Brad Taylor and Shawn Augenstein Old Problems in the N...GDG Cloud Southlake 28 Brad Taylor and Shawn Augenstein Old Problems in the N...
GDG Cloud Southlake 28 Brad Taylor and Shawn Augenstein Old Problems in the N...
James Anderson160 views
"Surviving highload with Node.js", Andrii Shumada by Fwdays
"Surviving highload with Node.js", Andrii Shumada "Surviving highload with Node.js", Andrii Shumada
"Surviving highload with Node.js", Andrii Shumada
Fwdays56 views
Business Analyst Series 2023 - Week 4 Session 8 by DianaGray10
Business Analyst Series 2023 -  Week 4 Session 8Business Analyst Series 2023 -  Week 4 Session 8
Business Analyst Series 2023 - Week 4 Session 8
DianaGray10123 views
Digital Personal Data Protection (DPDP) Practical Approach For CISOs by Priyanka Aash
Digital Personal Data Protection (DPDP) Practical Approach For CISOsDigital Personal Data Protection (DPDP) Practical Approach For CISOs
Digital Personal Data Protection (DPDP) Practical Approach For CISOs
Priyanka Aash158 views
Confidence in CloudStack - Aron Wagner, Nathan Gleason - Americ by ShapeBlue
Confidence in CloudStack - Aron Wagner, Nathan Gleason - AmericConfidence in CloudStack - Aron Wagner, Nathan Gleason - Americ
Confidence in CloudStack - Aron Wagner, Nathan Gleason - Americ
ShapeBlue130 views
Setting Up Your First CloudStack Environment with Beginners Challenges - MD R... by ShapeBlue
Setting Up Your First CloudStack Environment with Beginners Challenges - MD R...Setting Up Your First CloudStack Environment with Beginners Challenges - MD R...
Setting Up Your First CloudStack Environment with Beginners Challenges - MD R...
ShapeBlue173 views

Advanced symfony Techniques

  • 2. @kriswallsmith • Release Manager for symfony 1.3 & 1.4 • On Symfony and Doctrine teams • Senior Software Engineer at • 10 years experience with PHP and web development • Open source evangelist and international speaker • Hopeless plugin developer…
  • 3. DbFinderPlugin • sfPropelActAsPolymorphicBehaviorPlugin • sfControlPanelPlugin • sfSimpleBlogPlugin • sfDoctrineDynamicFormRelationsPlugin • sfSimpleCMSPlugin • sfDoctrineMasterSlavePlugin • sfSimpleForumPlugin • sfFeed2Plugin • sfSpyPlugin • sfFormYamlEnhancementsPlugin • sfSslRequirementPlugin • sfGoogleAnalyticsPlugin • sfStatsPlugin • sfGoogleWebsiteOptimizerPlugin • sfTaskExtraPlugin • sfModerationPlugin • sfWebBrowserPlugin • sfPagerNavigationPlugin
  • 4. Please see me if you want to help with or take over a plugin's maintenance. Lots to choose from!
  • 5. #phpmatsuri October 2-3, 2010 Tokyo
  • 6. #phpmatsuri • Around 90 attendees • CakePHP, Symfony, & Lithium were represented • Most folks were CakePHP users • CakePHP documentation was translated early, so… • Please help translate Symfony2 & Doctrine2 documentation!
  • 13. homepage: url: / param: { module: main, action: indexOrDash }
  • 14. homepage: url: / param: { module: main, action: indexOrDash } if (preg_match('/.../', $r->getHost(), $m))
  • 15. class sfRoute • ->matchesUrl(...) Does the supplied URL match this route? GET / HTTP/1.0 Host: foobar.domain.com
  • 16. class sfRoute Ver y slow • ->matchesUrl(...) url_for('main/dashboard?username=foobar') Does the supplied URL match this route? • ->matchesParameters(...) Do the supplied parameters match this route?
  • 17. class sfRoute • ->matchesUrl(...) Does the supplied URL match this route? • ->matchesParameters(...) url_for('@dashboard?username=foobar') Do the supplied parameters match this route? • ->generate(...) Generate a URL using this route and these parameters.
  • 18. ->matchesUrl(...) • $url The current URI • $context An array of contextual information, including the current host • Returns false or an array of parameters extracted from the URI
  • 19. ->matchesParameters(...) • $params An associative array of parameter names and values • $context An array of contextual information, including the current host • Returns true or false
  • 20. ->generate(...) • $params An associative array of parameter names and values • $context An array of contextual information, including the current host • $absolute Whether to generate an absolute URL • Returns the generated URL
  • 21. Process the host string with a second, internal route
  • 22. public function __construct(...) { list($host, $pattern) = explode('/', $pattern, 2); $hostRoute = $this->createHostRoute($host, ...); parent::__construct(...); }
  • 23. public function matchesUrl($url, $c) { // check parent::matchesUrl() first $hp = $hostRoute->matchesUrl('/'.$c['host'], $c); // include host parameters in return }
  • 24. public function matchesParameters($p, $c) { $hp = $this->extractHostParams($p); return parent::matchesParameters($p, $c) && $hostRoute->matchesParameters($hp, $c); }
  • 25. public function generate($p, $c, $abs) { $hp = $this->extractHostParams($p); // protocol, prefix... $host = $hostRoute->generate($hp, $c, false); $uri = parent::generate($p, $c, false); return $protocol.':/'.$host.$prefix.$uri; }
  • 26. homepage: url: / param: { module: main, action: indexOrDash }
  • 27. Hard co d homepage: e d F TL url: domain.com/ :( class: sfHostAwareRoute param: { module: main, action: index } dashboard: url: :username.domain.com/ class: sfHostAwareRoute param: { module: main, action: dashboard }
  • 28. homepage: url: %APP_HOST%/ class: sfHostAwareRoute param: { module: main, action: index } dashboard: url: :username.%APP_HOST%/ class: sfHostAwareRoute param: { module: main, action: dashboard }
  • 30. class sfHostAwareRoutingConfigHandler extends sfRoutingConfigHandler { protected function parse($configFiles) { return array_map( array($this, 'filterRoute'), parent::parse($configFiles) ); } // ... }
  • 31. FTW! Free protected function filterRoute($route) { list($class, $args) = $route; $args[0] = $this->replaceConstants($args[0]); return array($class, $args); }
  • 32. # config_handlers.yml config/routing.yml: class: sfHostAwareRoutingConfigHandler file: %SF_LIB_DIR%/sfHostAwareRout...
  • 33. sfHostAwareRoutingPlugin Add subdomains to your routing rules.
  • 40. W here's my blog pos t!? ! AIL F
  • 42. class GracefulSecurityFilter extends sfBasicSecurityFilter { protected function forwardToLoginAction() { // stash the interrupted request $attr->add(array( 'module' => $context->getActionName(), 'action' => $context->getModuleName(), 'method' => $request->getMethod(), 'params' => $requestParams->getAll(), ), 'stash'); parent::forwardToLoginAction(); } }
  • 43. # filters.yml security: class: GracefulSecurityFilter
  • 44. Replay the stashed request after login
  • 45. // called after authentication protected function replayStashedRequest() { if ($s = $attr->removeNamespace('stash')) { $request->setMethod($s['method']); $params->clear(); $params->add($s['params']); $this->forward($s['module'], $s['action']); } }
  • 50. # security.yml acceptInvitation: is_secure: true extra_credentials: account: { lifetime: 300 }
  • 51. Events to the rescue!
  • 53. // connect to the event $ed->connect('controller.change_action', $cb)
  • 55. // check current user $u->getAttribute('extra_credentials', array())
  • 56. // remove any expired credentials $now = time(); foreach ($creds as $name => $attr) { if ($now > $attr['expires_at']) { unset($creds[$name]); } }
  • 57. // stash credentials and referer $u->setAttribute('challenge_credentials', ...) $u->setAttribute('challenge_referer', ...)
  • 58. // forward to challenge form $controller->forward('security', 'challenge') throw new sfStopException();
  • 59. // add the granted credentials $now = time(); foreach ($new as $name => $attr) { $creds[$name] = array( 'expires_at' => $now + $attr['lifetime'], ); } $u->setAttribute('extra_credentials', $creds);
  • 60. // send them on their way $this->redirect($referer);
  • 61. sfExtraSecurityPlugin Re-prompt your users for authentication.
  • 64. class jsActions extends sfActions { public function executeWidget(sfWebRequest $req) { $this->lightbox = $req->hasParameter('lb'); $this->debug = $req->hasParameter('debug'); } }
  • 65. <?php if ($debug): ?> console.log("embedding mootools"); <?php endif; ?> var e = document.createElement("script"); e.src = "<?php echo public_path('js/moo.js', true) ?>"; e.async = true; document.body.appendChild(e); // etc...
  • 67. # module.yml all: view_class: Javascript JavascriptView
  • 68. class JavascriptView extends sfPHPView { public function render() { return $this->compress(parent::render()); } protected function compress() { // ... } }
  • 69. $i = tempnam(sys_get_temp_dir(), __CLASS__); $o = tempnam(sys_get_temp_dir(), __CLASS__); file_put_contents($i, $content); shell_exec(vsprintf( 'java -jar %s --type js -o %s %s', array_map('escapeshellarg', array($yui, $o, $i)) )); return file_get_contents($o);
  • 71. # cache.yml widget: enabled: true with_layout: true
  • 73. A Few Apache Tricks
  • 76. <Directory /path/to/web> Include /path/to/.htaccess </Directory>
  • 78. Missing Asset s #FAIL :(
  • 79. AliasMatch /sf/(.*) /path/to/symfony/data/web/sf/$1 AliasMatch /sfDoctrinePlugin/(.*) /path/to/sfDoctrinePlugin/web/$1 NameVirtualHost *:80 <VirtualHost _default_:80> # ...
  • 80. Assets Fo u nd FTW!
  • 85. GET /about/ HTTP/1.1 Host: domain.com HTTP/1.1 301 Moved Permanently Location: http://domain.com/about
  • 87. Book One book has many authors, Authors one author has many books. Person
  • 88. Book: columns: title: string(255) relations: authors: { class: Person, refClass: BookAuthor } BookAuthor: columns: book_id: integer author_id: integer relations: book: { local: book_id } author: { class: Person, local: author_id } Person: columns: name: string(255)
  • 90. // embed related forms $this->embedRelation('authors'); unset($this['authors_list']);
  • 97. // embed related forms dynamically! $this->embedDynamicRelation('authors');
  • 99. // called when a form is configured public function embedDynamicRelation($name) { $rel = $table->getRelation($name); $this->rels[] = $rel; $this->doEmbed($name, $obj->get($rel->getAlias())); }
  • 100. // called when a form is bound public function filterValues(sfEvent $event, $values) { foreach ($this->rels as $rel) { $name = $rel->getName(); $this->doEmbed($name, $values[$name]); } $obj->addListener(new DeleteListener($form)); }
  • 101. $parent = new BaseForm(); foreach ($values as $i => $value) { if (is_object($value)) { // create form with object } elseif ($value['id']) { // find previously embedded form } else { // create a new form } $parent->embedForm($i, $child); } $form->embedForm($rel->getName(), $parent);
  • 102. // extract existing objects from embedded forms // and compare to the current object collection public function preSave(Doctrine_Event $event) { foreach ($coll as $i => $obj) { $pos = array_search($obj, $existing, true); if (false === $pos) $coll->remove($i); if ($column['notnull']) $obj->delete(); } }
  • 103. sfDoctrineDynamicFormRelationsPlugin Common sense embedded forms.
  • 104. Questions? • Host aware routing • Graceful POST authentication • Extra security • Javascript compression • Apache tricks • Embedded forms
  • 105. OpenSky is Hiring! http://engineering.shopopensky.com Please contact me if you're interested.