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
300
Wide Event Analytics (LISA19)
igorw
4
920
a day in the life of a request
igorw
0
130
production: an owner's manual
igorw
0
160
The Power of 2
igorw
0
290
LISP 1.5 Programmer's Manual: A Dramatic Reading
igorw
0
420
The Moral Character of Software
igorw
1
270
interdisciplinary computing (domcode)
igorw
0
280
miniKanren (clojure berlin)
igorw
1
290
Other Decks in Programming
See All in Programming
開発者への寄付をアプリ内課金として実装する時の気の使いどころ
ski
0
310
ИИ-Агенты в каждый дом – Алексей Порядин, PythoNN
sobolevn
0
140
あなたの知らない「動画広告」の世界 - iOSDC Japan 2025
ukitaka
0
250
GraphQL×Railsアプリのデータベース負荷分散 - 月間3,000万人利用サービスを無停止で
koxya
1
890
気づいて!アプリからのSOS 〜App Store Connect APIで始めるパフォーマンス健康診断〜
waka12
0
240
CSC305 Lecture 04
javiergs
PRO
0
180
Build your own WebP codec in Swift
kishikawakatsumi
2
810
GitHub Actions × AWS OIDC連携の仕組みと経緯を理解する
ota1022
0
210
Advance Your Career with Open Source
ivargrimstad
0
120
AIを活用したレシート読み取り機能の開発から得られた実践知 / AI Receipt Scan Practice
rockname
2
1.4k
半自動E2Eで手っ取り早くリグレッションテストを効率化しよう
beryu
6
2.3k
TokyoR#119 bignners session2 Visualization
kotatyamtema
0
120
Featured
See All Featured
Facilitating Awesome Meetings
lara
56
6.6k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
15
1.7k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
234
17k
Measuring & Analyzing Core Web Vitals
bluesmoon
9
600
The Cult of Friendly URLs
andyhume
79
6.6k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
132
19k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
26
3.1k
Context Engineering - Making Every Token Count
addyosmani
3
130
Bootstrapping a Software Product
garrettdimon
PRO
307
110k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
30
9.7k
A Tale of Four Properties
chriscoyier
160
23k
Building Flexible Design Systems
yeseniaperezcruz
329
39k
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