Your SlideShare is downloading. ×
0
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Advanced symfony Techniques
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Advanced symfony Techniques

13,039

Published on

Go beyond the documentation and explore some of what's possible if you stretch symfony to its limits. We will look at a number of aspects of symfony 1.4 and Doctrine 1.2 and tease out some powerful …

Go beyond the documentation and explore some of what's possible if you stretch symfony to its limits. We will look at a number of aspects of symfony 1.4 and Doctrine 1.2 and tease out some powerful functionality you may not have expected to find, but will doubtless be able to use. Topics covered will include routing, forms, the config cache and record listeners. If you're comfortable in symfony and wondering what's next, this session is for you.

Published in: Technology
0 Comments
25 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
13,039
On Slideshare
0
From Embeds
0
Number of Embeds
14
Actions
Shares
0
Downloads
248
Comments
0
Likes
25
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Advanced symfony Techniques Kris Wallsmith
  • 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!
  • 7. CAUTION PSEUDO CODE AHEAD
  • 8. Host Aware Routing
  • 9. domain.com
  • 10. foobar.domain.com
  • 11. barfoo.domain.com
  • 12. homepage: url: / param: { module: main, action: indexOrDash }
  • 13. homepage: url: / param: { module: main, action: indexOrDash } if (preg_match('/.../', $r->getHost(), $m))
  • 14. class sfRoute • ->matchesUrl(...) Does the supplied URL match this route? GET / HTTP/1.0 Host: foobar.domain.com
  • 15. 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?
  • 16. 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.
  • 17. ->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
  • 18. ->matchesParameters(...) • $params An associative array of parameter names and values • $context An array of contextual information, including the current host • Returns true or false
  • 19. ->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
  • 20. Process the host string with a second, internal route
  • 21. public function __construct(...) { list($host, $pattern) = explode('/', $pattern, 2); $hostRoute = $this->createHostRoute($host, ...); parent::__construct(...); }
  • 22. public function matchesUrl($url, $c) { // check parent::matchesUrl() first $hp = $hostRoute->matchesUrl('/'.$c['host'], $c); // include host parameters in return }
  • 23. public function matchesParameters($p, $c) { $hp = $this->extractHostParams($p); return parent::matchesParameters($p, $c) && $hostRoute->matchesParameters($hp, $c); }
  • 24. 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; }
  • 25. homepage: url: / param: { module: main, action: indexOrDash }
  • 26. 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 }
  • 27. homepage: url: %APP_HOST%/ class: sfHostAwareRoute param: { module: main, action: index } dashboard: url: :username.%APP_HOST%/ class: sfHostAwareRoute param: { module: main, action: dashboard }
  • 28. Custom Config Handler
  • 29. class sfHostAwareRoutingConfigHandler extends sfRoutingConfigHandler { protected function parse($configFiles) { return array_map( array($this, 'filterRoute'), parent::parse($configFiles) ); } // ... }
  • 30. FTW! Free protected function filterRoute($route) { list($class, $args) = $route; $args[0] = $this->replaceConstants($args[0]); return array($class, $args); }
  • 31. # config_handlers.yml config/routing.yml: class: sfHostAwareRoutingConfigHandler file: %SF_LIB_DIR%/sfHostAwareRout...
  • 32. sfHostAwareRoutingPlugin Add subdomains to your routing rules.
  • 33. Graceful POST Authentication
  • 34. An example…
  • 35. CENSORED CENSORED
  • 36. W here's my blog pos t!? ! AIL F
  • 37. Extend the security filter
  • 38. 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(); } }
  • 39. # filters.yml security: class: GracefulSecurityFilter
  • 40. Replay the stashed request after login
  • 41. // 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']); } }
  • 42. Extra Security
  • 43. An example…
  • 44. # security.yml acceptInvitation: is_secure: true extra_credentials: account: { lifetime: 300 }
  • 45. Events to the rescue!
  • 46. controller.change_action
  • 47. // connect to the event $ed->connect('controller.change_action', $cb)
  • 48. // check security.yml $action->getSecurityValue('extra_credentials')
  • 49. // check current user $u->getAttribute('extra_credentials', array())
  • 50. // remove any expired credentials $now = time(); foreach ($creds as $name => $attr) { if ($now > $attr['expires_at']) { unset($creds[$name]); } }
  • 51. // stash credentials and referer $u->setAttribute('challenge_credentials', ...) $u->setAttribute('challenge_referer', ...)
  • 52. // forward to challenge form $controller->forward('security', 'challenge') throw new sfStopException();
  • 53. // add the granted credentials $now = time(); foreach ($new as $name => $attr) { $creds[$name] = array( 'expires_at' => $now + $attr['lifetime'], ); } $u->setAttribute('extra_credentials', $creds);
  • 54. // send them on their way $this->redirect($referer);
  • 55. sfExtraSecurityPlugin Re-prompt your users for authentication.
  • 56. Javascript Compression
  • 57. <script src="http://domain.com/widget.js"></script>
  • 58. class jsActions extends sfActions { public function executeWidget(sfWebRequest $req) { $this->lightbox = $req->hasParameter('lb'); $this->debug = $req->hasParameter('debug'); } }
  • 59. <?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...
  • 60. Custom View Class
  • 61. # module.yml all: view_class: Javascript JavascriptView
  • 62. class JavascriptView extends sfPHPView { public function render() { return $this->compress(parent::render()); } protected function compress() { // ... } }
  • 63. $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);
  • 64. Standard Caching
  • 65. # cache.yml widget: enabled: true with_layout: true
  • 66. developer.yahoo.com/yui/compressor/
  • 67. A Few Apache Tricks
  • 68. rm web/.htaccess
  • 69. AllowOverride None
  • 70. <Directory /path/to/web> Include /path/to/.htaccess </Directory>
  • 71. Core Assets
  • 72. Missing Asset s #FAIL :(
  • 73. AliasMatch /sf/(.*) /path/to/symfony/data/web/sf/$1 AliasMatch /sfDoctrinePlugin/(.*) /path/to/sfDoctrinePlugin/web/$1 NameVirtualHost *:80 <VirtualHost _default_:80> # ...
  • 74. Assets Fo u nd FTW!
  • 75. The Dreaded Trailing Slash…
  • 76. AIL #F
  • 77. RewriteEngine On RewriteRule ^(.*)/$ /$1 [R=301,L]
  • 78. GET /about/ HTTP/1.1 Host: domain.com HTTP/1.1 301 Moved Permanently Location: http://domain.com/about
  • 79. Embedded Forms
  • 80. Book One book has many authors, Authors one author has many books. Person
  • 81. 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)
  • 82. // embed related forms $this->embedRelation('authors'); unset($this['authors_list']);
  • 83. // embed related forms dynamically! $this->embedDynamicRelation('authors');
  • 84. form.method_not_found form.filter_values
  • 85. // called when a form is configured public function embedDynamicRelation($name) { $rel = $table->getRelation($name); $this->rels[] = $rel; $this->doEmbed($name, $obj->get($rel->getAlias())); }
  • 86. // 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)); }
  • 87. $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);
  • 88. // 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(); } }
  • 89. sfDoctrineDynamicFormRelationsPlugin Common sense embedded forms.
  • 90. Questions? • Host aware routing • Graceful POST authentication • Extra security • Javascript compression • Apache tricks • Embedded forms
  • 91. OpenSky is Hiring! http://engineering.shopopensky.com Please contact me if you're interested.
  • 92. Thank you!

×