SlideShare une entreprise Scribd logo
1  sur  106
Télécharger pour lire hors ligne
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!

Contenu connexe

Tendances

Speed up your developments with Symfony2
Speed up your developments with Symfony2Speed up your developments with Symfony2
Speed up your developments with Symfony2Hugo Hamon
 
Building Lithium Apps
Building Lithium AppsBuilding Lithium Apps
Building Lithium AppsNate Abele
 
Electrify your code with PHP Generators
Electrify your code with PHP GeneratorsElectrify your code with PHP Generators
Electrify your code with PHP GeneratorsMark Baker
 
Design Patterns avec PHP 5.3, Symfony et Pimple
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
 
Symfony2, creare bundle e valore per il cliente
Symfony2, creare bundle e valore per il clienteSymfony2, creare bundle e valore per il cliente
Symfony2, creare bundle e valore per il clienteLeonardo Proietti
 
Silex meets SOAP & REST
Silex meets SOAP & RESTSilex meets SOAP & REST
Silex meets SOAP & RESTHugo Hamon
 
Forget about Index.php and build you applications around HTTP - PHPers Cracow
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 CracowKacper Gunia
 
Lithium: The Framework for People Who Hate Frameworks, Tokyo Edition
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 EditionNate Abele
 
Rich domain model with symfony 2.5 and doctrine 2.5
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.5Leonardo Proietti
 
The Origin of Lithium
The Origin of LithiumThe Origin of Lithium
The Origin of LithiumNate Abele
 
SPL: The Missing Link in Development
SPL: The Missing Link in DevelopmentSPL: The Missing Link in Development
SPL: The Missing Link in Developmentjsmith92
 
Scaling Symfony2 apps with RabbitMQ - Symfony UK Meetup
Scaling Symfony2 apps with RabbitMQ - Symfony UK MeetupScaling Symfony2 apps with RabbitMQ - Symfony UK Meetup
Scaling Symfony2 apps with RabbitMQ - Symfony UK MeetupKacper Gunia
 

Tendances (20)

Speed up your developments with Symfony2
Speed up your developments with Symfony2Speed up your developments with Symfony2
Speed up your developments with Symfony2
 
Building Lithium Apps
Building Lithium AppsBuilding Lithium Apps
Building Lithium Apps
 
Electrify your code with PHP Generators
Electrify your code with PHP GeneratorsElectrify your code with PHP Generators
Electrify your code with PHP Generators
 
New in php 7
New in php 7New in php 7
New in php 7
 
Design Patterns avec PHP 5.3, Symfony et Pimple
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
 
Nubilus Perl
Nubilus PerlNubilus Perl
Nubilus Perl
 
Symfony2 - OSIDays 2010
Symfony2 - OSIDays 2010Symfony2 - OSIDays 2010
Symfony2 - OSIDays 2010
 
Symfony2, creare bundle e valore per il cliente
Symfony2, creare bundle e valore per il clienteSymfony2, creare bundle e valore per il cliente
Symfony2, creare bundle e valore per il cliente
 
Silex meets SOAP & REST
Silex meets SOAP & RESTSilex meets SOAP & REST
Silex meets SOAP & REST
 
Forget about Index.php and build you applications around HTTP - PHPers Cracow
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
 
Lithium: The Framework for People Who Hate Frameworks, Tokyo Edition
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
 
Rich domain model with symfony 2.5 and doctrine 2.5
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
 
The Origin of Lithium
The Origin of LithiumThe Origin of Lithium
The Origin of Lithium
 
Lithium Best
Lithium Best Lithium Best
Lithium Best
 
Perl Web Client
Perl Web ClientPerl Web Client
Perl Web Client
 
SPL: The Missing Link in Development
SPL: The Missing Link in DevelopmentSPL: The Missing Link in Development
SPL: The Missing Link in Development
 
PhpBB meets Symfony2
PhpBB meets Symfony2PhpBB meets Symfony2
PhpBB meets Symfony2
 
Symfony tips and tricks
Symfony tips and tricksSymfony tips and tricks
Symfony tips and tricks
 
Scaling Symfony2 apps with RabbitMQ - Symfony UK Meetup
Scaling Symfony2 apps with RabbitMQ - Symfony UK MeetupScaling Symfony2 apps with RabbitMQ - Symfony UK Meetup
Scaling Symfony2 apps with RabbitMQ - Symfony UK Meetup
 
Zero to SOLID
Zero to SOLIDZero to SOLID
Zero to SOLID
 

En vedette

Upgrading to php 5.6
Upgrading to php 5.6Upgrading to php 5.6
Upgrading to php 5.6Luka Skupnjak
 
Trick or Tip - Symfony Edition
Trick or Tip - Symfony EditionTrick or Tip - Symfony Edition
Trick or Tip - Symfony EditionDionyshs Tsoumas
 
Symfony2: Get your project started
Symfony2: Get your project startedSymfony2: Get your project started
Symfony2: Get your project startedRyan Weaver
 
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later
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
 
Keeping the frontend under control with Symfony and Webpack
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
 
TechLeads meetup: Евгений Потапов, ITSumma
TechLeads meetup: Евгений Потапов, ITSumma TechLeads meetup: Евгений Потапов, ITSumma
TechLeads meetup: Евгений Потапов, ITSumma Badoo Development
 
TechLeads meetup: Макс Лапшин, Erlyvideo
TechLeads meetup: Макс Лапшин, ErlyvideoTechLeads meetup: Макс Лапшин, Erlyvideo
TechLeads meetup: Макс Лапшин, ErlyvideoBadoo Development
 
TechLeads meetup: Алексей Рыбак, Badoo
TechLeads meetup: Алексей Рыбак, BadooTechLeads meetup: Алексей Рыбак, Badoo
TechLeads meetup: Алексей Рыбак, BadooBadoo Development
 
TechLeads meetup: Андрей Шелёхин, Tinkoff.ru
TechLeads meetup: Андрей Шелёхин, Tinkoff.ruTechLeads meetup: Андрей Шелёхин, Tinkoff.ru
TechLeads meetup: Андрей Шелёхин, Tinkoff.ruBadoo Development
 

En vedette (10)

Upgrading to php 5.6
Upgrading to php 5.6Upgrading to php 5.6
Upgrading to php 5.6
 
Trick or Tip - Symfony Edition
Trick or Tip - Symfony EditionTrick or Tip - Symfony Edition
Trick or Tip - Symfony Edition
 
Deployment talk dpc 13
Deployment talk dpc 13Deployment talk dpc 13
Deployment talk dpc 13
 
Symfony2: Get your project started
Symfony2: Get your project startedSymfony2: Get your project started
Symfony2: Get your project started
 
SymfonyCon Berlin 2016 - Symfony Plugin for PhpStorm - 3 years later
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
 
Keeping the frontend under control with Symfony and Webpack
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
 
TechLeads meetup: Евгений Потапов, ITSumma
TechLeads meetup: Евгений Потапов, ITSumma TechLeads meetup: Евгений Потапов, ITSumma
TechLeads meetup: Евгений Потапов, ITSumma
 
TechLeads meetup: Макс Лапшин, Erlyvideo
TechLeads meetup: Макс Лапшин, ErlyvideoTechLeads meetup: Макс Лапшин, Erlyvideo
TechLeads meetup: Макс Лапшин, Erlyvideo
 
TechLeads meetup: Алексей Рыбак, Badoo
TechLeads meetup: Алексей Рыбак, BadooTechLeads meetup: Алексей Рыбак, Badoo
TechLeads meetup: Алексей Рыбак, Badoo
 
TechLeads meetup: Андрей Шелёхин, Tinkoff.ru
TechLeads meetup: Андрей Шелёхин, Tinkoff.ruTechLeads meetup: Андрей Шелёхин, Tinkoff.ru
TechLeads meetup: Андрей Шелёхин, Tinkoff.ru
 

Similaire à Advanced symfony Techniques

関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐいHisateru Tanaka
 
Aura Project for PHP
Aura Project for PHPAura Project for PHP
Aura Project for PHPHari K T
 
Nashvile Symfony Routes Presentation
Nashvile Symfony Routes PresentationNashvile Symfony Routes Presentation
Nashvile Symfony Routes PresentationBrent Shaffer
 
Be RESTful (Symfony Camp 2008)
Be RESTful (Symfony Camp 2008)Be RESTful (Symfony Camp 2008)
Be RESTful (Symfony Camp 2008)Fabien Potencier
 
Resource Routing in ExpressionEngine
Resource Routing in ExpressionEngineResource Routing in ExpressionEngine
Resource Routing in ExpressionEngineMichaelRog
 
symfony on action - WebTech 207
symfony on action - WebTech 207symfony on action - WebTech 207
symfony on action - WebTech 207patter
 
Keeping it Small: Getting to know the Slim Micro Framework
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 FrameworkJeremy Kendall
 
Practical PHP 5.3
Practical PHP 5.3Practical PHP 5.3
Practical PHP 5.3Nate Abele
 
Keeping it small: Getting to know the Slim micro framework
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 frameworkJeremy Kendall
 
Keeping It Small with Slim
Keeping It Small with SlimKeeping It Small with Slim
Keeping It Small with SlimRaven Tools
 
Filesystem abstractions and msg queue sergeev - symfony camp 2018
Filesystem abstractions and msg queue   sergeev - symfony camp 2018Filesystem abstractions and msg queue   sergeev - symfony camp 2018
Filesystem abstractions and msg queue sergeev - symfony camp 2018Юлия Коваленко
 
What mom never told you about bundle configurations - Symfony Live Paris 2012
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 2012D
 
第49回Php勉強会@関東 Datasource
第49回Php勉強会@関東 Datasource第49回Php勉強会@関東 Datasource
第49回Php勉強会@関東 DatasourceKaz Watanabe
 
What's new in the Drupal 7 API?
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 Badiu
 
Symfony components in the wild, PHPNW12
Symfony components in the wild, PHPNW12Symfony components in the wild, PHPNW12
Symfony components in the wild, PHPNW12Jakub Zalas
 
PHP 5.3 Overview
PHP 5.3 OverviewPHP 5.3 Overview
PHP 5.3 Overviewjsmith92
 
Perforce Object and Record Model
Perforce Object and Record Model  Perforce Object and Record Model
Perforce Object and Record Model Perforce
 
What's New In Laravel 5
What's New In Laravel 5What's New In Laravel 5
What's New In Laravel 5Darren Craig
 
Apostrophe (improved Paris edition)
Apostrophe (improved Paris edition)Apostrophe (improved Paris edition)
Apostrophe (improved Paris edition)tompunk
 
Apostrophe
ApostropheApostrophe
Apostrophetompunk
 

Similaire à Advanced symfony Techniques (20)

関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい
 
Aura Project for PHP
Aura Project for PHPAura Project for PHP
Aura Project for PHP
 
Nashvile Symfony Routes Presentation
Nashvile Symfony Routes PresentationNashvile Symfony Routes Presentation
Nashvile Symfony Routes Presentation
 
Be RESTful (Symfony Camp 2008)
Be RESTful (Symfony Camp 2008)Be RESTful (Symfony Camp 2008)
Be RESTful (Symfony Camp 2008)
 
Resource Routing in ExpressionEngine
Resource Routing in ExpressionEngineResource Routing in ExpressionEngine
Resource Routing in ExpressionEngine
 
symfony on action - WebTech 207
symfony on action - WebTech 207symfony on action - WebTech 207
symfony on action - WebTech 207
 
Keeping it Small: Getting to know the Slim Micro Framework
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
 
Practical PHP 5.3
Practical PHP 5.3Practical PHP 5.3
Practical PHP 5.3
 
Keeping it small: Getting to know the Slim micro framework
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
 
Keeping It Small with Slim
Keeping It Small with SlimKeeping It Small with Slim
Keeping It Small with Slim
 
Filesystem abstractions and msg queue sergeev - symfony camp 2018
Filesystem abstractions and msg queue   sergeev - symfony camp 2018Filesystem abstractions and msg queue   sergeev - symfony camp 2018
Filesystem abstractions and msg queue sergeev - symfony camp 2018
 
What mom never told you about bundle configurations - Symfony Live Paris 2012
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
 
第49回Php勉強会@関東 Datasource
第49回Php勉強会@関東 Datasource第49回Php勉強会@関東 Datasource
第49回Php勉強会@関東 Datasource
 
What's new in the Drupal 7 API?
What's new in the Drupal 7 API?What's new in the Drupal 7 API?
What's new in the Drupal 7 API?
 
Symfony components in the wild, PHPNW12
Symfony components in the wild, PHPNW12Symfony components in the wild, PHPNW12
Symfony components in the wild, PHPNW12
 
PHP 5.3 Overview
PHP 5.3 OverviewPHP 5.3 Overview
PHP 5.3 Overview
 
Perforce Object and Record Model
Perforce Object and Record Model  Perforce Object and Record Model
Perforce Object and Record Model
 
What's New In Laravel 5
What's New In Laravel 5What's New In Laravel 5
What's New In Laravel 5
 
Apostrophe (improved Paris edition)
Apostrophe (improved Paris edition)Apostrophe (improved Paris edition)
Apostrophe (improved Paris edition)
 
Apostrophe
ApostropheApostrophe
Apostrophe
 

Plus de Kris Wallsmith

How kris-writes-symfony-apps-london
How kris-writes-symfony-apps-londonHow kris-writes-symfony-apps-london
How kris-writes-symfony-apps-londonKris Wallsmith
 
How Kris Writes Symfony Apps
How Kris Writes Symfony AppsHow Kris Writes Symfony Apps
How Kris Writes Symfony AppsKris Wallsmith
 
Love and Loss: A Symfony Security Play
Love and Loss: A Symfony Security PlayLove and Loss: A Symfony Security Play
Love and Loss: A Symfony Security PlayKris Wallsmith
 
How Kris Writes Symfony Apps
How Kris Writes Symfony AppsHow Kris Writes Symfony Apps
How Kris Writes Symfony AppsKris Wallsmith
 
Assetic (Symfony Live Paris)
Assetic (Symfony Live Paris)Assetic (Symfony Live Paris)
Assetic (Symfony Live Paris)Kris Wallsmith
 
Introducing Assetic: Asset Management for PHP 5.3
Introducing Assetic: Asset Management for PHP 5.3Introducing Assetic: Asset Management for PHP 5.3
Introducing Assetic: Asset Management for PHP 5.3Kris Wallsmith
 
A Practical Introduction to Symfony2
A Practical Introduction to Symfony2A Practical Introduction to Symfony2
A Practical Introduction to Symfony2Kris Wallsmith
 

Plus de Kris Wallsmith (14)

Matters of State
Matters of StateMatters of State
Matters of State
 
The View From Inside
The View From InsideThe View From Inside
The View From Inside
 
How kris-writes-symfony-apps-london
How kris-writes-symfony-apps-londonHow kris-writes-symfony-apps-london
How kris-writes-symfony-apps-london
 
Drupal, meet Assetic
Drupal, meet AsseticDrupal, meet Assetic
Drupal, meet Assetic
 
How Kris Writes Symfony Apps
How Kris Writes Symfony AppsHow Kris Writes Symfony Apps
How Kris Writes Symfony Apps
 
Love and Loss: A Symfony Security Play
Love and Loss: A Symfony Security PlayLove and Loss: A Symfony Security Play
Love and Loss: A Symfony Security Play
 
How Kris Writes Symfony Apps
How Kris Writes Symfony AppsHow Kris Writes Symfony Apps
How Kris Writes Symfony Apps
 
Assetic (Zendcon)
Assetic (Zendcon)Assetic (Zendcon)
Assetic (Zendcon)
 
Assetic (OSCON)
Assetic (OSCON)Assetic (OSCON)
Assetic (OSCON)
 
Assetic (Symfony Live Paris)
Assetic (Symfony Live Paris)Assetic (Symfony Live Paris)
Assetic (Symfony Live Paris)
 
Introducing Assetic: Asset Management for PHP 5.3
Introducing Assetic: Asset Management for PHP 5.3Introducing Assetic: Asset Management for PHP 5.3
Introducing Assetic: Asset Management for PHP 5.3
 
A Practical Introduction to Symfony2
A Practical Introduction to Symfony2A Practical Introduction to Symfony2
A Practical Introduction to Symfony2
 
Symfony 2
Symfony 2Symfony 2
Symfony 2
 
Symfony in the Cloud
Symfony in the CloudSymfony in the Cloud
Symfony in the Cloud
 

Dernier

NIST Cybersecurity Framework (CSF) 2.0 Workshop
NIST Cybersecurity Framework (CSF) 2.0 WorkshopNIST Cybersecurity Framework (CSF) 2.0 Workshop
NIST Cybersecurity Framework (CSF) 2.0 WorkshopBachir Benyammi
 
UiPath Platform: The Backend Engine Powering Your Automation - Session 1
UiPath Platform: The Backend Engine Powering Your Automation - Session 1UiPath Platform: The Backend Engine Powering Your Automation - Session 1
UiPath Platform: The Backend Engine Powering Your Automation - Session 1DianaGray10
 
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...Aggregage
 
How Accurate are Carbon Emissions Projections?
How Accurate are Carbon Emissions Projections?How Accurate are Carbon Emissions Projections?
How Accurate are Carbon Emissions Projections?IES VE
 
Bird eye's view on Camunda open source ecosystem
Bird eye's view on Camunda open source ecosystemBird eye's view on Camunda open source ecosystem
Bird eye's view on Camunda open source ecosystemAsko Soukka
 
Comparing Sidecar-less Service Mesh from Cilium and Istio
Comparing Sidecar-less Service Mesh from Cilium and IstioComparing Sidecar-less Service Mesh from Cilium and Istio
Comparing Sidecar-less Service Mesh from Cilium and IstioChristian Posta
 
Building AI-Driven Apps Using Semantic Kernel.pptx
Building AI-Driven Apps Using Semantic Kernel.pptxBuilding AI-Driven Apps Using Semantic Kernel.pptx
Building AI-Driven Apps Using Semantic Kernel.pptxUdaiappa Ramachandran
 
Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)Commit University
 
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019IES VE
 
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...DianaGray10
 
Computer 10: Lesson 10 - Online Crimes and Hazards
Computer 10: Lesson 10 - Online Crimes and HazardsComputer 10: Lesson 10 - Online Crimes and Hazards
Computer 10: Lesson 10 - Online Crimes and HazardsSeth Reyes
 
AI Fame Rush Review – Virtual Influencer Creation In Just Minutes
AI Fame Rush Review – Virtual Influencer Creation In Just MinutesAI Fame Rush Review – Virtual Influencer Creation In Just Minutes
AI Fame Rush Review – Virtual Influencer Creation In Just MinutesMd Hossain Ali
 
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPA
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPAAnypoint Code Builder , Google Pub sub connector and MuleSoft RPA
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPAshyamraj55
 
Using IESVE for Loads, Sizing and Heat Pump Modeling to Achieve Decarbonization
Using IESVE for Loads, Sizing and Heat Pump Modeling to Achieve DecarbonizationUsing IESVE for Loads, Sizing and Heat Pump Modeling to Achieve Decarbonization
Using IESVE for Loads, Sizing and Heat Pump Modeling to Achieve DecarbonizationIES VE
 
Linked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond OntologiesLinked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond OntologiesDavid Newbury
 
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...UbiTrack UK
 
UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8DianaGray10
 
ADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDE
ADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDEADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDE
ADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDELiveplex
 

Dernier (20)

NIST Cybersecurity Framework (CSF) 2.0 Workshop
NIST Cybersecurity Framework (CSF) 2.0 WorkshopNIST Cybersecurity Framework (CSF) 2.0 Workshop
NIST Cybersecurity Framework (CSF) 2.0 Workshop
 
UiPath Platform: The Backend Engine Powering Your Automation - Session 1
UiPath Platform: The Backend Engine Powering Your Automation - Session 1UiPath Platform: The Backend Engine Powering Your Automation - Session 1
UiPath Platform: The Backend Engine Powering Your Automation - Session 1
 
20230104 - machine vision
20230104 - machine vision20230104 - machine vision
20230104 - machine vision
 
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...
 
How Accurate are Carbon Emissions Projections?
How Accurate are Carbon Emissions Projections?How Accurate are Carbon Emissions Projections?
How Accurate are Carbon Emissions Projections?
 
Bird eye's view on Camunda open source ecosystem
Bird eye's view on Camunda open source ecosystemBird eye's view on Camunda open source ecosystem
Bird eye's view on Camunda open source ecosystem
 
Comparing Sidecar-less Service Mesh from Cilium and Istio
Comparing Sidecar-less Service Mesh from Cilium and IstioComparing Sidecar-less Service Mesh from Cilium and Istio
Comparing Sidecar-less Service Mesh from Cilium and Istio
 
Building AI-Driven Apps Using Semantic Kernel.pptx
Building AI-Driven Apps Using Semantic Kernel.pptxBuilding AI-Driven Apps Using Semantic Kernel.pptx
Building AI-Driven Apps Using Semantic Kernel.pptx
 
Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)
 
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
 
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
 
Computer 10: Lesson 10 - Online Crimes and Hazards
Computer 10: Lesson 10 - Online Crimes and HazardsComputer 10: Lesson 10 - Online Crimes and Hazards
Computer 10: Lesson 10 - Online Crimes and Hazards
 
AI Fame Rush Review – Virtual Influencer Creation In Just Minutes
AI Fame Rush Review – Virtual Influencer Creation In Just MinutesAI Fame Rush Review – Virtual Influencer Creation In Just Minutes
AI Fame Rush Review – Virtual Influencer Creation In Just Minutes
 
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPA
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPAAnypoint Code Builder , Google Pub sub connector and MuleSoft RPA
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPA
 
Using IESVE for Loads, Sizing and Heat Pump Modeling to Achieve Decarbonization
Using IESVE for Loads, Sizing and Heat Pump Modeling to Achieve DecarbonizationUsing IESVE for Loads, Sizing and Heat Pump Modeling to Achieve Decarbonization
Using IESVE for Loads, Sizing and Heat Pump Modeling to Achieve Decarbonization
 
20150722 - AGV
20150722 - AGV20150722 - AGV
20150722 - AGV
 
Linked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond OntologiesLinked Data in Production: Moving Beyond Ontologies
Linked Data in Production: Moving Beyond Ontologies
 
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
 
UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8
 
ADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDE
ADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDEADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDE
ADOPTING WEB 3 FOR YOUR BUSINESS: A STEP-BY-STEP GUIDE
 

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.