Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Silex - Symfony goes micro
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
Igor Wiedler
October 21, 2011
Programming
14
11k
Silex - Symfony goes micro
Talk on the Silex microframework as given at symfonyday 2011.
Igor Wiedler
October 21, 2011
Tweet
Share
More Decks by Igor Wiedler
See All by Igor Wiedler
Redis Bedtime Stories
igorw
1
320
Wide Event Analytics (LISA19)
igorw
4
930
a day in the life of a request
igorw
0
150
production: an owner's manual
igorw
0
170
The Power of 2
igorw
0
310
LISP 1.5 Programmer's Manual: A Dramatic Reading
igorw
0
450
The Moral Character of Software
igorw
1
290
interdisciplinary computing (domcode)
igorw
0
300
miniKanren (clojure berlin)
igorw
1
310
Other Decks in Programming
See All in Programming
360° Signals in Angular: Signal Forms with SignalStore & Resources @ngLondon 01/2026
manfredsteyer
PRO
0
130
Rust 製のコードエディタ “Zed” を使ってみた
nearme_tech
PRO
0
180
Fragmented Architectures
denyspoltorak
0
160
Raku Raku Notion 20260128
hareyakayuruyaka
0
310
コマンドとリード間の連携に対する脅威分析フレームワーク
pandayumi
1
460
dchart: charts from deck markup
ajstarks
3
990
FOSDEM 2026: STUNMESH-go: Building P2P WireGuard Mesh Without Self-Hosted Infrastructure
tjjh89017
0
170
Package Management Learnings from Homebrew
mikemcquaid
0
230
20260127_試行錯誤の結晶を1冊に。著者が解説 先輩データサイエンティストからの指南書 / author's_commentary_ds_instructions_guide
nash_efp
1
980
Automatic Grammar Agreementと Markdown Extended Attributes について
kishikawakatsumi
0
200
MUSUBIXとは
nahisaho
0
130
そのAIレビュー、レビューしてますか? / Are you reviewing those AI reviews?
rkaga
6
4.6k
Featured
See All Featured
How to optimise 3,500 product descriptions for ecommerce in one day using ChatGPT
katarinadahlin
PRO
0
3.4k
Facilitating Awesome Meetings
lara
57
6.8k
RailsConf 2023
tenderlove
30
1.3k
Darren the Foodie - Storyboard
khoart
PRO
2
2.4k
From π to Pie charts
rasagy
0
120
AI: The stuff that nobody shows you
jnunemaker
PRO
2
260
Beyond borders and beyond the search box: How to win the global "messy middle" with AI-driven SEO
davidcarrasco
1
53
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
128
55k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
17k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
47
7.9k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
234
17k
Rebuilding a faster, lazier Slack
samanthasiow
85
9.4k
Transcript
None
• phpBB • Symfony2 • Silex igorw
None
Silex Symfony goes micro μ
Silex is not Symfony
Microframework
None
What? • Bare bones • Routes mapped to controllers •
The ‘C’ of ‘MVC’ • REST • Single file app
Why?
Sometimes a full-stack framework is too much for a simple
task.
simple
What makes silex special?
• concise • extensible • testable
• concise • extensible • testable
• concise • extensible • testable
• concise • extensible • testable
• concise • extensible • testable
Http Kernel Interface
Response handle(Request $request)
client
request client
reponse client request
clean
PSR-0
None
Silex is not Symfony
Silex is a user interface for Symfony
require_once __DIR__.'/silex.phar'; $app = new Silex\Application(); $app->get('/', function() { return
"Hello world!"; });
Phar require_once __DIR__.'/silex.phar'; $app = new Silex\Application(); $app->get('/', function() {
return "Hello world!"; });
Application require_once __DIR__.'/silex.phar'; $app = new Silex\Application(); $app->get('/', function() {
return "Hello world!"; });
require_once __DIR__.'/silex.phar'; $app = new Silex\Application(); $app->get('/', function() { return
"Hello world!"; }); Controller
$app->run();
None
<IfModule mod_rewrite.c> RewriteEngine On RewriteBase /some/path RewriteCond %{REQUEST_FILENAME} !-f RewriteCond
%{REQUEST_FILENAME} !-d RewriteRule ^(.*)$ index.php [QSA,L] </IfModule>
server { location / { if (-f $request_filename) { break;
} rewrite ^(.*) /index.php last; } location ~ index\.php$ { fastcgi_pass /var/run/php5-fpm.sock; fastcgi_index index.php; include fastcgi_params; } }
Wait a minute!
Lambdas λ
$(function () { $("a").click(function (event) { alert("Thanks for visiting!"); });
});
PHP 5.3
$f = function ($a, $b) { return $a + $b;
}; $f(1, 2);
lazy $f = function () { exit; };
nested $f = function () { return function () {
return true; }; }; $g = $f(); $value = $g();
scope $outer = 'world'; $f = function () use ($outer)
{ $inner = 'hello'; return "$inner $outer"; }; => "hello world"
scope $helloWorld = function () { $outer = 'world'; $f
= function () use ($outer) { $inner = 'hello'; return "$inner $outer"; }; return $f(); }
passing $output = function ($info) { echo $info."\n"; }; $doStuff
= function ($output) { $output('doing some magic'); doMagic(); $output('did some magic'); };
factory $userFactory = function ($name) { return new User($name); };
// ... $user = $userFactory($_POST['name']);
Usage
$app->get('/', function () { return "Hello world!"; });
Dynamic Routing
$app->get('/hello/{name}', function ($name) use ($app) { return "Hello ".$app->escape($name); });
$app->get('/hello/{name}', function ($name) use ($app) { return "Hello ".$app->escape($name); });
Controllers
assert $app->get('/blog/{id}', function ($id) { ... }) ->assert('id', '\d+');
value $app->get('/{page}', function ($page) { ... }) ->value('page', 'index');
bind $app->get('/', function () { ... }) ->bind('homepage'); $app['url_generator']->generate('homepage')
bind $app->get('/blog/{id}', function ($id) { ... }) ->bind('blog_post'); $app['url_generator'] ->generate('blog_post',
array('id' => $id))
convert $app->get('/blog/{post}', function (Post $post) { ... }) ->convert('post', function
($post) use ($app) { $id = (int) $post; return $app['posts']->find($id); });
Before & After
$app->before(function () { ... }); $app->get('/', function () { ...
}); $app->after(function () { ... });
$app->before(function (Request $request) { $loggedIn = $request ->getSession() ->get('logged_in'); if
(!$loggedIn) { return new RedirectResponse('/login'); } });
$app->after(function (Request $request, Response $response) { // tweak the Response
});
$app->after(function ( Request $request, Response $response, ) use ($app) {
$response->headers->set('x-csrf-token', $app['csrf_token']); });
REST
• get • post • put • delete • head
• options • patch
$app->get('/posts/{id}', ...); $app->post('/posts', ...); $app->put('/posts/{id}', ...); $app->delete('/post/{id}', ...);
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; $app->post('/message', function (Request $request) { mail(
'
[email protected]
', 'New message', $request->get('body') ); return new Response('Email has been sent!', 201); });
Caching
Error Handling
use Symfony\Component\HttpFoundation\Response; $app->error(function (\Exception $e, $code) { return new Response('Whoops!',
$code); });
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; throw new NotFoundHttpException("Could not find what you were
looking for.");
$app->abort(404, "Could not find the thing.");
$app['debug'] = true;
Redirecting
$app->get('/', function () use ($app) { return $app->redirect('/hello'); });
Pimple
50 NCLOC
Symfony2 DIC Pimple
Symfony2 DIC Pimple Container
Symfony2 DIC Pimple Container Builder
Symfony2 DIC Pimple Container Builder Extension
Symfony2 DIC Pimple Container Builder Extension Loader
Symfony2 DIC Pimple Container Builder Extension XML/Yaml Loader
Symfony2 DIC Pimple Container Builder Extension XML/Yaml Compiler Loader
Symfony2 DIC Pimple Container Builder Extension XML/Yaml Compiler Loader Container
Symfony2 DIC Pimple Container Builder Extension XML/Yaml Compiler Loader Container
ServiceProvider ( )
$container = new Pimple();
$app = new Silex\Application();
Parameters $app['some_parameter'] = 'value'; $app['asset.host'] = 'http://cdn.mysite.com/'; $app['database.dsn'] = 'mysql:dbname=myapp';
Services $app['some_service'] = function () { return new Service(); };
$service = $app['some_service'];
Dependencies $app['some_service'] = function ($app) { return new Service( $app['some_other_service'],
$app['some_service.config'] ); };
Shared $app['some_service'] = $app->share(function () { return new Service(); });
Protected $app['lambda_parameter'] = $app->protect( function ($a, $b) { return $a
+ $b; }); // will not execute the lambda $add = $app['lambda_parameter']; // calling it now echo $add(2, 3);
Exposed Services • debug • request • autoloader • routes
• controllers • dispatcher • resolver • kernel
Service Providers
interface ServiceProviderInterface { function register(Application $app); }
Core Service Providers • doctrine • form • http cache
• monolog • session • swiftmailer • symfony bridges • translation • twig • url generator • validator
Twig
$app->register( new Silex\ServiceProvider\TwigServiceProvider(), array( 'twig.path' => __DIR__.'/views', 'twig.class_path' => __DIR__.'/vendor/twig/lib',
) );
$app->get('/', function () use ($app) { return $app['twig']->render('hello.twig'); });
3rd Party • doctrine orm • pomm (postgres) • predis
• mongo • KyotoTycoon • memcache • rest • markdown • gravatar • buzz • config • solr • profiler • ...
Functional Testing
• src • app.php • web • index.php • tests
• bootstrap.php • YourTest.php
src/app.php require_once __DIR__.'/../vendor/silex.phar'; ... return $app;
web/index.php $app = require_once __DIR__.'/../src/app.php'; $app->run();
tests/bootstrap.php require_once __DIR__.'/../vendor/silex.phar';
use Silex\WebTestCase; class YourTest extends WebTestCase { public function createApp()
{ return require __DIR__.'/../src/app.php'; } // tests... } tests/YourTest.php
public function testAbout() { $client = $this->createClient(); $client->request('GET', '/about'); $response
= $client->getResponse(); $this->assertTrue($response->isOk()); $this->assertContains('trashbin', $response->getContent()); $this->assertContains('github', $response->getContent()); $this->assertContains('igorw', $response->getContent()); }
phpunit.xml.dist <?xml version="1.0" encoding="UTF-8"?> <phpunit backupGlobals="false" backupStaticAttributes="false" colors="true" convertErrorsToExceptions="true" convertNoticesToExceptions="true"
convertWarningsToExceptions="true" processIsolation="false" stopOnFailure="false" syntaxCheck="false" bootstrap="tests/bootstrap.php" > <testsuites> <testsuite name="YourApp Test Suite"> <directory>./tests/</directory> </testsuite> </testsuites> </phpunit>
$ phpunit
None
None
• smallish sites • well-defined scope • prototyping • restful
apis When to use
and many more...
The future
The future • Cookbooks
The future • Cookbooks • Best practices
The future • Cookbooks • Best practices • Symfony2 integration
The future • Cookbooks • Best practices • Symfony2 integration
• FOSUserBundle
The future • Cookbooks • Best practices • Symfony2 integration
• FOSUserBundle • Composer
on github fabpot/Silex fabpot/Pimple
silex.sensiolabs.org
Ω
Questions? joind.in/3699 @igorwesome speakerdeck.com /u/igorw