<?php
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;
require __DIR__ . '/../vendor/autoload.php';
/**
* Instantiate App
*
* In order for the factory to work you need to ensure you have installed
* a supported PSR-7 implementation of your choice e.g.: Slim PSR-7 and a supported
* ServerRequest creator (included with Slim PSR-7)
*/
$app = AppFactory::create();
/**
* The routing middleware should be added earlier than the ErrorMiddleware
* Otherwise exceptions thrown from it will not be handled by the middleware
*/
$app->addRoutingMiddleware();
/**
* Add Error Middleware
*
* @param bool $displayErrorDetails -> Should be set to false in production
* @param bool $logErrors -> Parameter is passed to the default ErrorHandler
* @param bool $logErrorDetails -> Display error details in error log
* @param LoggerInterface|null $logger -> Optional PSR-3 Logger
*
* Note: This middleware should be added last. It will not handle any exceptions/errors
* for middleware added after it.
*/
$errorMiddleware = $app->addErrorMiddleware(true, true, true);
// Define app routes
$app->get('/hello/{name}', function (Request $request, Response $response, $args) {
$name = $args['name'];
$response->getBody()->write("Hello, $name");
return $response;
});
// Run app
$app->run();
mcrypt
extension is required only if you use encrypted cookies.vendor/
directory.composer require slim/slim:"4.*"
AppFactory::create()
and App::run()
without having to manually create a ServerRequest
you need to install one of the following implementations:composer require slim/psr7
composer require nyholm/psr7 nyholm/psr7-server
composer require guzzlehttp/psr7 "^2"
composer require guzzlehttp/psr7 "^1"
composer require sapphirecat/slim4-http-interop-adapter
composer require laminas/laminas-diactoros​
public/index.php
<?php
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;
require __DIR__ . '/../vendor/autoload.php';
$app = AppFactory::create();
$app->get('/', function (Request $request, Response $response, $args) {
$response->getBody()->write("Hello world!");
return $response;
});
$app->run();
/public/
is public-accessible directory with index.php
file :cd public/
php -S localhost:8888
index.php
as your entry point then change appropriately.mod_rewrite
module is installed and enabled. In order to enable mod_rewrite
you can type the following command in the terminal :sudo a2enmod rewrite
sudo a2enmod actions
.htaccess
and index.php
files are in the same public-accessible directory. The .htaccess
file should contain this code:RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [QSA,L]
public/ directory
does not appear in the URL, you should add a second .htaccess
file above the public/ directory
with the following internal redirect rule:RewriteEngine on
RewriteRule ^$ public/ [L]
RewriteRule (.*) public/$1 [L]
.htaccess
files require URL rewriting..htaccess
rewrite rules can be used: To do this, the file /etc/apache2/apache2.conf
must be opened in an editor with root privileges.<Directory ...>
directive from AllowOveride
None to AllowOveride
All.<Directory /var/www/>
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
sudo service apache2 restart
Debian/Ubuntu
variants. For all other Linux distributions, please consult the documentation of your specific Linux distribution to find out how to restart Apache.public/index.php
.redirect
” the sub-directory to the front-controller create a second .htaccess
file above the public/ directory
..htaccess
file should contain this code:RewriteEngine on
RewriteRule ^$ public/ [L]
RewriteRule (.*) public/$1 [L]
setBasePath()
method.$app->setBasePath('/myapp');
.htaccess
file in your web server root directory (usually named htdocs
, public
, public_html
or www
) with the following content:<IfModule mod_rewrite.c>
RewriteEngine on
RewriteRule ^$ public/ [L]
RewriteRule (^[^/]*$) public/$1 [L]
</IfModule>
public
’ with the correct name of your domain name e.g. example.com/$1)Slim\App class
. This is the Slim application object. During instantiation, Slim registers default services for each application dependency.get(), post(), put(), delete(), patch(), head(), and options()
routing methods. These instance methods register a route with the application’s Router object. Each routing method returns the Route instance so you can immediately invoke the Route instance’s methods to add middleware or assign a name.run()
method. This method starts the following process:run()
method begins to inwardly traverse the application’s middleware stack. This is a concentric structure of middleware layers that receive (and optionally manipulate) the Environment, Request, and Response objects before (and after) the Slim application runs. The Slim application is the inner-most layer of the concentric middleware structure. Each middleware layer is invoked inwardly beginning from the outer-most layer.run()
method reaches the inner-most middleware layer, it invokes the application instance and dispatches the current HTTP request to the appropriate application route object. If a route matches the HTTP method and URI, the route’s middleware and callable are invoked. If a matching route is not found, the Not Found or Not Allowed handler is invoked.header()
method, and the HTTP response body is output to the current output buffer.GuzzleHttp\Psr7\CachingStream
or any instance returned by the GuzzleHttp\Psr7\stream_for()
function.withHeader($name, $value)
method that returns a cloned value object with the new HTTP header.<?php
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;
require __DIR__ . '/../vendor/autoload.php';
$app = AppFactory::create();
$app->get('/foo', function (Request $request, Response $response, array $args) {
$payload = json_encode(['hello' => 'world'], JSON_PRETTY_PRINT);
$response->getBody()->write($payload);
return $response->withHeader('Content-Type', 'application/json');
});
$app->run();
withProtocolVersion($version)
withHeader($name, $value)
withAddedHeader($name, $value)
withoutHeader($name)
withBody(StreamInterface $body)
withMethod($method)
withUri(UriInterface $uri, $preserveHost = false)
withCookieParams(array $cookies)
withQueryParams(array $query)
withUploadedFiles(array $uploadedFiles)
withParsedBody($data)
withAttribute($name, $value)
withoutAttribute($name)
withStatus($code, $reasonPhrase = '')
Psr\Http\Message\ServerRequestInterface
- The PSR-7 request objectPsr\Http\Server\RequestHandlerInterface
- The PSR-15 request handler objectPsr\Http\Message\ResponseInterface
. Each middleware SHOULD invoke the next middleware and pass it the Request object as argument.Request
object and a RequestHandler
object. Each middleware MUST return an instance of Psr\Http\Message\ResponseInterface
.<?php
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
use Slim\Factory\AppFactory;
use Slim\Psr7\Response;
require __DIR__ . '/../vendor/autoload.php';
$app = AppFactory::create();
/**
* Example middleware closure
*
* @param ServerRequest $request PSR-7 request
* @param RequestHandler $handler PSR-15 request handler
*
* @return Response
*/
$beforeMiddleware = function (Request $request, RequestHandler $handler) {
$response = $handler->handle($request);
$existingContent = (string) $response->getBody();
$response = new Response();
$response->getBody()->write('BEFORE' . $existingContent);
return $response;
};
$afterMiddleware = function ($request, $handler) {
$response = $handler->handle($request);
$response->getBody()->write('AFTER');
return $response;
};
$app->add($beforeMiddleware);
$app->add($afterMiddleware);
// ...
$app->run();
AppFactory
before creating an App
.<?php
use DI\Container;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;
require __DIR__ . '/../vendor/autoload.php';
// Create Container using PHP-DI
$container = new Container();
// Set container to create App with on AppFactory
AppFactory::setContainer($container);
$app = AppFactory::create();
$container->set('myService', function () {
$settings = [...];
return new MyService($settings);
});
/**
* Example GET route
*
* @param ServerRequestInterface $request PSR-7 request
* @param ResponseInterface $response PSR-7 response
* @param array $args Route parameters
*
* @return ResponseInterface
*/
$app->get('/foo', function (Request $request, Response $response, $args) {
$myService = $this->get('myService');
// ...do something with $myService...
return $response;
});
has()
method, like this:/**
* Example GET route
*
* @param ServerRequestInterface $request PSR-7 request
* @param ResponseInterface $response PSR-7 response
* @param array $args Route parameters
*
* @return ResponseInterface
*/
$app->get('/foo', function (Request $request, Response $response, $args) {
if ($this->has('myService')) {
$myService = $this->get('myService');
}
return $response;
});
AppFactory::createFromContainer()
method.<?php
use App\Factory\MyResponseFactory;
use DI\Container;
use Psr\Container\ContainerInterface;
use Psr\Http\Message\ResponseFactoryInterface;
use Slim\Factory\AppFactory;
require_once __DIR__ . '/../vendor/autoload.php';
// Create Container using PHP-DI
$container = new Container();
// Add custom response factory
$container->set(ResponseFactoryInterface::class, function (ContainerInterface $container) {
return new MyResponseFactory(...);
});
// Configure the application via container
$app = AppFactory::createFromContainer($container);
// ...
$app->run();
Slim\App
is the entry point to your Slim application and is used to register the routes that link to your callbacks or controllers.<?php
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;
require __DIR__ . '/../vendor/autoload.php';
// Instantiate app
$app = AppFactory::create();
// Add Error Handling Middleware
$app->addErrorMiddleware(true, false, false);
// Add route callbacks
$app->get('/', function (Request $request, Response $response, array $args) {
$response->getBody()->write('Hello World');
return $response;
});
// Run application
$app->run();
<?php
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;
require __DIR__ . '/../vendor/autoload.php';
$app = AppFactory::create();
$app->get('/hello', function (Request $request, Response $response) {
$response->getBody()->write('Hello World');
return $response;
});
$app->run();
<?php
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
use Slim\Factory\AppFactory;
require __DIR__ . '/../vendor/autoload.php';
$app = AppFactory::create();
$app->add(function (Request $request, RequestHandler $handler) {
return $handler->handle($request);
});
// ...define app routes...
$app->run();
getMethod()
.$method = $request->getMethod();
METHOD
parameter in a POST
request’s body. The HTTP request must use the application/x-www-form-urlencoded
content type.POST /path HTTP/1.1
Host: example.com
Content-type: application/x-www-form-urlencoded
Content-length: 22
data=value&_METHOD=PUT
X-Http-Method-Override
HTTP request header. This works with any HTTP
request content type.POST /path HTTP/1.1
Host: example.com
Content-type: application/json
Content-length: 16
X-Http-Method-Override: PUT
{"data":"value"}
http
or https
)example.com
)80
or 443
)/users/1
)sort=created&dir=asc
)getUri()
method:$uri = $request->getUri();
a=1&b=2
)getQueryParams()
.$app
->get('/course/{id}', Video::class . ':watch')
->add(PermissionMiddleware::class);
<?php
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
use Slim\Routing\RouteContext;
class PermissionMiddleware
{
public function __invoke(Request $request, RequestHandler $handler)
{
$routeContext = RouteContext::fromRequest($request);
$route = $routeContext->getRoute();
$courseId = $route->getArgument('id');
// do permission logic...
return $handler->handle($request);
}
}
$app->get('/books/{id}', function ($request, $response, array $args) {
// Show book identified by $args['id']
});
post()
method. It accepts two arguments:$app->post('/books', function ($request, $response, array $args) {
// Create new book
});
put()
method. It accepts two arguments:$app->put('/books/{id}', function ($request, $response, array $args) {
// Update book identified by $args['id']
});
delete()
method. It accepts two arguments:$app->delete('/books/{id}', function ($request, $response, array $args) {
// Delete book identified by $args['id']
});
options()
method. It accepts two arguments:$app->options('/books/{id}', function ($request, $response, array $args) {
// Return response headers
});
patch()
method. It accepts two arguments:$app->patch('/books/{id}', function ($request, $response, array $args) {
// Apply changes to book identified by $args['id']
});
any()
method. It accepts two arguments:$app->any('/books/[{id}]', function ($request, $response, array $args) {
// Apply changes to books or book identified by $args['id'] if specified.
// To check which method is used: $request->getMethod();
});
__invoke()
method instead of a Closure. You can then do the mapping somewhere else:$app->any('/user', 'MyRestfulController');
map()
method. It accepts three arguments:$app->map(['GET', 'POST'], '/books', function ($request, $response, array $args) {
// Create new book or list all books
});​
Request
The first argument is a Psr\Http\Message\ServerRequestInterface
object that represents the current HTTP request.Response
The second argument is a Psr\Http\Message\ResponseInterface
object that represents the current HTTP response.Arguments
The third argument is an associative array that contains values for the current route’s named placeholders.$app->get('/hello/{name}', function ($request, $response, array $args) {
// Use app HTTP cookie service
$this->get('cookies')->set('name', [
'value' => $args['name'],
'expires' => '7 days'
]);
})
Slim\App
also provides a group()
method. Each group’s route pattern is prepended to the routes or groups contained within it, and any placeholder arguments in the group pattern are ultimately made available to the nested routes:use Slim\Routing\RouteCollectorProxy;
// ...
$app->group('/users/{id:[0-9]+}', function (RouteCollectorProxy $group) {
$group->map(['GET', 'DELETE', 'PATCH', 'PUT'], '', function ($request, $response, array $args) {
// Find, delete, patch or replace user identified by $args['id']
// ...
return $response;
})->setName('user');
$group->get('/reset-password', function ($request, $response, array $args) {
// Route for /users/{id:[0-9]+}/reset-password
// Reset the password for user identified by $args['id']
// ...
return $response;
})->setName('user-password-reset');
});
__invoke()
method$app->get('/', '\HomeController:home');
$app->get('/', \HomeController::class . ':home');
$app->get('/', [\HomeController::class, 'home']);
/
route and telling Slim to execute the home()
method on the HomeController
class.HomeController
in the container, if it’s found it will use that instance otherwise it will call it’s constructor with the container as the first argument. Once an instance of the class is created it will then call the specified method using whatever Strategy you have defined.DispatcherInterface
, RouteCollectorInterface, RouteParserInterface
and RouteResolverInterface
which create a bridge between Slim’s components and the routing library. If you were using determineRouteBeforeAppMiddleware
, you need to add the Middleware\RoutingMiddleware
middleware to your application just before your call run()
to maintain the previous behaviour.<?php
use Slim\Factory\AppFactory;
require __DIR__ . '/../vendor/autoload.php';
$app = AppFactory::create();
// Add Routing Middleware
$app->addRoutingMiddleware();
// ...
$app->run();
<?php
use Slim\Factory\AppFactory;
require __DIR__ . '/../vendor/autoload.php';
$app = AppFactory::create();
/**
* The routing middleware should be added earlier than the ErrorMiddleware
* Otherwise exceptions thrown from it will not be handled by the middleware
*/
$app->addRoutingMiddleware();
/**
* Add Error Middleware
*
* @param bool $displayErrorDetails -> Should be set to false in production
* @param bool $logErrors -> Parameter is passed to the default ErrorHandler
* @param bool $logErrorDetails -> Display error details in error log
* @param LoggerInterface|null $logger -> Optional PSR-3 Logger
*
* Note: This middleware should be added last. It will not handle any exceptions/errors
* for middleware added after it.
*/
$errorMiddleware = $app->addErrorMiddleware(true, true, true);
// ...
$app->run();
ErrorRenderers
. The core ErrorHandler
extends the AbstractErrorHandler
class which has been completely refactored. By default it will call the appropriate ErrorRenderer
for the supported content types. The core ErrorHandler
defines renderers for the following content types :application/json
application/xml
and text/xml
text/html
text/plain
\Slim\Interfaces\ErrorRendererInterface
.<?php
use Slim\Interfaces\ErrorRendererInterface;
use Throwable;
class MyCustomErrorRenderer implements ErrorRendererInterface
{
public function __invoke(Throwable $exception, bool $displayErrorDetails): string
{
return 'My awesome format';
}
}
text/html
content types.<?php
use MyApp\Handlers\MyErrorHandler;
use Slim\Factory\AppFactory;
require __DIR__ . '/../vendor/autoload.php';
$app = AppFactory::create();
// Add Routing Middleware
$app->addRoutingMiddleware();
// Add Error Middleware
$errorMiddleware = $app->addErrorMiddleware(true, true, true);
// Get the default error handler and register my custom error renderer.
$errorHandler = $errorMiddleware->getDefaultErrorHandler();
$errorHandler->registerErrorRenderer('text/html', MyCustomErrorRenderer::class);
// ...
$app->run();
X-Http-Method-Override
request header or the request body parameter _METHOD
to override an incoming request’s method. The middleware should be placed after the routing middleware has been added.<?php
use Slim\Factory\AppFactory;
use Slim\Middleware\MethodOverrideMiddleware;
require __DIR__ . '/../vendor/autoload.php';
$app = AppFactory::create();
// Add RoutingMiddleware before we add the MethodOverrideMiddleware so the method is overrode before routing is done
$app->addRoutingMiddleware();
// Add MethodOverride middleware
$methodOverrideMiddleware = new MethodOverrideMiddleware();
$app->add($methodOverrideMiddleware);
// ...
$app->run();
<?php
use Slim\Factory\AppFactory;
use Slim\Middleware\OutputBufferingMiddleware;
use Slim\Psr7\Factory\StreamFactory;
require __DIR__ . '/../vendor/autoload.php';
$app = AppFactory::create();
$streamFactory = new StreamFactory();
/**
* The two modes available are
* OutputBufferingMiddleware::APPEND (default mode) - Appends to existing response body
* OutputBufferingMiddleware::PREPEND - Creates entirely new response body
*/
$mode = OutputBufferingMiddleware::APPEND;
$outputBufferingMiddleware = new OutputBufferingMiddleware($streamFactory, $mode);
$app->add($outputBufferingMiddleware);
// ...
$app->run();
getBody()
yourself. As this is a common requirement, Slim 4 provides BodyParsingMiddleware to handle this task.addErrorMiddlware
, so that the stack looks like this :<?php
use Slim\Factory\AppFactory;
require_once __DIR__ . '/../vendor/autoload.php';
$app = AppFactory::create();
// Parse json, form data and xml
$app->addBodyParsingMiddleware();
$app->addRoutingMiddleware();
$app->addErrorMiddleware(true, true, true);
// ...
$app->run();
Posted JSON, form or XML data :
No changes are required to the POST handler because the BodyParsingMiddleware
detects that the Content-Type is set to a JSON media type and so places the decoded body into the Request’s parsed body property.
For data posted to the website from a browser, you can use the $request’s
getParsedBody()
method.
This will return an array of the posted data.
$app->post('/', function (Request $request, Response $response, $args): Response {
$data = $request->getParsedBody();
$html = var_export($data, true);
$response->getBody()->write($html);
return $response;
});
Content-Type
from the request header to detect the media type.application/*
addContentLengthHeader
setting that was removed from Slim 3. This middleware should be placed on the end of the middleware stack so that it gets executed first and exited last.<?php
use Slim\Factory\AppFactory;
use Slim\Middleware\ContentLengthMiddleware;
require __DIR__ . '/../vendor/autoload.php';
$app = AppFactory::create();
// Add any middleware which may modify the response body before adding the ContentLengthMiddleware
$contentLengthMiddleware = new ContentLengthMiddleware();
$app->add($contentLengthMiddleware);
// ...
$app->run();