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 (phpday)
Search
Igor Wiedler
May 29, 2012
Programming
11
1.4k
Silex (phpday)
Igor Wiedler
May 29, 2012
Tweet
Share
More Decks by Igor Wiedler
See All by Igor Wiedler
Redis Bedtime Stories
igorw
1
280
Wide Event Analytics (LISA19)
igorw
4
910
a day in the life of a request
igorw
0
120
production: an owner's manual
igorw
0
150
The Power of 2
igorw
0
270
LISP 1.5 Programmer's Manual: A Dramatic Reading
igorw
0
400
The Moral Character of Software
igorw
1
260
interdisciplinary computing (domcode)
igorw
0
270
miniKanren (clojure berlin)
igorw
1
270
Other Decks in Programming
See All in Programming
Webからモバイルへ Vue.js × Capacitor 活用事例
naokihaba
0
470
Haskell でアルゴリズムを抽象化する / 関数型言語で競技プログラミング
naoya
16
3.6k
GoのWebAssembly活用パターン紹介
syumai
3
9.4k
The Evolution of Enterprise Java with Jakarta EE 11 and Beyond
ivargrimstad
1
520
データベースコネクションプール(DBCP)の変遷と理解
fujikawa8
1
230
KotlinConf 2025 現地で感じたServer-Side Kotlin
n_takehata
1
180
eBPFを用いたAIネットワーク監視システム論文の実装 / eBPF Japan Meetup #4
yuukit
3
730
インターフェース設計のコツとツボ
togishima
2
690
XSLTで作るBrainfuck処理系
makki_d
0
180
Development of an App for Intuitive AI Learning - Blockly Summit 2025
teba_eleven
0
110
Datadog RUM 本番導入までの道
shinter61
1
210
Cursor Meetup Tokyo ゲノミクスとCursor: 進化と制約のあいだ
koido
2
950
Featured
See All Featured
A Tale of Four Properties
chriscoyier
159
23k
Mobile First: as difficult as doing things right
swwweet
223
9.6k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
46
9.6k
Reflections from 52 weeks, 52 projects
jeffersonlam
349
20k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
280
13k
Fantastic passwords and where to find them - at NoRuKo
philnash
51
3.3k
A better future with KSS
kneath
239
17k
What's in a price? How to price your products and services
michaelherold
245
12k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
16
910
Measuring & Analyzing Core Web Vitals
bluesmoon
7
470
Automating Front-end Workflow
addyosmani
1370
200k
We Have a Design System, Now What?
morganepeng
52
7.6k
Transcript
None
• phpBB • Symfony2 • Silex • Composer igorw @igorwesome
None
$s=stream_socket_server('tcp://127.0.0.1:81'); while($c=stream_socket_accept($s)) fwrite($c,"HTTP/1.1 200 OK\r\nContent-Length: 2\r\n\r\nHi");
require __DIR__.'/c.php'; if (!is_callable($c = @$_GET['c'] ?: function() { echo
'Woah!'; })) throw new Exception('Error'); $c();
Silex Symfony2 μ-framework
Silex is not Symfony
Microframework
None
What? • Bare bones • Routes mapped to controllers •
The ‘C’ of ‘MVC’ • REST • Single file app (ish)
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!"; });
Phar require_once __DIR__.'/silex.phar'; $app = new Silex\Application(); $app->get('/', function() {
return "Hello world!"; }); = FUBAR
Composer require_once 'vendor/autoload.php'; $app = new Silex\Application(); $app->get('/', function() {
return "Hello world!"; });
Application require_once 'vendor/autoload.php'; $app = new Silex\Application(); $app->get('/', function() {
return "Hello world!"; });
require_once 'vendor/autoload.php'; $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 { index index.php location / { try_files $uri $uri/
/index.php; } location ~ index\.php$ { fastcgi_pass /var/run/php5-fpm.sock; fastcgi_index index.php; include fastcgi_params; } }
Wait a minute!
Lambdas λ
$(function () { $("a").on("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']);
event listener $emitter = new EventEmitter(); $emitter->on('user.create', function (User $user)
{ $msg = sprintf("User %s created.", $user->name); log($msg); });
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
});
Methods
• get • post • put • delete • head
• options
$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); });
$app->abort(404, "Could not find the thing.");
$app['debug'] = true;
Redirecting
$app->get('/', function () use ($app) { return $app->redirect('/hello'); });
Pimple
~50 NCLOC
$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
3rd Party • doctrine orm • propel • pomm (postgres)
• predis • mongo • KyotoTycoon • memcache • rest • markdown • gravatar • buzz • config • solr • profiler • ...
Redis
$app->register(new PredisServiceProvider());
$app->get('/{id}', function ($id) use ($app) { $key = 'pastes:'.$id; $paste
= $app['predis']->hgetall($key); ... });
None
• smallish sites • well-defined scope • prototyping • restful
apis When to use
and many more...
None
New feature: Streaming
$app->get('/some-video', function () use ($app) { $file = $app['app.video_filename']; $stream
= function () use ($file) { readfile($file); }; return $app->stream( $stream, 200, array('Content-Type' => 'video/mpeg') ); });
New feature: Middlewares
$mustBeLogged = function (Request $request) use ($app) { if (!$app['session']->has('userId'))
{ return $app->redirect('/user/login'); } }; $app->get('/user/my-profile', function () { ... }) ->middleware($mustBeLogged);
New feature: JSON helper
$app->get('/users/{id}', function ($id) use ($app) { $user = getUser($id); if
(!$user) { $message = 'The user was not found.'; $error = array('message' => $message); return $app->json($error, 404); } return $app->json($user); });
New feature: Finish filter
$app->finish(function () { // send e-mails // very slow query
// some slow API calls });
New feature: Composer
None
{ "minimum-stability": "dev", "require": { "silex/silex": "1.0.*@dev" } } composer.json
$ php composer.phar install
require 'vendor/autoload.php';
on github fabpot/Silex fabpot/Pimple
silex.sensiolabs.org
Ω
Questions? joind.in/6391 @igorwesome speakerdeck.com /u/igorw