2. Usage
Apache
// web/index.php
require_once __DIR__.'/../vendor/autoload.php';
= new ;
->get('/hello/{name}', function ($name) use ( ) {
return 'Hello ' . ->escape($name);
});
->run();
$app SilexApplication()
$app $app
$app
$app
Install
$ composer require silex/silex:~1.2
Web Server Configuration
<IfModule mod_rewrite.c>
Options -MultiViews
RewriteEngine On
#RewriteBase /path/to/app
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [QSA,L]
</IfModule>
If your site is not at the webroot level:
uncomment the statement and adjust the
path to point to your directory, relative from the webroot.
RewriteBase
For Apache 2.2.16+, you can use the FallbackResource
directive:
FallbackResource /index.php
server {
#site root is redirected to the app boot script
location = / {
try_files @site @site;
}
# all other locations try other files first and go to our
# front controller if none of them exists
location / {
try_files $uri $uri/ @site;
}
#return 404 for all php files as we do have a front controller
location ~ .php$ {
return 404;
}
location @site {
fastcgi_pass unix:/var/run/php-fpm/www.sock;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root/index.php;
#uncomment when running via https
#fastcgi_param HTTPS on;
}
}
nginx IIS
<?xml version="1.0"?>
<configuration>
<system.webServer>
<defaultDocument>
<files>
<clear />
<add value="index.php" />
</files>
</defaultDocument>
<rewrite>
<rules>
<rule name="Silex Front Controller"
stopProcessing="true">
<match url="^(.*)$" ignoreCase="false" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}"
matchType="IsFile" ignoreCase="false"
negate="true" />
</conditions>
<action type="Rewrite" url="index.php"
appendQueryString="true" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
server.document-root = "/path/to/app"
url.rewrite-once = (
# configure some static files
"^/assets/.+" => "$0",
"^/favicon.ico$" => "$0",
"^(/[^?]*)(?.*)?" => "/index.php$1$2"
)
Lighttpd
web.config file:
simple-vhost:
configure your vhost to forward non-existent resources
to index.php:
Allows run silex without any configuration. However, in
order to serve static files, you'll have to make sure your
front controller returns false in that case ( ):web/index.php
$filename = __DIR__.preg_replace('#(?.*)$#', '',
$_SERVER['REQUEST_URI']);
if (php_sapi_name() === 'cli-server' && is_file($filename)) {
return false;
}
= require __DIR__.'/../src/app.php';
->run();
$app
$app
The application should be running at .http://localhost:8080
$ php -S localhost:8080 -t web web/index.php
To start the server from the command-line:
PHP 5.4 built-in webserver
only for
development!
3. App Configuration
false
80
443
‘UTF-8’
‘en’
null
$app
$app
$app
$app
$app
$app
['debug']
['request.http_port']
['request.https_port']
['charset']
['locale']
['logger']
// turn on the debug mode
$app['debug'] = true;
If your application is hosted behind a reverse proxy
at address $ip, and you want Silex to trust the
X-Forwarded-For* headers, you will need to run your
application like this:
use SymfonyComponentHttpFoundationRequest;
Request::setTrustedProxies(array($ip));
->run();$app
$app['asset_path'] = 'http://assets.examples.com';
Custom Configuration ( )Parameters
{{ .asset_path }}/css/styles.cssapp
$app['base_url'] = '/';
Default Configuration
Using in a template (Twig)
Configuration Default value
Set Get
$debug = ['debug'];$app
Global Configuration
To apply a controller setting to all controllers
(a converter, a middleware, a requirement, or a default value),
configure it on :$app['controllers']
$app['controllers']
->value('id', '1')
->assert('id', 'd+')
->requireHttps()
->method('get')
->convert('id', function () {/* ... */ })
->before(function () {/* ... */ });
Global configuration does not apply to controller providers
you might mount as they have their own global configuration
applied to already registered
controllers and become the
defaults for new controllers
Symfony2 Components
HttpFoundation
HttpKernel
Routing
EventDispatcher
Symfony2 components used by Silex:
For Request and Response.
Because we need a heart.
For matching defined routes.
For hooking into the HttpKernel
App Helper Methods
$app-> ('/account );redirect '
$subRequest = Request::create('/hi', 'GET');
-> ($subRequest, HttpKernelInterface::SUB_REQUEST);$app handle
Redirect
Forward
Generate the URI using :UrlGeneratorProvider
$r = Request::create($app['url_generator']->generate('hi’), 'GET');
Return JSON data and apply correct escape
JSON
$app
$app
-> ($error, 404);
-> ($user);
json
json
Streaming response (when you cannot buffer the data being sent)
Stream
$app-> ($stream, 200, array('Content-Type' => 'image/png'));stream
To send chunks, make sure to call ob_flush and flush after
every chunk:
$stream = function () {
$fh = fopen('http://www.example.com/', 'rb');
while (!feof($fh)) {
echo fread($fh, 1024);
ob_flush();
flush();
}
fclose($fh);
};
Sending a file
$app-> ('/base/path/' . $path)
->setContentDisposition(
ResponseHeaderBag::DISPOSITION_ATTACHMENT,
'pic.jpg')
sendFile
HttpFoundation 2.2+
Create a BinaryFileResponse
$app-> ($name)escape
Escape
Escape user input, to prevent Cross-Site-Scripting attacks
Stop the request early. It actually throws an exception
$app-> (404, "Book $id does not exist.");abort
Abort
Set
$assetPath = ['asset_path'];$app
Get
EARLY_EVENT = 512;
LATE_EVENT = -512;
App Events
4. Routing
A route pattern consists of:
Pattern
-> ('/blog', function () use ($posts) {
$output = '';
foreach ($posts as $post) {
$output .= $post['title'];
$output .= '<br />';
}
return $output;
});
$app get
HTTP Methods
$app
$app
-> ('/books', function ($id) {
// ...
});
-> ('/books/{id}', function () {
// ...
});
post
get
For Symfony Components 2.2+:
explicitly enable method override
HTTP method override
(for PUT, DELETE, and PATCH)
The current App is
automatically injected
to the closure thanks
to the type hinting
Forms in most web browsers do not directly support
the use of other HTTP methods.
Use a special form field named ._method
<form action="/my/target/route/" method=" ">
<!-- ... -->
<input type="hidden" name=" " value=" " />
</form>
POST
_method PUT
use SymfonyComponentHttpFoundationRequest;
Request::enableHttpMethodParameterOverride();
->run();$app
Can be restricted
via the method
method
$app
$app
$app
-> ('/book’, function () {
// ...
});
-> ('/book', function () {
// ...
})
-> ('PATCH');
-> ('/book', function () {
// ...
})
-> ('PUT|POST');
match
match
match
method
method
The order of the routes is significant.
The first matching route will be used
(place more generic routes at the bottom)
variable part passed to the closure
$app SilexApplication $app
$app
->get('/blog/ ', function ( , ) use ($posts) {
if (!isset($posts[$id])) {
->abort(404, "Post $id does not exist.");
}
$post = $posts[$id];
return "<h1>{$post['title']}</h1>" .
“<p>{$post['body']}</p>";
});
{id} $id
patternmethod
Defines a path that points to a resource.
Can include variable parts and you are able
to set RegExp requirements for them
One of the HTTP methods:
GET, POST, PUT or DELETE.
Describes the interaction with the resource
Method
POST
GET
Dynamic Route (Route Variable)
$app
$app
-> ('/books/{id}', function ($id) {
// ...
});
-> ('/books/{id}', function ($id) {
// ...
});
put
delete
PUT
DELETE
$app-> ('/books/{id}', function ($id) {
// ...
});
patchPATCH
Matching all Methods
Default Values
This will allow matching /, in which
case the variable will have the
value
page
index
$app->get('/{page}', function ($page) {
// ...
})
-> (' ’, ' ');value page index
To define a default value for any
route variable call on the
object:
value
Controller
The form's method attribute must be set to
when using this field:
POST
5. Route Variables Converters
$app->get('/user/{id}', function ($id) {
// ...
})-> ('id', function ($id) {return (int) $id; });convert
Appling some converters before injecting route variables
into the controller:
Converting route variables to objects
$userProvider = function ($id) {
return new User($id);
};
->get('/user/{user}/edit', function (User $user) {
// ...
})-> ('user', $userProvider);
$app
convert
The converter callback also receives the as
its second argument:
Request
$callback = function ($post, Request $req) {
return new Post($req->attributes->get('slug'));
};
->get('/blog/{id}/{slug}', function (Post $post) {
// ...
})-> ('post', $callback);
$app
convert
Converter defined as a service
use DoctrineCommonPersistenceObjectManager;
use SymfonyComponentHttpKernelExceptionNotFoundHttpException;
class UserConverter
{
private $om;
public function __construct(ObjectManager $om)
{
$this->om = $om;
}
public function convert($id)
{
if (null === $user = $this->om->find('User', (int) $id)) {
throw new NotFoundHttpException(
sprintf('User %d does not exist', $id)
);
}
return $user;
}
}
The service will now be registered in the app, and
the convert method will be used as converter:
E.g.: user converter based on Doctrine ObjectManager:
$app
$app
['converter.user'] = $app->share(function () {
return new UserConverter();
});
->get('/user/{user}', function (User $user) {
// ...
})-> ('user', 'converter.user:convert');convert
Requirements
$app->get('/blog/{id}', function ($id) {
// ...
})
-> ('id', 'd+');assert
$app->get('/blog/{postId}/{commentId}', function ($postId, $commentId) {
// ...
})
-> ('postId', 'd+')
-> ('commentId', 'd+');
assert
assert
Chained requirements
$app
$app
->get('/', function () {
// ...
})
-> ('homepage');
->get('/blog/{id}', function ($id) {
// ...
})
-> ('blog_post');
bind
bind
Named Routes
It only makes sense to name routes if you use providers
that make use of the RouteCollection
$app->get('/', ' );
use SilexApplication;
use SymfonyComponentHttpFoundationRequest;
namespace Acme
{
class Foo
{
public function bar(Request $request, Application $app)
{
// ...
AcmeFoo::bar'
Controllers in Classes
For an even stronger separation between Silex and your
controllers, you can define your controllers as services
Group URLs (mount) mount() prefixes all routes with the given prefix
and merges them into the main Application
// define controllers for a blog
$blog = ['controllers_factory'];
$blog->get('/', function () {
return 'Blog home page';
});
$app
$app['controllers_factory']
ControllerCollection
is a factory that returns a new instance
of .
When mounting a route collection under /blog, it is not possible to define
a route for the /blog URL. The shortest possible URL is /blog/.
// define "global" controllers
->get('/', function () {
return 'Main home page';
});
-> ('/blog', $blog);
-> ('/forum', $forum);
// / map to the main home page
// /blog/ map to the blog home page
// /forum/ map to the forum home page
$app
$app
$app
mount
mount
// define controllers for a forum
$forum = ['controllers_factory'];
$forum->get('/', function () {
return 'Forum home page';
});
$app
version 1.2
(a:b notation)
6. Error Handlers
use SymfonyComponentHttpFoundationResponse;
-> (function (Exception $e, ) {
return new Response('Something went terribly wrong.');
});
$app error $code
use SymfonyComponentHttpFoundationResponse;
-> (function (Exception $e, ) {
switch ( ) {
case 404:
$message = 'Page not found.';
break;
default:
$message = 'Something went terribly wrong.';
}
return new Response($message);
});
$app error $code
$code
Check for specific errors (using ):$code
As Silex ensures that the status code
is set to the most appropriate one depending
on the exception, setting the status on the
response won't work.
To overwrite the status code (which should not
without a good reason), set the
header:
Response
X-Status-Code
return new Response('Error', 404 /* ignored */,
array('X-Status-Code' => 200));
To restrict an error handler to only handle some Exception
classes set a more specific type hint for the Closure argument:
$app-> (function (LogicException $e, $code) {
// this handler will only handle LogicException exceptions
// and exceptions that extends LogicException
});
error
Silex comes with a default error handler that displays a
detailed error message with the stack trace when debug
is true, and a simple error message otherwise.
-> (function (Exception $e, $code) use ( ) {
if ( ['debug']) {
return;
}
// ... logic to handle the error and return a Response
});
$app $app
$app
error
The error handlers are also called when you use abort to
abort a request early:
$app $app
$app
->get('/blog/{id}', function (SilexApplication , $id)
use ($posts) {
if (!isset($posts[$id])) {
-> (404, "Post $id does not exist.");
}
return new Response(...);
});
abort
Traits
Define shortcut methods.
PHP 5.4+
Almost all built-in service providers have some
corresponding PHP traits.
To use them, define your own class and
include the traits you want:
Application
use SilexApplication;
class MyApplication extends Application
{
use ApplicationTwigTrait;
use ApplicationSecurityTrait;
use ApplicationFormTrait;
use ApplicationUrlGeneratorTrait;
use ApplicationSwiftmailerTrait;
use ApplicationMonologTrait;
use ApplicationTranslationTrait;
}
To define your own Route class and use some traits:
use SilexRoute;
class MyRoute extends Route
{
use RouteSecurityTrait;
}
To use the newly defined route, override the
setting:$app['route_class']
$app['route_class'] = 'MyRoute';
Restricting Error Handler
Debug and Error Handler
Use a separate error handler for .
Make sure to register it before the response
error handlers, because once a response is returned,
the following handlers are ignored.
logging
Logging and Error Handler
Error handlers registered via method always
take precedence. To keep the nice error messages when
debug is on use this:
error()
To register an error handler, pass a closure to the
error method which takes an argument
and returns a response:
Exception
http://silex.sensiolabs.org/
Silex documentation, examples, and download:
7. Middlewares
Application Middlewares
$app $app-> (function (Request $req, Application ) {
// ...
});
before
Only run
for “master”
request
Run after the routing and security and before the controller.
Before
To run the middleware even if an exception is thrown
early on (on a 404 or 403 error for instance),
register it as an early event:
$app $app-> (function (Request $req, Application ) {
// ...
}, );
before
Application::EARLY_EVENT
$app-> (function (Request $req, Response $resp) {
// ...
});
after
After
Run before the Response is sent to the client.
$app-> (function (Request $req, Response $resp) {
// ...
// Warning: modifications to the Request or Response
// will be ignored
});
finish
Terminate
Event registered on the Symfony response event.
Event registered on the Symfony terminate event.
Event registered on the Symfony request event.
Run after the Response has been sent to the client
(like sending emails or logging).
Route Middlewares
Added to routes or route collections.
Only triggered when the corresponding route is matched.
You can also stack them:
$app->get('/somewhere', function () {
// ...
})
-> ($before1)
-> ($before2)
-> ($after1)
-> ($after2)
;
before
before
after
after
Fired before the route callback, but after the before
application middlewares:
Before
$before = function (Request $req, Application ) {
// ...
};
->get('/somewhere', function () {
// ...
})
-> ($before);
$app
$app
before
Fired after the route callback, but before the application
after application middlewares:
After
$after = function (Request $req,
Response $resp,
Application ) {
// ...
};
->get('/somewhere', function () {
// ...
})
-> ($after);
$app
$app
after
The middlewares are triggered in the same order they
are added.
To control the priority of the middleware
pass an additional argument to the registration methods:
$app-> (function (Request $req) {
// ...
}, );
before
32
Middlewares Priority
As a convenience, two constants allow you to register
an event as early as possible or as late as possible:
$app
$app
-> (function (Request $req) {
// ...
}, );
-> (function (Request $req) {
// ...
}, );
before
Application::EARLY_EVENT
before
Application::LATE_EVENT
If a before middleware returns a Response object,
the Request handling is short-circuited (the next
middlewares won't be run, nor the route callback),
and the Response is passed to the after middlewares
right away:
Short-circuiting the Controller
$app-> (function (Request $req) {
// redirect the user to the login screen if access
// to the Resource is protected
if (...) {
return new RedirectResponse('/login');
}
});
before
If a before middleware does not return a Response or null,
a is thrown.RuntimeException
8. Services
Silex use (extends)
Pimple for DI
Definition
closurearray
$app['some_service'] = function () {
return new Service();
};
Retrieve the service:
$service = ['some_service'];$app
Every time is called,
a new instance of the service is created.
$app['some_service']
Shared Services
Use the same instance of a service across all of your code.
Create the service on first invocation, and then return the
existing instance on any subsequent access.
$app $app['some_service'] = -> (function () {
return new Service();
});
share
Access Container from Closure
Access the service container from within a service
definition closure.
For example when fetching services the current service
depends on.
$app $app
$app
$app
['some_service'] = function ( ) {
return new Service( ['some_other_service'],
['some_service.config']);
};
also works for
shared services
some_service depends
on some_other_service
$app
$app $app $app
$app
['user.persist_path'] = '/tmp/users';
['user.persister'] = -> (function ( ) {
return new JsonUserPersister( ['user.persist_path']);
});
share
Protected Closures
The container sees closures as factories for services, so
it will always execute them when reading them.
In some cases you will however want to store a closure
as a parameter, so that you can fetch it and execute
it yourself -- with your own arguments.
This is why Pimple allows to protect closures from being
executed, by using the method:protect
$app $app
$app
['closure_parameter'] = -> (function ($a, $b) {
return $a + $b;
});
// will not execute the closure
$add = ['closure_parameter'];
// calling it now
echo $add(2, 3);
protect
protected closures
do not get access
to the container
Core Services
Current request object (instance of ).
It gives access to GET, POST parameters
and lots more! E.g.:
Only available when a request is being
served, you can only access it from within
a controller, an application before/after
middlewares, or an error handler.
that is used internally.
You can add, modify, and read routes.
that is used
internally.
that is used internally.
It is the core of the Symfony2 system
and is used quite a bit by Silex.
that is used internally.
It takes care of executing the controller
with the right arguments.
Request
$id = ['request']->get('id');
RouteCollection
SilexControllerCollection
EventDispatcher
ControllerResolver
$app
HttpKernel
Request
Response
UrlGenerator
error()
['exception_handler']->disable()
PsrLogLoggerInterface
MonologServiceProvider
SymfonyComponentHttpKernel
LogLoggerInterface
that is used internally. Is the
heart of Symfony2, it takes a
as input and returns a as output
Simplified representation of the
request that is used by the Router and
the
Default handler that is used when
you don't register one via the
method or if the handler does not return
a Response. Disable it with
.
instance.
By default, logging is disabled as the
value is set to null. To enable logging
either use the
or define your own logger service that
conforms to the PSR logger interface.
In versions of Silex before 1.1 this must
be a
.
$app
request_context
request
routes
controllers
dispatcher
resolver
are shared
$app $app['asset_path'] = -> (function () {
// logic to determine the asset path
return 'http://assets.examples.com';
});
share
Define the service:
kernel
exception_handler
logger
E.g. 2:
E.g. 3:
9. Providers
Service Providers
Allow to reuse parts of an application into another one
In order to load and use a service provider,
register it on the application:
Loading providers
Creating a provider
Providers must implement the :SilexServiceProviderInterface
interface ServiceProviderInterface
{
public function (Application );
public function (Application );
}
register
boot
$app
$app
define services on the application which
then may make use of other services and
parameters
register()
Just create a new class that implements the two methods:
configure the application, just before it
handles a request
boot()
namespace Acme;
use SilexApplication;
use SilexServiceProviderInterface;
class HelloServiceProvider implements ServiceProviderInterface
{
public function register(Application )
{
['hello'] = -> (function ($name) use ( ){
$default = ['hello.default_name'] ?
['hello.default_name'] : ‘';
$name = $name ?: $default;
return 'Hello ' . -> ($name);
});
}
public function boot(Application )
{
}
}
$app
$app $app $app
$app
$app
$app
$app
protect
escape
-> (new AcmeHelloServiceProvider(), array(
'hello.default_name' => 'Mary',
));
->get('/hello', function () use ( ) {
$name = ['request']->get('name');
return ['hello']($name);
});
$app
$app $app
$app
$app
register
Using the provider:
Controller Providers
To load and use a controller provider, "mount" its controllers
under a path:
$app-> ('/blog', new AcmeBlogControllerProvider());mount
All controllers defined by the provider will now be available
under the /blog path.
Loading providers
Creating a provider
Providers must implement the :SilexControllerProviderInterface
interface ControllerProviderInterface
{
public function (Application );
}
connect $app
namespace Acme;
use SilexApplication;
use SilexControllerProviderInterface;
class HelloControllerProvider implements ControllerProviderInterface
{
public function connect(Application )
{
// creates a new controller based on the default route
$controllers = ['controllers_factory'];
$controllers->get('/', function (Application ) {
return ->redirect('/hello');
});
return $controllers;
}
}
$app
$app
$app
$app
The connect method must return an instance of
ControllerCollection. ControllerCollection is the class
where all controller related methods are defined
(like get, post, match, ...).
Using:
$app-> ('/blog', new AcmeHelloControllerProvider());mount
$app-> (new AcmeDatabaseServiceProvider());register
$app-> (new AcmeDatabaseServiceProvider(), array(
'database.dsn' => 'mysql:host=localhost;dbname=mydb’,
'database.user' => 'root',
‘database.password' => 'secret_root_password',
));
register
It is possible to provide some parameters as a second
argument. These will be set after the provider is
registered, but before it is booted:
E.g.:
10. Doctrine Service Provider
Only Doctrine DBAL.
An ORM service
is not supplied
db.options
db
db.config
db.event_manager
Parameters
Services
$app-> (new ,
array(
'db.options' => array(
‘driver' => 'pdo_sqlite',
'path' => __DIR__.'/app.db',
),
));
register SilexProviderDoctrineServiceProvider()
Registering
$app $app
$app
->get('/blog/{id}', function ($id) use ( ) {
$sql = "SELECT * FROM posts WHERE id = ?";
$post = ['db']-> ($sql, array((int) $id));
return "<h1>{$post['title']}</h1>".
“<p>{$post['body']}</p>";
});
fetchAssoc
Usage
Using multiple databases
$app-> (new ,
array(
'dbs.options' => array (
'mysql_read' => array(
'driver' => 'pdo_mysql',
'host' => 'mysql_read.someplace.tld',
'dbname' => 'my_database',
'user' => 'my_username',
'password' => 'my_password',
'charset' => 'utf8',
),
'mysql_write' => array(
'driver' => 'pdo_mysql',
'host' => 'mysql_write.someplace.tld',
'dbname' => 'my_database',
'user' => 'my_username',
'password' => 'my_password',
'charset' => 'utf8',
),
),
));
register SilexProviderDoctrineServiceProvider()
$app
$app
['db']->fetchAll('SELECT * FROM table');
['dbs']['mysql_read']->fetchAll('SELECT * FROM table');
The first registered connection is the default, so the lines
below are equivalent:
$app $app
$app
$app
->get('/blog/{id}', function ($id) use ( ) {
$sql = "SELECT * FROM posts WHERE id = ?";
$post = ['dbs']['mysql_read']-> (
$sql,
array((int) $id)
);
$sql = "UPDATE posts SET value = ? WHERE id = ?";
['dbs']['mysql_write']-> (
$sql,
array('newValue', (int) $id)
);
return "<h1>{$post['title']}</h1>".
"<p>{$post['body']}</p>";
});
fetchAssoc
executeUpdate
Using multiple connections:
Included Providers
DoctrineServiceProvider
MonologServiceProvider
SessionServiceProvider
SerializerServiceProvider
SwiftmailerServiceProvider
TwigServiceProvider
TranslationServiceProvider
UrlGeneratorServiceProvider
ValidatorServiceProvider
HttpCacheServiceProvider
FormServiceProvider
SecurityServiceProvider
RememberMeServiceProvider
ServiceControllerServiceProvider
Providers available in the namespace
:
SilexProvider
(https://github.com/silexphp/Silex-Providers)
Array of Doctrine DBAL options.
These options are available:
The database driver to use.
Can be: pdo_mysql, pdo_sqlite,
pdo_pgsql, pdo_oci, oci8, ibm_db2,
pdo_ibm, pdo_sqlsrv
Name of the database
Host of the database.
(default: pdo_mysql)
(default: localhost)
driver
dbname
host
User of the database.
Password of the database
(default: root)
Only relevant for pdo_mysql, and
pdo_oci/oci8, specifies the charset used
when connecting to the database
Only relevant for pdo_sqlite, specifies
the path to the SQLite database
Specifies the port of the database.
Only relevant for pdo_mysql, pdo_pgsql,
and pdo_oci/oci8
user
password
charset
path
port
The database connection, instance of
Configuration object for Doctrine.
Event Manager for Doctrine
DoctrineDBALConnection
(default: empty DoctrineDBALConfiguration)
Integration with the Doctrine DBAL for easy database access
11. Monolog Service Provider
monolog.logfile
monolog.bubble
monolog.permission
monolog.level
monolog.name
Parameters
Services
Registering
monolog
monolog.listener
$app-> (new ,
array(
‘monolog.logfile' => __DIR__.'/dev.log',
));
register SilexProviderMonologServiceProvider()
->post('/user', function () use ($app) {
// ...
['monolog']-> (sprintf("User '%s' registered.",
$username));
return new Response('', 201);
});
$app
$app addInfo
Usage
It is possible to configure Monolog
(like adding or changing the handlers)
before using it by extending the monolog service:
$app $app $app
$app
['monolog'] = -> ( -> ('monolog',
function($monolog, ) {
$monolog-> (...);
return $monolog;
}));
share extend
pushHandler
Customization
Traits
log
$app-> (sprintf("User '%s' registered.", $username));log
File where logs are written to
Whether the messages that are handled
can bubble up the stack or not
File permissions default,
nothing change
Level of logging, defaults to DEBUG.
Must be one of:
(log everything),
(log everything except
DEBUG),
.
In addition to the constants,
it is also possible to supply the level
in string form, e.g.: “ ", " ",
“ ", " "
Name of the monolog
channel
Logger::DEBUG
Logger::INFO
Logger::WARNING,
Logger::ERROR
Logger::
DEBUG INFO
WARNING ERROR
- optional
*
*
*
*
*
The monolog logger instance
E.g.:
An event listener to log requests,
responses and errors
$app['monolog']-> ('Test’);addDebug
Logs a message
Session Service Provider
Parameters
session.storage.save_path
session.storage.options
Log requests and errors and allow to add logging to app
Path for the
.
An array of options that is
passed to the constructor of
the service
In case of the default
, the
most useful options are:
NativeFileSessionHandler
session.storage
NativeSessionStorage
name
id
cookie_lifetime
cookie_path
cookie_domain
cookie_secure
cookie_httponly
The cookie name.
The session id.
Cookie lifetime
Cookie path
Cookie domain
Cookie secure (HTTPS)
Whether the cookie is http only
(default: _SESS)
efault: null)(d
Whether to simulate sessions or not
(useful when writing functional tests).
session.test
All of these are optional. Default Sessions life time
is 1800 seconds (30 minutes). To override, set
the lifetime option.
*
Service for storing data persistently between requests
Services
Registering
session
session.storage
session.storage.handler
$app-> (new );register SilexProviderSessionServiceProvider()
Instance of Symfony2's Session
Service that is used for
persistence of the session data
Service that is used by the
for data accesssession.storage
Usage
['session']-> ('user', array('username' => $username));
$user = ['session']-> ('user'))
$app
$app
set
get
Custom Session Configurations
When using a custom session configuration is necessary
to disable the by setting
to null and configure the
ini setting yourself
NativeFileSessionHandler
session.storage.handler
session.save_path
$app['session.storage.handler'] = null;
(default: null)
(default: myapp)
(default:
NativeFileSessionHandler)
(default: value of
sys_get_temp_dir())
12. Swiftmailer Service Provider
Parameters
Services
Registering
Usage
swiftmailer.use_spool
swiftmailer.options
$app['swiftmailer.options'] = array(
'host' => 'host',
'port' => '25',
'username' => 'username',
'password' => 'password',
'encryption' => null,
‘auth_mode' => null
);
mailer
$app-> (
new
);
register
SilexProviderSwiftmailerServiceProvider()
$app $app
$app
$app
->post('/feedback', function () use ( ) {
$request = ['request'];
$message =
->setSubject('[YourSite] Feedback')
->setFrom(array('noreply@yoursite.com'))
->setTo(array('feedback@yoursite.com'))
->setBody($request->get('message'));
['mailer']-> ($message);
return new Response('Thank you!', 201);
});
Swift_Message::newInstance()
send
Traits
mail
$app-> (Swift_Message::newInstance()
->setSubject('[YourSite] Feedback')
->setFrom(array('noreply@yoursite.com'))
->setTo(array('feedback@yoursite.com'))
->setBody($request->get('message')));
mail
Translation Service Provider
Parameters
Services
Registering
translator.domains
locale
locale_fallbacks
translator
translator.loader
translator.message_selector
$app-> (new ,
array(
'locale_fallbacks' => array('en'),
));
register SilexProviderTranslationServiceProvider()
Service for sending email through the Swift Mailer library
A boolean to specify whether or not
to use the memory spool.
An array of options for the default
SMTP-based configuration.
The following options can be set:
host
port
username
password
encryption
auth_mode
SMTP hostname.
SMTP port.
SMTP username.
SMTP password.
SMTP encryption.
SMTP authentication
mode.
(default: 'localhost')
efault: 25)
efault: empty string)
efault: empty string)
efault: null)
efault: null)
(d
(d
(d
(d
(d
The mailer instance
$message = ;
// ...
['mailer']-> ($message);
Swift_Message::newInstance()
send$app
swiftmailer.transport
swiftmailer.transport.buffer
swiftmailer.transport.authhandler
swiftmailer.transport.eventdispatcher
Sends an email
Service for translating your app into different languages
Mapping of domains/locales/messages.
Contains the translation data for all
languages and domains
Locale for the translator. Generally set
this based on some request parameter
Fallback locales for the translator.
Used when the current locale has no
messages set
- optional*
*
*
*
(default: en)
(default: en)
(default: Swift_Transport_EsmtpTransport)
Transport used for e-mail
delivery.
used by the
transport
Authentication handler
used by the transport.
Try by default:
CRAM-MD5, login,
plaintext
Internal event dispatcher
used by Swiftmailer
StreamBuffer
(default: true)
Instance of , that is
used for translation
Instance of an implementation
of the translation
Instance of
Translator
LoaderInterface
MessageSelector
(default: ArrayLoader)
Usage
$app['translator.domains'] = array(
'messages' => array(
'en' => array(
'hello' => 'Hello %name%',
'goodbye' => 'Goodbye %name%',
),
13. Twig Service Provider
Traits
trans
transChoice
$app
$app
-> ('Hello World');
-> ('Hello World');
trans
transChoice
twig.path
twig.templates
twig.options
twig.form.templates
Services
Registering
Usage
Traits
twig
twig.loader
$app-> (new ,
array(
'twig.path' => __DIR__.'/views',
));
register SilexProviderTwigServiceProvider()
$app $app
$app
->get('/hello/{name}', function ($name) use ( ) {
return ['twig']-> ('hello.twig', array(
'name' => $name,
));
});
render
In any Twig template, the variable refers to the
object. So you can access any service
from within your view.
E.g.: to access ,
just put this in your template:
app
Application
$app['request']->getHost()
{{ .request.host }}app
A render function is also registered to help
render another controller from a template:
{{ ( .request.baseUrl ~ '/sidebar') }}
{# or if using the UrlGeneratorServiceProvider #}
{{ (url('sidebar')) }}
render
render
app
render
return -> ('index.html', ['name' => 'Fabien']);$app render
Customization
$app $app
$app $app
['twig'] = -> (
-> ('twig', function($twig, ) {
$twig-> ('pi', 3.14);
$twig-> ('levenshtein',
new Twig_Filter_Function('levenshtein'));
return $twig;
}));
share
extend
addGlobal
addFilter
You can configure the Twig environment before using it by
extending the twig service:
$app
$app
['twig.path'] = array(__DIR__.'/../templates');
['twig.options'] = array(
'cache' => __DIR__.'/../var/cache/twig'
);
The above example will result in following routes:
• /en/hello/igor will return Hello igor
• /de/hello/igor will return Hallo igor
• /fr/hello/igor will return Bonjour igor
• /it/hello/igor will return Hello igor (fallback)
'de' => array(
'hello' => 'Hallo %name%',
'goodbye' => 'Tschüss %name%',
),
'fr' => array(
'hello' => 'Bonjour %name%',
'goodbye' => 'Au revoir %name%',
),
),
'validators' => array(
'fr' => array(
'This value should be a valid number.' =>
‘Cette valeur doit être un nombre.',
),
),
);
->get('/{_locale}/{message}/{name}',
function ($message, $name) use ( ) {
return ['translator']-> (
$message,
array('%name%' => $name)
);
});
$app
$app
$app trans
Translates the given message
Translates the given choice message
by choosing a translation according
to a number
E.g.:
Parameters
Provide integration with the Twig template engine
Path to the directory containing twig
template files (it can also be an
array of paths)
Associative array of template names
to template contents. Use this if you
want to define your templates inline
Associative array of twig options
An array of templates used to render
forms (only available when the
is enabled)FormServiceProvider
- optional
*
*
*
*
Twig_Environment
twig.path twig.templates
instance. Main way
of interacting with Twig
The loader for Twig templates which uses the
and the options.
The loader can be replaced completely
Renders a view with the given parameters
and returns a object.Response
app variable
render function
*
14. Services
Service for generating URLs for named routes
Usage
$app
$app
$app
->get('/', function () {
return 'welcome to the homepage';
})
-> (' ');
->get('/navigation', function () use ($app) {
return '<a href="'.
['url_generator']-> (' ').
'">Home</a>';
});
bind
generate
home
home
When using Twig, the service can be used like this:
{{ .url_generator. (' ) }}app generate home'
if you have twig-bridge as a Composer dep,
you will have access to the path() and url() functions:
{{ ('home') }}
{{ ('home') }}
{# generates the absolute url http://example.org/ #}
path
url
Traits
path
url
$app
$app
-> ('home’);
-> ('home');
path
url
Registering
$app-> (
new
);
register
SilexProviderUrlGeneratorServiceProvider()
UrlGenerator Service Provider
url_generator An instance of , using the
that is provided through
the routes service. It has a generate method,
which takes the route name as an argument,
followed by an array of route parameters
UrlGenerator
RouteCollection
Generates a path
Generates an absolute URL
Service for validating data. It is most useful when used with
the , but can also be used standaloneFormServiceProvider
Validator Service Provider
Services
Registering
validator
validator.mapping.
class_metadata_factory
validator.validator_factory
$app-> (new );register SilexProviderValidatorServiceProvider()
Instance of
Factory for metadata loaders,
which can read validation
constraint information from
classes. Defaults to
.
This means you can define a static
method on
your data class, which takes a
ClassMetadata argument.
Then you can set constraints on
this ClassMetadata instance
Factory for .
Defaults to a standard
.
Mostly used internally by the
Validator
StaticMethodLoader--
ClassMetadataFactory
loadValidatorMetadata
ConstraintValidators
ConstraintValidatorFactory
Validator
Usage
use SymfonyComponentValidatorConstraints as ;
->get('/validate/{email}', function ($email) use ( ) {
$errors = ['validator']-> ($email,
new Email());
if (count($errors) > 0) {
return (string) $errors;
}
return 'The email is valid';
});
Assert
validateValue
Assert
$app $app
$app
use SymfonyComponentValidatorConstraints as Assert;
$author = new Author();
$author->first_name = 'Fabien';
$author->last_name = 'Potencier';
$book = new Book();
$book->title = 'My Book';
$book->author = $author;
$metadata = ['validator.mapping.class_metadata_factory']
-> ('Author');
$metadata-> ('first_name',
new AssertNotBlank());
$metadata-> ('first_name',
new AssertLength(array('min' => 10)));
$metadata-> ('last_name',
new AssertLength(array('min' => 10)));
$metadata = ['validator.mapping.class_metadata_factory']
-> ('Book');
$metadata-> ('title',
new AssertLength(array('min' => 10)));
$metadata-> ('author',
new AssertValid());
$errors = ['validator']-> ($book);
if (count($errors) > 0) {
foreach ($errors as $error) {
echo $error-> .' '.
$error-> ."n";
}
}else {
echo 'The author is valid';
}
$app
$app
$app
getMetadataFor
addPropertyConstraint
addPropertyConstraint
addPropertyConstraint
getMetadataFor
addPropertyConstraint
addPropertyConstraint
validate
getPropertyPath()
getMessage()
Validating Objects
Validating Values
Translation
$app['translator.domains'] = array(
'validators' => array(
'fr' => array(
'This value should be a valid number.' =>
'Cette valeur doit être un nombre.',
)
));
15. Usage
Traits
form.secret
Registering
$app-> (new );register FormServiceProvider()
$app $app
$app
->match('/form', function (Request $req) use ( ) {
// default data for when the form is displayed the first time
$data = array(
'name' => 'Your name',
'email' => 'Your email',
);
$form = ['form.factory']-> ('form', $data)
->add('name')
->add('email')
->add('gender', 'choice', array(
'choices' => array(1 => 'male', 2 => 'female'),
'expanded' => true,
))
->getForm();
createBuilder
form
$app-> ($data);form
HttpCache Service Provider
Parameters
Services
Registering
Usage
http_cache.cache_dir
http_cache.options
http_cache
http_cache.esi
http_cache.store
$app-> (new ,
array(
'http_cache.cache_dir' => __DIR__.'/cache/',
));
register SilexProviderHttpCacheServiceProvider()
->get('/', function() {
return new Response('Foo', 200, array(
' ' => 's-maxage=5',
));
});
$app
Cache-Control
Parameters
Service for building forms with the Symfony2 Form
component
Form Service Provider
This secret value is used for generating
and validating the CSRF token for a
specific page. It is very important to
set this value to a static randomly
generated value, to prevent hijacking
of your forms
(default:
md5(__DIR__))
Services
form.factory
form.csrf_provider
Instance of , that
is used for build a form
Instance of an
implementation of the
FormFactory
CsrfProviderInterface
(default:
DefaultCsrfProvider)
$form->handleRequest($req);
if ($form->isValid()) {
$data = $form->getData();
// do something with the data
// redirect somewhere
return ->redirect('...');
}
// display the form
return ['twig']->render('index.twig', array(
'form' => $form->
));
});
$app
$app
createView()
Creates a FormBuilder instance
Provides support for the Symfony2 Reverse Proxy
Cache directory to store the HTTP
cache data
An array of options for the
constructorHttpCache
- optional*
*
Instance of
Instance of , that implements the ESI
capabilities to and
instances
Instance of , that implements all
the logic for storing cache metadata
( and headers)
HttpCache
Esi
Request Response
Store
Request Response
If you want Silex to trust the
headers from your reverse proxy at address $ip,
you will need to whitelist it as documented in
Trusting Proxies. If you would be running Varnish in
front of your app on the same machine:
X-Forwarded-For*
Request::setTrustedProxies(array('127.0.0.1', '::1'));
->run();$app
Using Symfony2 reverse proxy natively
(with http_cache service)
Request::setTrustedProxies(array('127.0.0.1'));
[' ']->run();$app http_cache
The Symfony2 reverse proxy acts much like any other proxy
would, so whitelist it:
Disabling ESI
$app-> (new ,
array(
'http_cache.cache_dir' => __DIR__.'/cache/',
' ' => ,
));
register SilexProviderHttpCacheServiceProvider()
http_cache.esi null
16. HttpFragment Service Provider
Parameters
Services
Registering
Usage
Allows to embed fragments of HTML in a template
Symfony 2.4+
fragment.path
uri_signer.secret
fragment.renderers.
hinclude.global_template
fragment.handler
fragment.renderers
$app-> (new
);
register
SilexProviderHttpFragmentServiceProvider()
The main page content.
{{ ('/foo') }}
The main page content resumes here.
render
Using Twig for your templates:
Security Service Provider
Parameters
Services
Registering
Usage
security.hide_user_not_found
Manages authentication and authorization for apps
security
security.
authentication_manager
security.access_manager
security.session_strategy
security.user_checker
security.last_error
security.encoder_factory
security.encoder.digest
$app-> (new SilexProviderSecurityServiceProvider(),
array(
'security.firewalls' => // see below
));
register
The security features are only available after the
has been booted. So, to use it outside
of the handling of a request, call first:
Application
boot()
$app->boot();
// Current user
$token = ['security']-> ;
if (null !== $token) {
$user = $token-> ;
}
$app getToken()
getUser()
// Securing a Path with HTTP Authentication
// Find the encoder for a UserInterface instance
// Compute the encoded password for foo
// Checking User Roles
// Allowing Anonymous Users
['security.firewalls'] = array(
'admin' => array(
'pattern' => '^/admin',
'http' => true,
'users' => array(
// raw password is foo
'admin' => array('ROLE_ADMIN',
'5FZ2Z8QIkA7UTZ4BYkoC+GsReLf569mSKDsYQ8t+a8...'),
),
),
);
$encoder = ['security.encoder_factory']-> ($user);
$password = $encoder-> ('foo', $user-> ;
if ( ['security']-> ('ROLE_ADMIN')) {
// ...
}
['security.firewalls'] = array(
'unsecured' => array(
'anonymous' => true,
// ...
),
);
$app
$app
$app
$app
getEncoder
encodePassword getSalt())
isGranted
Path to use for the URL generated
for ESI and HInclude URLs
Secret to use for the URI signer
service (used for the HInclude
renderer)
Content or Twig template to use
for the default content when using
the HInclude renderer
(default:
/_fragment)
Instance of
Array of fragment renderers
(by default, the inline, ESI, and HInclude
renderers are pre-configured)
FragmentHandler
Defines whether to hide user
not found exception or not(default: true)
- optional*
*
Main entry point for the security
provider. Use it to get the current
user token
Instance of
,
responsible for authentication
Instance of
,
responsible for authorization
Define the session strategy used
for authentication (default to a
migration strategy)
Checks user flags after
authentication
Returns the last authentication
errors when given a object
Defines the encoding strategies
for user passwords (default to use
a digest algorithm for all users)
The encoder to use by default for
all users
AuthenticationProviderManager
AccessDecisionManager
Request
17. RememberMe Service Provider
Registering
Adds "Remember-Me" authentication to the
SecurityServiceProvider
$app
$app
$app
-> (new );
-> (new );
['security.firewalls'] = array(
'my-firewall' => array(
'pattern' => '^/secure$',
'form' => true,
'logout' => true,
'remember_me' => array(
'key' => 'Choose_A_Unique_Random_Key',
'always_remember_me' => true,
),
'users' => array( /* ... */ ),
),
);
register SilexProviderSecurityServiceProvider()
register SilexProviderRememberMeServiceProvider()
key
name
lifetime
path
domain
Options
Serializer Service Provider
Provides a serializer service
serializer
serializer.encoders
serializer.normalizers
Services
$app-> (new );register SilexProviderSerializerServiceProvider()
Registering
= new Application();
->register(new );
// only accept content types supported by the serializer
// via the assert method
->get("/pages/{id}.{_format}", function ($id) use ( ) {
// assume a page_repository service exists that returns Page
$app
$app
$app $app
SerializerServiceProvider()
// objects. Object returned has getters/setters exposing state
$page = ['page_repository']->find($id);$app
Usage
ServiceController Service Provider
Controllers can be created as services, providing the full
power of dependency injection and lazy loading
Registering
$app-> (
new );
register
SilexProviderServiceControllerServiceProvider()
use SilexApplication;
use DemoRepositoryPostRepository;
= new Application();
['posts.repository'] = -> (function() {
return new PostRepository;
});
->get('/posts.json', function() use ( ) {
return $app->json( ['posts.repository']->findAll());
});
$app
$app $app
$app $app
$app
share
Usage
Traits
user
encodePassword
secure
$user = -> ();
$encoded = -> ($user, 'foo');
->get('/', function () {
// do something but only for admins
})-> ('ROLE_ADMIN');
$app
$app
$app
user
encodePassword
secure
Returns the current user
Encode a given password
Secures a controller for the given roles
Secret key to generate tokens (you should
generate a random string)
Cookie name
Cookie lifetime
Cookie path
Cookie domain
(default: REMEMBERME)
(default: 31536000 ~ 1 year)
(default: /)
(default: null = request domain)
secure
httponly
always_remember_me
remember_me_parameter
(default: false)
(default: true)
(default: false)
(default: _remember_me)
Cookie is secure
Cookie is HTTP only
Enable remember me
Name of the request parameter
enabling remember_me on login.
/posts.json route will use a controller that is defined as a
service
$app $app $app
$app
$app
[' '] = -> (function() use ( ) {
return new PostController( ['posts.repository']);
});
->get('/posts.json', " ");
posts.controller share
posts.controller:indexJsonAction
Define the controller as a service:
$format = ['request']->getRequestFormat();
if (!$page instanceof Page) {
->abort("No page found for id: $id");
}
return new Response(
['serializer']-> ($page, $format), 200,
array(
"Content-Type" => ['request']->getMimeType($format)
));
})->assert("_format", "xml|json")
->assert("id", "d+");
$app
$app
$app
$app
serialize
and
and
SymfonyComponentSerializerSerializer
SymfonyComponentSerializer
EncoderJsonEncoder
SymfonyComponentSerializer
EncoderXmlEncoder
SymfonyComponentSerializer
NormalizerCustomNormalizer
SymfonyComponentSerializer
NormalizerGetSetMethodNormalizer