Symfony Components Ipc 2009
Symfony Components Ipc 2009
Fabien Potencier
Serial entrepreneur and developer by passion
Founder of Sensio (in 1998)
A services and consulting company
specialized in Web technologies
and Internet marketing (France and USA)
70 people
Open-Source specialists
Big corporate customers
Consulting, training, development, web design, and more
Sponsor of a lot of Open-Source projects
like symfony and Doctrine
Fabien Potencier
Creator and lead developer of symfony
and creator and lead developer of some more OSS:
symfony components
Swift Mailer : Powerful component based mailing library for PHP
Twig : Fexible, fast, and secure template language for PHP
Pirum : Simple PEAR Channel Server Manager
Sismo : PHP continuous integration server
Lime : Easy to use unit testing library for PHP
Twitto : A web framework in a tweet
Twittee : A Dependency Injection Container in a tweet
Pimple : A small PHP 5.3 dependency injection container
Fabien Potencier
Read my technical blog: http://fabien.potencier.org/
Follow me on Twitter: @fabpot
Fork my code on Github: http://github.com/fabpot/
symfony
Full-stack framework (MVC architecture)
symfony provides the infrastructure/tools needed for 95% of the web
projects
Open-Source (MIT License) since 2005
Based on
11 years of Sensio experience building websites for its customers
Existing Open-Source projects
But wait,
symfony is a monolithic
framework, right?
A bit of history
symfony 1.0 (January 2007) started as a glue between existing
Open-Source libraries
A bit of history
symfony 1.1 (June 2008) was a big refactoring of the code base
Decoupled the main component: like Forms, Routing, Cache, YAML, ORMs,
sfRequest
sfYAML
sfRouting
sfDatabase
sfLogger
sfForm
sfValidator
sfI18N
sfEventDispatcher
sfWidget
sfUser
sfStorage
sfResponse
sfCache
sfOutputEscaper
sfCoreAutoload
platform
Symfony Components
Symfony Components
Symfony Components
Symfony Components
Symfony Components
Extracted from symfony 1
Event Dispatcher
YAML
Output Escaper
Symfony\Components\Templating
Symfony Templating
use Symfony\Components\Templating\Engine;
use Symfony\Components\Templating\Loader\FilesystemLoader;
$loader = new FilesystemLoader(
'/path/to/templates/%name%.php'
);
$t = new Engine($loader);
echo $t->render('index', array('name' => 'Fabien'));
Template Loaders
No assumption about where and how templates are to be found
Filesystem
Database
Memory,
CacheLoader
Template Renderers
No assumption about the format of the templates
Template names are prexed with the renderer name:
index == php:index
user:index
$t = new Engine($loader, array(
'user' => new ProjectTemplateRenderer(),
'php' => new PhpRenderer(),
));
Template Embedding
Template Inheritance
<?php $this->extend('layout') ?>
Hello <?php echo $name ?>
<html>
<head>
</head>
<body>
<?php $this->output('content') ?>
</body>
</html>
Template Slots
<html>
<head>
<title><?php $this->output('title') ?></title>
</head>
<body>
<?php $this->output('content') ?>
</body>
</html>
<?php $this->set('title', 'Hello World! ') ?>
<?php $this->start('title') ?>
Hello World!
<?php $this->stop() ?>
Templating
A CMS example
http://fabien.potencier.org/talk/33/php-barcelona-symfony-2-0-on-PHP-5-3?position=76
Symfony Components
Dependency Injection
Symfony\Components\DependencyInjection
class Message
{
public function __construct()
{
$this->output = new Output();
}
}
class Message
{
public function __construct(OutputInterface $output)
{
$this->output = $output;
}
}
A DI container facilitates
objects description and object relationships,
congures and instantiates objects
$message = $container->message;
Get the conguration for the message service
The Message constructor must be given an output service
Get the output object from the container
Create a Message object by passing the constructor arguments
$message = $container->message;
is roughly equivalent to
$output = new FancyOutput();
$message = new Message($output, array('with_newline' => true));!
PHP
<container xmlns="http://symfony-project.org/2.0/container">
<services>
<service id="output" class="FancyOutput" />
XML
XML is validated
against an XSD
PHP
YAML
<container xmlns="http://symfony-project.org/2.0/container">
<parameters>
<parameter key="output.class">FancyOutput</parameter>
<parameter key="message.options" type="collection">
<parameter key="with_newline">true</parameter>
</parameter>
</parameters>
<services>
<service id="output" class="%output.class%" />
<service id="message" class="Message">
<argument type="service" id="output" />
<argument>%message.options%</argument>
</service>
</services>
</container>
$container = new Builder();
$loader = new XmlFileLoader($container);
$loader->load('services.xml');
<container xmlns="http://symfony-project.org/2.0/container">
<imports>
<import resource="config.xml" />
</imports>
<services>
<service id="output" class="%output.class%" />
<service id="message" class="Message">
<argument type="service" id="output" />
<argument>%message.options%</argument>
</service>
</services>
</container>
<container xmlns="http://symfony-project.org/2.0/container">
<parameters>
<parameter key="output.class">FancyOutput</parameter>
<parameter key="message.options" type="collection">
<parameter key="with_newline">true</parameter>
</parameter>
</parameters>
</container>
$container = new Builder();
$loader = new FileXmlFileLoader($container);
$loader->load('services.xml');
<services>
<import resource="config.yml" class="Symfony\Components\DependencyInjection
\Loader\YamlFileLoader" />
<service id="output" class="%output.class%" />
<service id="message" class="Message">
<argument type="service" id="output" />
<argument>%message.options%</argument>
</service>
</services>
parameters:
output.class: FancyOutput
message.options: { with_newline: true }
$container = new Builder();
$loader = new XmlFileLoader($container);
$loader->load('services.xml');
XmlDumper
YamlDumper
Make your container
PhpDumper
VERY fast
GraphvizDumper
use
use
use
use
use
use
use
Symfony\Components\DependencyInjection\Builder;
Symfony\Components\DependencyInjection\Reference;
Symfony\Components\DependencyInjection\Dumper\XmlDumper;
Symfony\Components\DependencyInjection\Dumper\YamlDumper;
Symfony\Components\DependencyInjection\Dumper\PhpDumper;
Symfony\Components\DependencyInjection\Loader\XmlFileLoader;
Symfony\Components\DependencyInjection\Loader\YamlFileLoader;
use Symfony\Components\DependencyInjection\Container;
use Symfony\Components\DependencyInjection\Reference;
use Symfony\Components\DependencyInjection\Parameter;
class ProjectServiceContainer extends Container
{
protected $shared = array();
protected function getOutputService()
{
if (isset($this->shared['output'])) return $this->shared['output'];
$instance = new FancyOutput();
return $this->shared['output'] = $instance;
}
protected function getMessageService()
{
if (isset($this->shared['message'])) return $this->shared['message'];
$instance = new Message($this->getService('output'), array('with_newline' => true));
return $this->shared['message'] = $instance;
}
}
use Symfony\Components\DependencyInjection\Dumper\GraphvizDumper;
$dumper = new GraphvizDumper($container);
echo $dumper->dump();
digraph sc {
ratio="compress"
node [fontsize="11" fontname="Arial" shape="record"];
edge [fontsize="9" fontname="Arial" color="grey" arrowhead="open" arrowsize="0.5"];
node_output [label="output\nFancyOutput\n", shape=record, fillcolor="#eeeeee", style="filled"];
node_message [label="message\nMessage\n", shape=record, fillcolor="#eeeeee", style="filled"];
node_service_container [label="service_container\nSymfony\\Components\\DependencyInjection\\Builder
\n", shape=record, fillcolor="#9999ff", style="filled"];
node_message -> node_output [label="" style="filled"];
}
Symfony Components
Output Escaper
Symfony\Components\OutputEscaper
Output Escaper
Provides automatic XSS protection for your templates
By wrapping template variables
Works for
strings
arrays
objects
properties
methods
__call(), __get(),
Iterators, Coutables,
use Symfony\Components\OutputEscaper\Escaper;
$title = 'Foo <br />';
echo Escaper::escape(ESC_SPECIALCHARS, $title);
use Symfony\Components\OutputEscaper\Escaper;
$article = array(
'title' => 'Foo <br />',
'author' => array(
'name' => 'Fabien <br/>',
)
);
$article = Escaper::escape(ESC_SPECIALCHARS, $article);
echo $article['title']."\n";
echo $article['author']['name']."\n";
class Article
{
protected $title;
protected $author;
public $full_title;
public property
class Author
{
protected $name;
public function __construct($name) { $this->name = $name; }
public function getName() { return $this->name; }
}
use Symfony\Components\OutputEscaper\Escaper;
$article = new Article(
'foo <br />',
new Author('Fabien <br />')
);
$article = Escaper::escape(ESC_SPECIALCHARS, $article);
echo
echo
echo
echo
echo
$article->getTitle()."\n";
$article->getAuthor()->getName()."\n";
$article->full_title."\n";
$article->title."\n";
$article->title()."\n";
Escaping Strategy
explicitly ask
for raw data
echo $article->getHtmlContent(ESC_RAW);
echo $article->getTitle(ESC_JS);
change the default
escaping strategy
symfony-live.com
symfony-live.com
Thank you!
My slides on slideshare.com/fabpot
with a bonus: How to use Symfony Components with ZF!
Sensio S.A.
92-98, boulevard Victor Hugo
92 115 Clichy Cedex
FRANCE
Tl. : +33 1 40 99 80 80
Contact
Fabien Potencier
fabien.potencier at sensio.com
http://www.sensiolabs.com/
http://www.symfony-project.org/
http://fabien.potencier.org/
S
U
N
BO
How to use Symfony Components
within a Zend Framework project?
Symfony Components
Event Dispatcher
Symfony Components
Dependency Injection
parameters:
mailer.username: foo
mailer.password: bar
mailer.class:
Zend_Mail
services:
mail.transport:
class:
Zend_Mail_Transport_Smtp
arguments: [smtp.gmail.com, { auth: login, username:
%mailer.username%, password: %mailer.password%, ssl: ssl, port: 465 }]
shared:
false
mailer:
class: %mailer.class%
calls:
- [setDefaultTransport, [@mail.transport]]
Symfony Components
Output Escaper
require_once '/path/to/sfOutputEscaperAutoloader.php';
sfOutputEscaperAutoloader::register();
class My_View extends Zend_View
{
public function __set($key, $val)
{
if ('_' === substr($key, 0, 1))
{
// throw an exception
}
$this->$key = sfOutputEscaper::escape(array($this, 'escape'), $val);
}
}
<dl>
<?php foreach ($this->entries as $entry): ?>
<dt><?php echo $this->escape($entry->email) ?></dt>
<dd><?php echo $this->escape($entry->comment) ?></dd>
<?php endforeach ?>
</dl>
<dl>
<?php foreach ($this->entries as $entry): ?>
<dt><?php echo $entry->email ?></dt>
<dd><?php echo $entry->comment ?></dd>
<?php endforeach ?>
</dl>
<?php echo $entry->getRawValue()->comment ?>
<?php echo $entry->getComment(ESC_RAW) ?>