diff --git a/README.md b/README.md index 874f5a72..e27d30bb 100644 --- a/README.md +++ b/README.md @@ -1,32 +1,37 @@ -# Slim-Website +# The Slim Framework Website -This is the repository for the Slim website at www.slimframework.com. +This is the repository for the Slim website ([slimframework.com][slimframework-url]). +## Want to contribute? -## Contributing +If you spot any errors, typos, or missing information, please submit [a pull request][pr-url]. -If you spot any errors, typos or missing information, please submit a pull -request. +### The documentation style guide + +Unless otherwise stated, the documentation follows [the AP Stylebook][ap-stylebook-url]. + +### Are you a Microsoft Windows user -### Windows User You need to make sure you have [Ruby Devkit Installed (MSYS2)](https://rubyinstaller.org/add-ons/devkit.html). -### Running Locally +### Building and running the documentation locally To run this site locally so that you can test your changes: + ```bash $ sudo gem install bundler $ bundle install ``` -Now, run the local jekyll: +Now, run the local [Jekyll][jekyll-url] installation: + ```bash $ bundle exec jekyll serve ``` -and browse to http://localhost:4000 +Then, browse to http://localhost:4000 in your browser of choice. -#### CSS +#### Editing the site's CSS The CSS uses Less and is managed by `grunt`. @@ -40,22 +45,28 @@ $ npm install To change any CSS, edit the appropriate files in `assets\less` and then run: ```bash -$ grunt +grunt ``` -You can also run `grunt watch` to automatically rebuild when you make CSS -changes. +You can also run `grunt watch` to automatically rebuild when you make CSS changes. -### Build Instructions For Deployment +### Build instructions for deployment ```bash -$ bundle exec jekyll build +bundle exec jekyll build ``` -### Update Algolia Search -Ensure you set the environment variable `ALGOLIA_API_KEY` before running these commands. See [algolia docs](https://community.algolia.com/jekyll-algolia/getting-started.html) for more information +### Update the Algolia search database + +Ensure you set the environment variable `ALGOLIA_API_KEY` before running these commands. +See [algolia docs](https://community.algolia.com/jekyll-algolia/getting-started.html) for more information. ```bash -$ bundle install -$ bundle exec jekyll algolia +bundle install +bundle exec jekyll algolia ``` + +[ap-stylebook-url]: https://www.apstylebook.com +[jekyll-url]: https://jekyllrb.com +[pr-url]: https://github.com/slimphp/Slim-Website/compare +[slimframework-url]: https://slimframework.com \ No newline at end of file diff --git a/docs/v4/concepts/di.md b/docs/v4/concepts/di.md index 76037068..25047ab7 100644 --- a/docs/v4/concepts/di.md +++ b/docs/v4/concepts/di.md @@ -2,15 +2,17 @@ title: Dependency Container --- -Slim uses an optional dependency container to prepare, manage, and inject application -dependencies. Slim supports containers that implement [PSR-11](http://www.php-fig.org/psr/psr-11/) like [PHP-DI](http://php-di.org/doc/frameworks/slim.html). +Slim uses an optional dependency container to prepare, manage, and inject application dependencies. +Slim supports containers that implement [PSR-11](http://www.php-fig.org/psr/psr-11/) like [PHP-DI](http://php-di.org/doc/frameworks/slim.html). ## Example usage with PHP-DI -You don't _have_ to provide a dependency container. If you do, however, you must provide an instance of the container to `AppFactory` before creating an `App`. +You don't _have_ to provide a dependency container. +If you do, however, you must provide an instance of the container to `AppFactory` before creating an `App`. ```php set('myService', function () { }); ``` -You can fetch services from your container explicitly as well as from inside a Slim -application route like this: +You can fetch services from your container explicitly as well as from inside a Slim application route like this: ```php /** @@ -79,8 +80,7 @@ $app->get('/foo', function (Request $request, Response $response, $args) { ## Configuring the application via a container -In case you want to create the `App` with dependencies already defined in your container, -you can use the `AppFactory::createFromContainer()` method. +In case you want to create the `App` with dependencies already defined in your container, you can use the `AppFactory::createFromContainer()` method. **Example** diff --git a/docs/v4/concepts/life-cycle.md b/docs/v4/concepts/life-cycle.md index 68388fdf..b31f8965 100644 --- a/docs/v4/concepts/life-cycle.md +++ b/docs/v4/concepts/life-cycle.md @@ -6,23 +6,33 @@ title: Lifecycle ### 1. Instantiation -First, you instantiate the `Slim\App` class. This is the Slim application object. During instantiation, Slim registers default services for each application dependency. +First, you instantiate the `Slim\App` class. +This is the Slim application object. +During instantiation, Slim registers default services for each application dependency. ### 2. Route Definitions -Second, you define routes using the application instance's `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. +Second, you define routes using the application instance's `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. ### 3. Application Runner -Third, you invoke the application instance's `run()` method. This method starts the following process: +Third, you invoke the application instance's `run()` method. +This method starts the following process: #### A. Enter Middleware Stack -The `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 innermost layer of the concentric middleware structure. Each middleware layer is invoked inwardly beginning from the outermost layer. +The `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 innermost layer of the concentric middleware structure. +Each middleware layer is invoked inwardly beginning from the outermost layer. #### B. Run Application -After the `run()` method reaches the innermost 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. +After the `run()` method reaches the innermost 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. #### C. Exit Middleware Stack @@ -30,4 +40,5 @@ After the application dispatch process completes, each middleware layer reclaims #### D. Send HTTP Response -After the outermost middleware layer cedes control, the application instance prepares, serializes, and returns the HTTP response. The HTTP response headers are set with PHP's native `header()` method, and the HTTP response body is output to the current output buffer. +After the outermost middleware layer cedes control, the application instance prepares, serializes, and returns the HTTP response. +The HTTP response headers are set with PHP's native `header()` method, and the HTTP response body is output to the current output buffer. diff --git a/docs/v4/concepts/middleware.md b/docs/v4/concepts/middleware.md index e03a3d3f..5892b378 100644 --- a/docs/v4/concepts/middleware.md +++ b/docs/v4/concepts/middleware.md @@ -2,11 +2,12 @@ title: Middleware --- -You can run code _before_ and _after_ your Slim application to manipulate the -Request and Response objects as you see fit. This is called _middleware_. -Why would you want to do this? Perhaps you want to protect your app -from cross-site request forgery. Maybe you want to authenticate requests -before your app runs. Middleware is perfect for these scenarios. +You can run code _before_ and _after_ your Slim application to manipulate the Request and Response objects as you see fit. +This is called _middleware_. +Why would you want to do this? +Perhaps you want to protect your app from cross-site request forgery. +Maybe you want to authenticate requests before your app runs. +Middleware is perfect for these scenarios. ## What is middleware? @@ -15,29 +16,24 @@ A middleware implements the [PSR-15 Middleware Interface](https://www.php-fig.or 1. `Psr\Http\Message\ServerRequestInterface` - The PSR-7 request object 2. `Psr\Http\Server\RequestHandlerInterface` - The PSR-15 request handler object -It can do whatever is appropriate with these objects. The only hard requirement -is that a middleware **MUST** return an instance of `Psr\Http\Message\ResponseInterface`. -Each middleware **SHOULD** invoke the next middleware and pass it the Request -object as argument. +It can do whatever is appropriate with these objects. +The only hard requirement is that a middleware **MUST** return an instance of `Psr\Http\Message\ResponseInterface`. +Each middleware **SHOULD** invoke the next middleware and pass it the Request object as argument. ## How does middleware work? -Different frameworks use middleware differently. Slim adds middleware as concentric -layers surrounding your core application. Each new middleware layer surrounds -any existing middleware layers. The concentric structure expands outwardly as -additional middleware layers are added. +Different frameworks use middleware differently. +Slim adds middleware as concentric layers surrounding your core application. +Each new middleware layer surrounds any existing middleware layers. +The concentric structure expands outwardly as additional middleware layers are added. The last middleware layer added is the first to be executed. -When you run the Slim application, the Request object traverses the -middleware structure from the outside in. They first enter the outermost middleware, -then the next outermost middleware, (and so on), until they ultimately arrive -at the Slim application itself. After the Slim application dispatches the -appropriate route, the resultant Response object exits the Slim application and -traverses the middleware structure from the inside out. Ultimately, a final -Response object exits the outermost middleware, is serialized into a raw HTTP -response, and is returned to the HTTP client. Here's a diagram that illustrates -the middleware process flow: +When you run the Slim application, the Request object traverses the middleware structure from the outside in. +They first enter the outermost middleware, then the next outermost middleware, (and so on), until they ultimately arrive at the Slim application itself. +After the Slim application dispatches the appropriate route, the resultant Response object exits the Slim application and traverses the middleware structure from the inside out. +Ultimately, a final Response object exits the outermost middleware, is serialized into a raw HTTP response, and is returned to the HTTP client. +Here's a diagram that illustrates the middleware process flow:
Middleware architecture @@ -45,7 +41,8 @@ the middleware process flow: ## How do I write middleware? -Middleware is a callable that accepts two arguments: a `Request` object and a `RequestHandler` object. Each middleware **MUST** return an instance of `Psr\Http\Message\ResponseInterface`. +Middleware is a callable that accepts two arguments: a `Request` object and a `RequestHandler` object. +Each middleware **MUST** return an instance of `Psr\Http\Message\ResponseInterface`. ### Closure middleware example. @@ -129,6 +126,7 @@ class ExampleBeforeMiddleware ```php run(); ## How do I add middleware? -You may add middleware to a Slim application, to an individual Slim application route or to a route group. All scenarios accept the same middleware and implement the same middleware interface. +You may add middleware to a Slim application, to an individual Slim application route or to a route group. +All scenarios accept the same middleware and implement the same middleware interface. ### Application middleware -Application middleware is invoked for every **incoming** HTTP request. Add application middleware with the Slim application instance's **add()** method. This example adds the Closure middleware example above: +Application middleware is invoked for every **incoming** HTTP request. +Add application middleware with the Slim application instance's **add()** method. +This example adds the Closure middleware example above: ```php group('/utils', function (RouteCollectorProxy $group) { $app->run(); ``` -When calling the **/utils/date** method, this would output a string similar to the below +When calling the **/utils/date** method, this would output a string similar to the below. ```bash It is now 2015-07-06 03:11:01. Enjoy! ``` -Visiting **/utils/time** would output a string similar to the below +Visiting **/utils/time** would output a string similar to the below. ```bash It is now 1436148762. Enjoy! ``` -But visiting **/** *(domain-root)*, would be expected to generate the following output as no middleware has been assigned +But visiting **/** *(domain-root)*, would be expected to generate the following output as no middleware has been assigned. ```bash Hello World ``` ### Passing variables from middleware -The easiest way to pass attributes from middleware is to use the request's -attributes. +The easiest way to pass attributes from middleware is to use the request's attributes. Setting the variable in the middleware: @@ -347,7 +358,8 @@ $foo = $request->getAttribute('foo'); ## Finding available middleware -You may find a PSR-15 Middleware class already written that will satisfy your needs. Here are a few unofficial lists to search. +You may find a PSR-15 Middleware class already written that will satisfy your needs. +Here are a few unofficial lists to search. * [Middleware for Slim Framework v4.x wiki](https://github.com/slimphp/Slim/wiki/Middleware-for-Slim-Framework-v4.x) * [middlewares/awesome-psr15-middlewares](https://github.com/middlewares/awesome-psr15-middlewares) diff --git a/docs/v4/concepts/value-objects.md b/docs/v4/concepts/value-objects.md index fde67cbb..833b5aac 100644 --- a/docs/v4/concepts/value-objects.md +++ b/docs/v4/concepts/value-objects.md @@ -2,31 +2,26 @@ title: PSR-7 and Value Objects --- -Slim supports [PSR-7](https://github.com/php-fig/http-message) interfaces for -its Request and Response objects. This makes Slim flexible because it can -use _any_ PSR-7 implementation. For example, you could return an instance of -`GuzzleHttp\Psr7\CachingStream` or any instance -returned by the `GuzzleHttp\Psr7\stream_for()` function. +Slim supports [PSR-7](https://github.com/php-fig/http-message) interfaces for its Request and Response objects. +This makes Slim flexible because it can use _any_ PSR-7 implementation. +For example, you could return an instance of `GuzzleHttp\Psr7\CachingStream` or any instance returned by the `GuzzleHttp\Psr7\stream_for()` function. Slim provides its own PSR-7 implementation. -However, you are free to -[install a third-party implementation](/docs/v4/start/installation.html). +However, you are free to [install a third-party implementation](/docs/v4/start/installation.html). ## Value objects Request and Response objects are [_immutable value objects_](http://en.wikipedia.org/wiki/Value_object). -They can be "changed" only by requesting a cloned version that has updated -property values. Value objects have a nominal overhead because they must be -cloned when their properties are updated. This overhead does not affect -performance in any meaningful way. +They can be "changed" only by requesting a cloned version that has updated property values. +Value objects have a nominal overhead because they must be cloned when their properties are updated. +This overhead does not affect performance in any meaningful way. -You can request a copy of a value object by invoking any of its PSR-7 -interface methods (these methods typically have a `with` prefix). For example, -a PSR-7 Response object has a `withHeader($name, $value)` method that returns a -cloned value object with the new HTTP header. +You can request a copy of a value object by invoking any of its PSR-7 interface methods (these methods typically have a `with` prefix). +For example, a PSR-7 Response object has a `withHeader($name, $value)` method that returns a cloned value object with the new HTTP header. ```php get('/foo', function (Request $request, Response $response, array $args) { $app->run(); ``` -The PSR-7 interface provides these methods to transform Request and Response -objects: +The PSR-7 interface provides these methods to transform Request and Response objects: * `withProtocolVersion($version)` * `withHeader($name, $value)` diff --git a/docs/v4/contributors/guidelines.md b/docs/v4/contributors/guidelines.md index 2d221648..f854480e 100644 --- a/docs/v4/contributors/guidelines.md +++ b/docs/v4/contributors/guidelines.md @@ -2,11 +2,13 @@ title: Contributor Guidelines --- -I encourage everyone to contribute to the Slim Framework project. You can find the latest code on GitHub at . +I encourage everyone to contribute to the Slim Framework project. +You can find the latest code on GitHub at . ## Issue Tracker -You can find outstanding issues on the [GitHub Issue Tracker](https://github.com/slimphp/Slim/issues). If you intend to work on a specific issue, leave a comment on the appropriate thread to inform other project contributors. +You can find outstanding issues on the [GitHub Issue Tracker](https://github.com/slimphp/Slim/issues). +If you intend to work on a specific issue, leave a comment on the appropriate thread to inform other project contributors. ## Pull Requests diff --git a/docs/v4/contributors/strategy.md b/docs/v4/contributors/strategy.md index 71dc6b58..d016df64 100644 --- a/docs/v4/contributors/strategy.md +++ b/docs/v4/contributors/strategy.md @@ -2,4 +2,6 @@ title: Branching Strategy --- -The Slim Framework uses a simple branching strategy. There is a `4.x` branch, and the `4.x` branch `HEAD` reference points to the latest unstable code. Each stable release is denoted with a numeric tag (e.g., `4.0.0`). +The Slim Framework uses a simple branching strategy. +There is a `4.x` branch, and the `4.x` branch `HEAD` reference points to the latest unstable code. +Each stable release is denoted with a numeric tag (e.g., `4.0.0`). diff --git a/docs/v4/cookbook/database-doctrine.md b/docs/v4/cookbook/database-doctrine.md index 8c2a3b2a..d0ec398a 100644 --- a/docs/v4/cookbook/database-doctrine.md +++ b/docs/v4/cookbook/database-doctrine.md @@ -12,24 +12,22 @@ The first step is importing the Doctrine ORM into your project using [composer]( composer require doctrine/orm symfony/cache ``` -Note that on April 30th 2021 Doctrine officially deprecated `doctrine/cache` when it released version v2.0.0, which -deleted all cache implementations from that library. +Note that on April 30th 2021 Doctrine officially deprecated `doctrine/cache` when it released version v2.0.0, which deleted all cache implementations from that library. Since then they recommend using `symfony/cache` instead, a PSR-6 compliant implementation. You only need it if you want to cache Doctrine metadata in production but there's no downside to do it, so we'll show how to set it up. -If you have not yet migrated to PHP8 or simply want to continue using traditional PHPDoc comments to annotate your entities you'll also need to import -the `doctrine/annotations` package, which used to be a dependency of `doctrine/orm` but since 2.10.0 is optional: +If you have not yet migrated to PHP8 or simply want to continue using traditional PHPDoc comments to annotate your entities you'll also need to import the `doctrine/annotations` package, which used to be a dependency of `doctrine/orm` but since 2.10.0 is optional: + ```bash composer require doctrine/annotations ``` - ## Define your first Entity You can skip this step and use your actual Doctrine entities instead. The following is just an example. -Note that it uses PHP8 attributes, convert them to PHPDoc annotations if you need to. +Note that it uses PHP 8 attributes, convert them to PHPDoc annotations if you need to.
```php @@ -81,10 +79,8 @@ final class User
Figure 1: A sample Doctrine entity.
- ## Provide database credentials - Next, add the Doctrine settings alongside your Slim configuration.
@@ -154,14 +150,10 @@ Slim 4 requires that you provide your own PSR-11 container implementation. This example uses [`uma/dic`](https://github.com/1ma/dic), a simple and concise PSR-11 container. Adapt this to your own choice of container. -Traditionally the annotation metadata reader was the most popular, but starting from `doctrine/orm` 2.10.0 they -made the dependency on `doctrine/annotations` optional, hinting that the project prefers users to migrate to -the modern PHP8 attribute notation. +Traditionally the annotation metadata reader was the most popular, but starting from `doctrine/orm` 2.10.0 they made the dependency on `doctrine/annotations` optional, hinting that the project prefers users to migrate to the modern PHP8 attribute notation. Here we show how to configure the metadata reader with PHP8 attributes. -If you have not yet migrated to PHP8 or want to use traditional PHPDoc annotations you'll need to -explicitly require `doctrine/annotations` with Composer and call `Setup::createAnnotationMetadataConfiguration(...)` instead -of `Setup::createAttributeMetadataConfiguration(...)` as in the following example. +If you have not yet migrated to PHP8 or want to use traditional PHPDoc annotations you'll need to explicitly require `doctrine/annotations` with Composer and call `Setup::createAnnotationMetadataConfiguration(...)` instead of `Setup::createAttributeMetadataConfiguration(...)` as in the following example.
```php @@ -208,15 +200,12 @@ return $container; ## Create the Doctrine console -To run database migrations, validate class annotations and so on you will use the `doctrine` CLI application that is -already present at `vendor/bin`. But in order to work this script needs a [`cli-config.php`](http://docs.doctrine-project.org/en/latest/reference/configuration.html#setting-up-the-commandline-tool) -file at the root of the project telling it how to find the `EntityManager` we just set up. +To run database migrations, validate class annotations and so on you will use the `doctrine` CLI application that is already present at `vendor/bin`. +But in order to work this script needs a [`cli-config.php`](http://docs.doctrine-project.org/en/latest/reference/configuration.html#setting-up-the-commandline-tool) file at the root of the project telling it how to find the `EntityManager` we just set up. -Our `cli-config.php` only needs to retrieve the EntityManager service we just defined in our container and -pass it to `ConsoleRunner::createHelperSet()`. +Our `cli-config.php` only needs to retrieve the EntityManager service we just defined in our container and pass it to `ConsoleRunner::createHelperSet()`.
- ```php get(EntityManager::class));
Figure 4: Enabling Doctrine's console app.
-Take a moment to verify that the console app works. When properly configured, its output will look more or less like this: - +Take a moment to verify that the console app works. +When properly configured, its output will look more or less like this:
```bash @@ -289,7 +278,8 @@ At this point you can initialize the database and load the schema by running `ph ## Using the EntityManager in our own code -Congratulations! You can now manage your database from the command line and use the `EntityManager` wherever you need it in your code. +Congratulations! +You can now manage your database from the command line and use the `EntityManager` wherever you need it in your code.
```php diff --git a/docs/v4/cookbook/enable-cors.md b/docs/v4/cookbook/enable-cors.md index f35a6186..52405214 100644 --- a/docs/v4/cookbook/enable-cors.md +++ b/docs/v4/cookbook/enable-cors.md @@ -168,8 +168,7 @@ $app->run(); ## Access-Control-Allow-Credentials -If the request contains credentials (cookies, authorization headers or TLS client certificates), -you might need to add an `Access-Control-Allow-Credentials` header to the response object. +If the request contains credentials (cookies, authorization headers or TLS client certificates), you might need to add an `Access-Control-Allow-Credentials` header to the response object. ```php $response = $response->withHeader('Access-Control-Allow-Credentials', 'true'); diff --git a/docs/v4/cookbook/retrieving-current-route.md b/docs/v4/cookbook/retrieving-current-route.md index ca349f6b..a8042e11 100644 --- a/docs/v4/cookbook/retrieving-current-route.md +++ b/docs/v4/cookbook/retrieving-current-route.md @@ -6,11 +6,13 @@ If you ever need to get access to the current route within your application, you From there you can get the route via `$routeContext->getRoute()` and access the route's name by using `getName()` or get the methods supported by this route via `getMethods()`, etc. -Note: If you need to access the `RouteContext` object during the middleware cycle before reaching the route handler you will need to add the `RoutingMiddleware` as the outermost middleware before the error handling middleware (See example below). +**Note:** If you need to access the `RouteContext` object during the middleware cycle before reaching the route handler you will need to add the `RoutingMiddleware` as the outermost middleware before the error handling middleware (See example below). Example: + ```php Figure 1: Example HTML form for file uploads
-Uploaded files can be moved to a directory using the `moveTo` method. Below is an example application -that handles the uploaded files of the HTML form above. +Uploaded files can be moved to a directory using the `moveTo` method. +Below is an example application that handles the uploaded files of the HTML form above.
```php diff --git a/docs/v4/deployment/deployment.md b/docs/v4/deployment/deployment.md index d3c093c5..47c29299 100644 --- a/docs/v4/deployment/deployment.md +++ b/docs/v4/deployment/deployment.md @@ -1,16 +1,19 @@ --- title: Deployment --- -Congratulations! if you have made it this far, that means you have successfully built something -awesome using Slim. However, the time to party has not come yet. We still have to push our -application to the production server. +Congratulations! +if you have made it this far, that means you have successfully built something awesome using Slim. +However, the time to party has not come yet. +We still have to push our application to the production server. -There are many ways to do this that are beyond the scope of this documentation. In -this section, we provide some notes for various set-ups. +There are many ways to do this that are beyond the scope of this documentation. +In this section, we provide some notes for various set-ups. ### Disable error display in production + ```php addErrorMiddleware(false, true, true); $app->run(); ``` -You should also ensure that your PHP installation is configured to not display -errors with the `php.ini` setting: +You should also ensure that your PHP installation is configured to not display errors with the `php.ini` setting: ```bash display_errors = 0 @@ -36,8 +38,7 @@ display_errors = 0 ## Deploying to your own server -If you control your server, then you should set up a deployment process using any -one of the many deployment system such as: +If you control your server, then you should set up a deployment process using any one of the many deployment system such as: * Deploybot * Capistrano @@ -47,9 +48,7 @@ Review the [Web Servers](/docs/v4/start/web-servers.html) documentation to confi ## Deploying to a shared server -If your shared server runs Apache, then you need to create a `.htaccess` file -in your web server root directory (usually named `htdocs`, `public`, `public_html` -or `www`) with the following content: +If your shared server runs Apache, then you need to create a `.htaccess` file in your web server root directory (usually named `htdocs`, `public`, `public_html` or `www`) with the following content: ```bash @@ -61,6 +60,5 @@ or `www`) with the following content: (replace 'public' with the correct name of your domain name e.g. example.com/$1) -Now upload all the files that make up your Slim project to the webserver. As you -are on shared hosting, this is probably done via FTP and you can use any FTP client, -such as Filezilla to do this. +Now upload all the files that make up your Slim project to the webserver. +As you are on shared hosting, this is probably done via FTP and you can use any FTP client, such as Filezilla to do this. diff --git a/docs/v4/features/templates.md b/docs/v4/features/templates.md index acbf810c..8f6f3937 100644 --- a/docs/v4/features/templates.md +++ b/docs/v4/features/templates.md @@ -2,21 +2,18 @@ title: Templates --- -Slim does not have a view layer like traditional MVC frameworks. Instead, -Slim's "view" _is the HTTP response_. Each Slim application route is responsible -for preparing and returning an appropriate PSR-7 response object. +Slim does not have a view layer like traditional MVC frameworks. +Instead, Slim's "view" _is the HTTP response_. +Each Slim application route is responsible for preparing and returning an appropriate PSR-7 response object. > Slim's "view" is the HTTP response. -That being said, the Slim project provides the [Twig-View](#the-slimtwig-view-component) and -[PHP-View](#the-slimphp-view-component) components to help you render templates to a PSR7 -Response object. +That being said, the Slim project provides the [Twig-View](#the-slimtwig-view-component) and [PHP-View](#the-slimphp-view-component) components to help you render templates to a PSR7 Response object. ## The slim/twig-view component -The [Twig-View][twigview] PHP component helps you render [Twig][twig] -templates in your application. This component is available on Packagist, and -it's easy to install with Composer like this: +The [Twig-View][twigview] PHP component helps you render [Twig][twig] templates in your application. +This component is available on Packagist, and it's easy to install with Composer like this: [twigview]: https://github.com/slimphp/Twig-View [twig]: http://twig.symfony.com/ @@ -51,10 +48,10 @@ $app->add(TwigMiddleware::create($app, $twig));
Figure 2: Add slim/twig-view middleware.
-Note : For production scenarios, `cache` should be set to some `'path/to/cache'` to store compiled templates (thus avoiding recomplication on every request). For more information, see [Twig environment options](http://twig.symfony.com/doc/3.x/api.html#environment-options) +**Note:** For production scenarios, `cache` should be set to some `'path/to/cache'` to store compiled templates (thus avoiding recomplication on every request). +For more information, see [Twig environment options](http://twig.symfony.com/doc/3.x/api.html#environment-options) -Now you can use the `slim/twig-view` component service inside an app route -to render a template and write it to a PSR-7 Response object like this: +Now you can use the `slim/twig-view` component service inside an app route to render a template and write it to a PSR-7 Response object like this:
```php @@ -71,26 +68,21 @@ $app->run();
Figure 3: Render template with slim/twig-view container service.
-In this example, `$view` invoked inside the route callback is a reference -to the `\Slim\Views\Twig` instance returned by the `fromRequest` method. -The `\Slim\Views\Twig` instance's `render()` method accepts a PSR-7 Response -object as its first argument, the Twig template path as its second argument, -and an array of template variables as its final argument. The `render()` method -returns a new PSR-7 Response object whose body is the rendered Twig template. +In this example, `$view` invoked inside the route callback is a reference to the `\Slim\Views\Twig` instance returned by the `fromRequest` method. +The `\Slim\Views\Twig` instance's `render()` method accepts a PSR-7 Response object as its first argument, the Twig template path as its second argument, and an array of template variables as its final argument. +The `render()` method returns a new PSR-7 Response object whose body is the rendered Twig template. ### The url_for() method -The `slim/twig-view` component exposes a custom `url_for()` function -to your Twig templates. You can use this function to generate complete -URLs to any named route in your Slim application. The `url_for()` -function accepts two arguments: +The `slim/twig-view` component exposes a custom `url_for()` function to your Twig templates. +You can use this function to generate complete URLs to any named route in your Slim application. +The `url_for()` function accepts two arguments: 1. A route name 2. A hash of route placeholder names and replacement values -The second argument's keys should correspond to the selected route's pattern -placeholders. This is an example Twig template that draws a link URL -for the "profile" named route shown in the example Slim application above. +The second argument's keys should correspond to the selected route's pattern placeholders. +This is an example Twig template that draws a link URL for the "profile" named route shown in the example Slim application above. ```html {% raw %} @@ -108,8 +100,7 @@ for the "profile" named route shown in the example Slim application above. ## The slim/php-view component The [PHP-View][phpview] PHP component helps you render PHP templates. -This component is available on Packagist and can be installed using -Composer like this: +This component is available on Packagist and can be installed using Composer like this: [phpview]: https://github.com/slimphp/PHP-View @@ -130,8 +121,6 @@ use Slim\Views\PhpRenderer; require __DIR__ . '/vendor/autoload.php'; - - // Create App $app = AppFactory::create(); @@ -147,6 +136,5 @@ $app->run(); ## Other template systems -You are not limited to the `Twig-View` and `PHP-View` components. You -can use any PHP template system provided that you ultimately write the rendered -template output to the PSR-7 Response object's body. +You are not limited to the `Twig-View` and `PHP-View` components. +You can use any PHP template system provided that you ultimately write the rendered template output to the PSR-7 Response object's body. diff --git a/docs/v4/middleware/body-parsing.md b/docs/v4/middleware/body-parsing.md index f4e477f7..2caf51ee 100644 --- a/docs/v4/middleware/body-parsing.md +++ b/docs/v4/middleware/body-parsing.md @@ -3,15 +3,12 @@ title: Body Parsing Middleware --- It’s very common in web APIs to send data in JSON or XML format. -Out of the box, PSR-7 implementations do not support these formats, -you have to decode the Request object’s getBody() yourself. -As this is a common requirement, Slim 4 provides `BodyParsingMiddleware` -to handle this task. +Out of the box, PSR-7 implementations do not support these formats, you have to decode the Request object’s getBody() yourself. +As this is a common requirement, Slim 4 provides `BodyParsingMiddleware` to handle this task. ## Usage -It's recommended to put the body parsing middleware before the call to -`addErrorMiddlware`, so that the stack looks like this: +It's recommended to put the body parsing middleware before the call to `addErrorMiddlware`, so that the stack looks like this: ```php 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. +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. +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. @@ -59,8 +53,8 @@ $app->post('/', function (Request $request, Response $response, $args): Response ## Media type detection * The middleware reads the `Content-Type` from the request header to detect the media type. -* Checks if this specific media type has a parser registered -* If not, look for a media type with a structured syntax suffix (RFC 6839), e.g. `application/*` +* Checks if this specific media type has a parser registered. +* If not, look for a media type with a structured syntax suffix (RFC 6839), e.g. `application/`. ## Supported media types diff --git a/docs/v4/middleware/content-length.md b/docs/v4/middleware/content-length.md index 6ce83d73..51038acb 100644 --- a/docs/v4/middleware/content-length.md +++ b/docs/v4/middleware/content-length.md @@ -2,11 +2,14 @@ title: Content Length Middleware --- -The Content Length Middleware will automatically append a `Content-Length` header to the response. This is to replace the `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. +The Content Length Middleware will automatically append a `Content-Length` header to the response. +This is to replace the `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. ## Usage ```php run(); ``` ## Adding Custom Error Handlers + You can now map custom handlers for any type of Exception or Throwable. + ```php setDefaultErrorHandler($myErrorHandler); $app->run(); ``` -With the second method, you can supply a logger that conforms to the -[PSR-3 standard](https://www.php-fig.org/psr/psr-3/), such as one from the popular -[Monolog](https://github.com/Seldaek/monolog/) library. +With the second method, you can supply a logger that conforms to the [PSR-3 standard](https://www.php-fig.org/psr/psr-3/), such as one from the popular [Monolog](https://github.com/Seldaek/monolog/) library. ```php run(); ``` ## Error Handling/Rendering + The rendering is finally decoupled from the handling. It will still detect the content-type and render things appropriately with the help of `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: +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` -For any content type you can register your own error renderer. So first define a new error renderer -that implements `\Slim\Interfaces\ErrorRendererInterface`. +For any content type you can register your own error renderer. +So first define a new error renderer that implements `\Slim\Interfaces\ErrorRendererInterface`. ```php run(); ``` ### Force a specific content type for error rendering -By default, the error handler tries to detect the error renderer using the `Accept` header of the -request. If you need to force the error handler to use a specific error renderer you can + +By default, the error handler tries to detect the error renderer using the `Accept` header of the request. +If you need to force the error handler to use a specific error renderer you can write the following. ```php @@ -223,9 +238,13 @@ $errorHandler->forceContentType('application/json'); ``` ## New HTTP Exceptions -We have added named HTTP exceptions within the application. These exceptions work nicely with the native renderers. They can each have a `description` and `title` attribute as well to provide a bit more insight when the native HTML renderer is invoked. + +We have added named HTTP exceptions within the application. +These exceptions work nicely with the native renderers. +They can each have a `description` and `title` attribute as well to provide a bit more insight when the native HTML renderer is invoked. The base class `HttpSpecializedException` extends `Exception` and comes with the following sub classes: + * HttpBadRequestException * HttpForbiddenException * HttpInternalServerErrorException @@ -234,7 +253,9 @@ The base class `HttpSpecializedException` extends `Exception` and comes with the * HttpNotImplementedException * HttpUnauthorizedException -You can extend the `HttpSpecializedException` class if they need any other response codes that we decide not to provide with the base repository. Example if you wanted a 504 gateway timeout exception that behaves like the native ones you would do the following: +You can extend the `HttpSpecializedException` class if they need any other response codes that we decide not to provide with the base repository. +Example if you wanted a 504 gateway timeout exception that behaves like the native ones you would do the following: + ```php class HttpGatewayTimeoutException extends HttpSpecializedException { diff --git a/docs/v4/middleware/method-overriding.md b/docs/v4/middleware/method-overriding.md index 27977122..c92786a3 100644 --- a/docs/v4/middleware/method-overriding.md +++ b/docs/v4/middleware/method-overriding.md @@ -2,11 +2,13 @@ title: Method Overriding Middleware --- -The Method Overriding Middleware enables you to use the `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. +The Method Overriding Middleware enables you to use the `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. ## Usage ```php run(); ## Advanced Notices and Warnings Handling -**Warnings** and **Notices** are not caught by default. If you wish your application to display an error page when they happen, you will need to implement code similar to the following `index.php`. +**Warnings** and **Notices** are not caught by default. +If you wish your application to display an error page when they happen, you will need to implement code similar to the following `index.php`. ```php ```php run();
Figure 1: Inject PSR-7 request into application route callback.
-The PSR-7 request object is injected into your Slim application _middleware_ -as the first argument of the middleware callable like this: +The PSR-7 request object is injected into your Slim application _middleware_ as the first argument of the middleware callable like this:
```php @@ -73,25 +70,23 @@ Every HTTP request has a method that is typically one of: * PATCH * OPTIONS -You can inspect the HTTP request's method with the Request object method -appropriately named `getMethod()`. +You can inspect the HTTP request's method with the Request object method appropriately named `getMethod()`. ```php $method = $request->getMethod(); ``` -It is possible to fake or _override_ the HTTP request method. This is -useful if, for example, you need to mimic a `PUT` request using a traditional -web browser that only supports `GET` or `POST` requests. +It is possible to fake or _override_ the HTTP request method. +This is useful if, for example, you need to mimic a `PUT` request using a traditional web browser that only supports `GET` or `POST` requests.
Heads Up!
To enable request method overriding the Method Overriding Middleware must be injected into your application.
-There are two ways to override the HTTP request method. You can include a -`METHOD` parameter in a `POST` request's body. The HTTP request must use the -`application/x-www-form-urlencoded` content type. +There are two ways to override the HTTP request method. +You can include a `METHOD` parameter in a `POST` request's body. +The HTTP request must use the `application/x-www-form-urlencoded` content type.
```bash @@ -105,9 +100,8 @@ data=value&_METHOD=PUT
Figure 3: Override HTTP method with _METHOD parameter.
-You can also override the HTTP request method with a custom -`X-Http-Method-Override` HTTP request header. This works with any HTTP request -content type. +You can also override the HTTP request method with a custom `X-Http-Method-Override` HTTP request header. +This works with any HTTP request content type.
```bash @@ -124,8 +118,8 @@ X-Http-Method-Override: PUT ## The Request URI -Every HTTP request has a URI that identifies the requested application -resource. The HTTP request URI has several parts: +Every HTTP request has a URI that identifies the requested application resource. +The HTTP request URI has several parts: * Scheme (e.g. `http` or `https`) * Host (e.g. `example.com`) @@ -141,8 +135,7 @@ You can fetch the PSR-7 Request object's [URI object][psr7_uri] with its `getUri $uri = $request->getUri(); ``` -The PSR-7 Request object's URI is itself an object that provides the following -methods to inspect the HTTP request's URL parts: +The PSR-7 Request object's URI is itself an object that provides the following methods to inspect the HTTP request's URL parts: * getScheme() * getAuthority() @@ -157,16 +150,14 @@ You can get the query parameters as an associative array on the Request object u ## The Request Headers -Every HTTP request has headers. These are metadata that describe the HTTP -request but are not visible in the request's body. Slim's PSR-7 -Request object provides several methods to inspect its headers. +Every HTTP request has headers. +These are metadata that describe the HTTP request but are not visible in the request's body. Slim's PSR-7 Request object provides several methods to inspect its headers. ### Get All Headers You can fetch all HTTP request headers as an associative array with the PSR-7 -Request object's `getHeaders()` method. The resultant associative array's keys -are the header names and its values are themselves a numeric array of string -values for their respective header name. +Request object's `getHeaders()` method. +The resultant associative array's keys are the header names and its values are themselves a numeric array of string values for their respective header name.
```php @@ -180,8 +171,9 @@ foreach ($headers as $name => $values) { ### Get One Header -You can get a single header's value(s) with the PSR-7 Request object's `getHeader($name)` method. This returns an array of values for the given header name. Remember, _a single -HTTP header may have more than one value!_ +You can get a single header's value(s) with the PSR-7 Request object's `getHeader($name)` method. +This returns an array of values for the given header name. +Remember, _a single HTTP header may have more than one value!_
```php @@ -190,9 +182,8 @@ $headerValueArray = $request->getHeader('Accept');
Figure 6: Get values for a specific HTTP header.
-You may also fetch a comma-separated string with all values for a given header -with the PSR-7 Request object's `getHeaderLine($name)` method. Unlike the -`getHeader($name)` method, this method returns a comma-separated string. +You may also fetch a comma-separated string with all values for a given header with the PSR-7 Request object's `getHeaderLine($name)` method. +Unlike the `getHeader($name)` method, this method returns a comma-separated string.
```php @@ -203,8 +194,7 @@ $headerValueString = $request->getHeaderLine('Accept'); ### Detect Header -You can test for the presence of a header with the PSR-7 Request object's -`hasHeader($name)` method. +You can test for the presence of a header with the PSR-7 Request object's `hasHeader($name)` method.
```php @@ -217,12 +207,13 @@ if ($request->hasHeader('Accept')) { ## The Request Body -Every HTTP request has a body. If you are building a Slim application that -consumes JSON or XML data, you can use the PSR-7 Request object's -`getParsedBody()` method to parse the HTTP request body into a native PHP format. +Every HTTP request has a body. +If you are building a Slim application that consumes JSON or XML data, you can use the PSR-7 Request object's `getParsedBody()` method to parse the HTTP request body into a native PHP format. Note that body parsing differs from one PSR-7 implementation to another. -You may need to implement middleware in order to parse the incoming input depending on the PSR-7 implementation you have installed. Here is an example for parsing incoming `JSON` input: +You may need to implement middleware in order to parse the incoming input depending on the PSR-7 implementation you have installed. +Here is an example for parsing incoming `JSON` input: + ```php getParsedBody();
Figure 9: Parse HTTP request body into native PHP format
-Technically speaking, the PSR-7 Request object represents the HTTP request -body as an instance of `Psr\Http\Message\StreamInterface`. You can get -the HTTP request body `StreamInterface` instance with the PSR-7 Request object's -`getBody()` method. The `getBody()` method is preferable if the incoming HTTP -request size is unknown or too large for available memory. +Technically speaking, the PSR-7 Request object represents the HTTP request body as an instance of `Psr\Http\Message\StreamInterface`. +You can get the HTTP request body `StreamInterface` instance with the PSR-7 Request object's `getBody()` method. +The `getBody()` method is preferable if the incoming HTTP request size is unknown or too large for available memory.
```php @@ -269,8 +258,7 @@ $body = $request->getBody();
Figure 10: Get HTTP request body
-The resultant `Psr\Http\Message\StreamInterface` instance provides the following -methods to read and iterate its underlying PHP `resource`. +The resultant `Psr\Http\Message\StreamInterface` instance provides the following methods to read and iterate its underlying PHP `resource`. * getSize() * tell() @@ -287,9 +275,8 @@ methods to read and iterate its underlying PHP `resource`. ## Uploaded Files -The file uploads in `$_FILES` are available from the Request object's -`getUploadedFiles()` method. This returns an array keyed by the name of the -`input` element. +The file uploads in `$_FILES` are available from the Request object's `getUploadedFiles()` method. +This returns an array keyed by the name of the `input` element.
```php @@ -298,8 +285,7 @@ $files = $request->getUploadedFiles();
Figure 11: Get uploaded files
-Each object in the `$files` array is an instance of -`Psr\Http\Message\UploadedFileInterface` and supports the following methods: +Each object in the `$files` array is an instance of `Psr\Http\Message\UploadedFileInterface` and supports the following methods: * getStream() * moveTo($targetPath) @@ -312,8 +298,7 @@ See the [cookbook](/docs/v4/cookbook/uploading-files.html) on how to upload file ## Request Helpers -Slim's PSR-7 Request implementation provides these additional proprietary methods -to help you further inspect the HTTP request. +Slim's PSR-7 Request implementation provides these additional proprietary methods to help you further inspect the HTTP request. ### Detect XHR requests @@ -357,7 +342,6 @@ $length = $request->getHeaderLine('Content-Length'); ### Server Parameter To fetch data related to the incoming request environment, you will need to use `getServerParams()`. - For example, to get a single Server Parameter: ```php @@ -367,8 +351,7 @@ $authorization = $params['HTTP_AUTHORIZATION'] ?? null; ### POST Parameters -If the request method is `POST` and the `Content-Type` is either `application/x-www-form-urlencoded` -or `multipart/form-data`, you can retrieve all `POST` parameters as follows: +If the request method is `POST` and the `Content-Type` is either `application/x-www-form-urlencoded` or `multipart/form-data`, you can retrieve all `POST` parameters as follows: ```php // Get all POST parameters @@ -443,7 +426,7 @@ $app->get('/', function(Request $request, Response $response) { With PSR-7 it is possible to inject objects/values into the request object for further processing. In your applications middleware often need to pass along information to your route closure and the way to do it is to add it to the request object via an attribute. -Example, Setting a value on your request object. +Example, setting a value on your request object. ```php use Psr\Http\Message\ServerRequestInterface as Request; diff --git a/docs/v4/objects/response.md b/docs/v4/objects/response.md index e3bd9e66..16567f3e 100644 --- a/docs/v4/objects/response.md +++ b/docs/v4/objects/response.md @@ -2,21 +2,19 @@ title: Response --- -Your Slim app's routes and middleware are given a PSR-7 response object that -represents the current HTTP response to be returned to the client. The response -object implements the [PSR-7 ResponseInterface][psr7] with which you can -inspect and manipulate the HTTP response status, headers, and body. +Your Slim app's routes and middleware are given a PSR-7 response object that represents the current HTTP response to be returned to the client. +The response object implements the [PSR-7 ResponseInterface][psr7] with which you can inspect and manipulate the HTTP response status, headers, and body. [psr7]: https://www.php-fig.org/psr/psr-7/#33-psrhttpmessageresponseinterface ## How to get the Response object -The PSR-7 response object is injected into your Slim application routes as the -second argument to the route callback like this: +The PSR-7 response object is injected into your Slim application routes as the second argument to the route callback like this:
```php run(); ## The Response Status -Every HTTP response has a numeric [status code][statuscodes]. The status code -identifies the _type_ of HTTP response to be returned to the client. The PSR-7 -Response object's default status code is `200` (OK). You can get the PSR-7 -Response object's status code with the `getStatusCode()` method like this. +Every HTTP response has a numeric [status code][statuscodes]. +The status code identifies the _type_ of HTTP response to be returned to the client. +The PSR-7 Response object's default status code is `200` (OK). +You can get the PSR-7 Response object's status code with the `getStatusCode()` method like this. [statuscodes]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html @@ -62,16 +60,13 @@ $newResponse = $response->withStatus(302); ## The Response Headers -Every HTTP response has headers. These are metadata that describe the HTTP -response but are not visible in the response's body. The PSR-7 -Response object provides several methods to inspect and manipulate its headers. +Every HTTP response has headers. +These are metadata that describe the HTTP response but are not visible in the response's body. The PSR-7 Response object provides several methods to inspect and manipulate its headers. ### Get All Headers -You can fetch all HTTP response headers as an associative array with the PSR-7 -Response object's `getHeaders()` method. The resultant associative array's keys -are the header names and its values are themselves a numeric array of string -values for their respective header name. +You can fetch all HTTP response headers as an associative array with the PSR-7 Response object's `getHeaders()` method. +The resultant associative array's keys are the header names and its values are themselves a numeric array of string values for their respective header name.
```php @@ -85,9 +80,9 @@ foreach ($headers as $name => $values) { ### Get One Header -You can get a single header's value(s) with the PSR-7 Response object's -`getHeader($name)` method. This returns an array of values for the given header -name. Remember, _a single HTTP header may have more than one value!_ +You can get a single header's value(s) with the PSR-7 Response object's `getHeader($name)` method. +This returns an array of values for the given header name. +Remember, _a single HTTP header may have more than one value!_
```php @@ -96,9 +91,8 @@ $headerValueArray = $response->getHeader('Vary');
Figure 6: Get values for a specific HTTP header.
-You may also fetch a comma-separated string with all values for a given header -with the PSR-7 Response object's `getHeaderLine($name)` method. Unlike the -`getHeader($name)` method, this method returns a comma-separated string. +You may also fetch a comma-separated string with all values for a given header with the PSR-7 Response object's `getHeaderLine($name)` method. +Unlike the `getHeader($name)` method, this method returns a comma-separated string.
```php @@ -109,8 +103,7 @@ $headerValueString = $response->getHeaderLine('Vary'); ### Detect Header -You can test for the presence of a header with the PSR-7 Response object's -`hasHeader($name)` method. +You can test for the presence of a header with the PSR-7 Response object's `hasHeader($name)` method.
```php @@ -123,8 +116,7 @@ if ($response->hasHeader('Vary')) { ### Set Header -You can set a header value with the PSR-7 Response object's -`withHeader($name, $value)` method. +You can set a header value with the PSR-7 Response object's `withHeader($name, $value)` method.
```php @@ -188,11 +180,9 @@ $newResponse = $oldResponse->withoutHeader('Allow'); An HTTP response typically has a body. -Just like the PSR-7 Request object, the PSR-7 Response object implements -the body as an instance of `Psr\Http\Message\StreamInterface`. You can get -the HTTP response body `StreamInterface` instance with the PSR-7 Response -object's `getBody()` method. The `getBody()` method is preferable if the -outgoing HTTP response length is unknown or too large for available memory. +Just like the PSR-7 Request object, the PSR-7 Response object implements the body as an instance of `Psr\Http\Message\StreamInterface`. +You can get the HTTP response body `StreamInterface` instance with the PSR-7 Response object's `getBody()` method. +The `getBody()` method is preferable if the outgoing HTTP response length is unknown or too large for available memory.
```php @@ -201,8 +191,7 @@ $body = $response->getBody();
Figure 12: Get HTTP response body
-The resultant `Psr\Http\Message\StreamInterface` instance provides the following -methods to read from, iterate, and write to its underlying PHP `resource`. +The resultant `Psr\Http\Message\StreamInterface` instance provides the following methods to read from, iterate, and write to its underlying PHP `resource`. * getSize() * tell() @@ -217,8 +206,8 @@ methods to read from, iterate, and write to its underlying PHP `resource`. * getContents() * getMetadata($key = null) -Most often, you'll need to write to the PSR-7 Response object. You can write -content to the `StreamInterface` instance with its `write()` method like this: +Most often, you'll need to write to the PSR-7 Response object. +You can write content to the `StreamInterface` instance with its `write()` method like this:
```php @@ -228,12 +217,10 @@ $body->write('Hello');
Figure 13: Write content to the HTTP response body
-You can also _replace_ the PSR-7 Response object's body with an entirely new -`StreamInterface` instance. This is particularly useful when you want to pipe -content from a remote destination (e.g. the filesystem or a remote API) into -the HTTP response. You can replace the PSR-7 Response object's body with -its `withBody(StreamInterface $body)` method. Its argument **MUST** be an -instance of `Psr\Http\Message\StreamInterface`. +You can also _replace_ the PSR-7 Response object's body with an entirely new `StreamInterface` instance. +This is particularly useful when you want to pipe content from a remote destination (e.g. the filesystem or a remote API) into the HTTP response. +You can replace the PSR-7 Response object's body with its `withBody(StreamInterface $body)` method. +Its argument **MUST** be an instance of `Psr\Http\Message\StreamInterface`.
```php diff --git a/docs/v4/start/installation.md b/docs/v4/start/installation.md index ae5308cf..404f1c37 100644 --- a/docs/v4/start/installation.md +++ b/docs/v4/start/installation.md @@ -9,14 +9,14 @@ title: Installation ## Step 1: Install Composer -Don't have Composer? It's easy to install by following the instructions on their [download](https://getcomposer.org/download/) page. +Don't have Composer? +It's easy to install by following the instructions on their [download](https://getcomposer.org/download/) page. ## Step 2: Install Slim We recommend you install Slim with [Composer](https://getcomposer.org/). -Navigate into your project's root directory and execute the bash command -shown below. This command downloads the Slim Framework and its third-party -dependencies into your project's `vendor/` directory. +Navigate into your project's root directory and execute the bash command shown below. +This command downloads the Slim Framework and its third-party dependencies into your project's `vendor/` directory. ```bash composer require slim/slim:"4.*" @@ -28,28 +28,34 @@ Before you can get up and running with Slim you will need to choose a PSR-7 impl In order for auto-detection to work and enable you to use `AppFactory::create()` and `App::run()` without having to manually create a `ServerRequest` you need to install one of the following implementations: ### [Slim PSR-7](https://github.com/slimphp/Slim-Psr7) + ```bash composer require slim/psr7 ``` ### [Nyholm PSR-7](https://github.com/Nyholm/psr7) and [Nyholm PSR-7 Server](https://github.com/Nyholm/psr7-server) + ```bash composer require nyholm/psr7 nyholm/psr7-server ``` ### [Guzzle PSR-7](https://github.com/guzzle/psr7) + #### For usage with Guzzle PSR-7 version 2: + ```bash composer require guzzlehttp/psr7 "^2" ``` #### For usage with Guzzle PSR-7 version 1: + ```bash composer require guzzlehttp/psr7 "^1" composer require sapphirecat/slim4-http-interop-adapter ``` ### [Laminas Diactoros](https://github.com/laminas/laminas-diactoros) + ```bash composer require laminas/laminas-diactoros ``` diff --git a/docs/v4/start/upgrade.md b/docs/v4/start/upgrade.md index 6e3d52ec..17ac4101 100644 --- a/docs/v4/start/upgrade.md +++ b/docs/v4/start/upgrade.md @@ -2,14 +2,16 @@ title: Upgrade Guide --- -If you are upgrading from version 3 to version 4, these are the significant changes that -you need to be aware of. +If you are upgrading from version 3 to version 4, these are the significant changes that you need to be aware of. ## PHP Version Requirement + Slim 4 requires **PHP 7.4 or newer**. ## Breaking changes to Slim\App constructor + Slim's App settings used to be a part of the container and they have now been decoupled from it. + ```php /** * Slim 3 App::__construct($container = []) @@ -32,13 +34,18 @@ $app = new App(...); ``` ## Removed App Settings + - `addContentLengthHeader` See [Content Length Middleware](/docs/v4/middleware/content-length.html) for new implementation of this setting. - `determineRouteBeforeAppMiddleware` Position [Routing Middleware](/docs/v4/middleware/routing.html) at the right position in your middleware stack to replicate existing behavior. - `outputBuffering` See [Output Buffering Middleware](/docs/v4/middleware/output-buffering.html) for new implementation of this setting. - `displayErrorDetails` See [Error Handling Middleware](/docs/v4/middleware/error-handling.html) for new implementation of this setting. ## Changes to Container -Slim no longer has a Container so you need to supply your own. If you were relying on request or response being in the container, then you need to either set them to a container yourself, or refactor. Also, `App::__call()` method has been removed, so accessing a container property via `$app->key_name()` no longer works. + +Slim no longer has a Container so you need to supply your own. +If you were relying on request or response being in the container, then you need to either set them to a container yourself, or refactor. +Also, `App::__call()` method has been removed, so accessing a container property via `$app->key_name()` no longer works. + ```php /** * Slim 3.x shipped with the Pimple container implementation and enabled the following syntax @@ -50,9 +57,9 @@ $container['view'] = function (\Psr\Container\ContainerInterface $container){ return new \Slim\Views\Twig(''); }; - /** - * Slim 4.x does not ship with a container library. It supports all PSR-11 implementations such as PHP-DI + * Slim 4.x does not ship with a container library. + * It supports all PSR-11 implementations such as PHP-DI. * To install PHP-DI `composer require php-di/php-di` */ @@ -70,20 +77,30 @@ $container->set('view', function(\Psr\Container\ContainerInterface $container){ ``` ## Changes to base path handling -Up to v3, Slim extracted the base path from the folder where the application was instantiated. This is no longer the case, and the base path must be explicitly declared [in case your application is not executed from the root of your domain](/docs/v4/start/web-servers.html#run-from-a-sub-directory): + +Up to v3, Slim extracted the base path from the folder where the application was instantiated. +This is no longer the case, and the base path must be explicitly declared [in case your application is not executed from the root of your domain](/docs/v4/start/web-servers.html#run-from-a-sub-directory): + ```php use Slim\Factory\AppFactory; + // ... + $app = AppFactory::create(); $app->setBasePath('/my-app-subpath'); + // ... + $app->run(); ``` ## Changes to Routing components -The `Router` component from Slim 3 has been split into multiple different components in order to decouple FastRoute from the `App` core and offer more flexibility to the end user. It has been split into -`RouteCollector`, `RouteParser` and `RouteResolver`. Those 3 components can all have their respective interfaces which you can implement on your own and inject into -the `App` constructor. The following pull requests offer a lot of insight on the public interfaces of these new components: + +The `Router` component from Slim 3 has been split into multiple different components in order to decouple FastRoute from the `App` core and offer more flexibility to the end user. +It has been split into `RouteCollector`, `RouteParser` and `RouteResolver`. +Those 3 components can all have their respective interfaces which you can implement on your own and inject into the `App` constructor. +The following pull requests offer a lot of insight on the public interfaces of these new components: + - [Pull Request #2604](https://github.com/slimphp/Slim/pull/2604) - [Pull Request #2622](https://github.com/slimphp/Slim/pull/2622) - [Pull Request #2639](https://github.com/slimphp/Slim/pull/2639) @@ -92,6 +109,7 @@ the `App` constructor. The following pull requests offer a lot of insight on the - [Pull Request #2642](https://github.com/slimphp/Slim/pull/2642) This also means that [Route Groups](/docs/v4/objects/routing.html#route-groups) have changed their signatures: + ```php $app->group('/user', function(\Slim\Routing\RouteCollectorProxy $app){ $app->get('', function() { /* ... */ }); @@ -100,27 +118,34 @@ $app->group('/user', function(\Slim\Routing\RouteCollectorProxy $app){ ``` ## New Middleware Approach -In Slim 4 we wanted to give more flexibility to the developers by decoupling some of Slim's App core functionality and implementing it as middleware. This gives you the ability to swap in custom implementations of the core components. + +In Slim 4 we wanted to give more flexibility to the developers by decoupling some of Slim's App core functionality and implementing it as middleware. +This gives you the ability to swap in custom implementations of the core components. ## Middleware Execution + Middleware execution has not changed and is still `Last In First Out (LIFO)` like in Slim 3. ## New App Factory -The `AppFactory` component was introduced to reduce some of the friction caused by decoupling the PSR-7 implementation from the `App` core. It detects which PSR-7 -implementation and ServerRequest creator is installed in your project root and enables you to instantiate an app via `AppFactory::create()` and use `App::run()` without -having to pass in a `ServerRequest` object. The following PSR-7 implementations and ServerRequest creator combos are supported: + +The `AppFactory` component was introduced to reduce some of the friction caused by decoupling the PSR-7 implementation from the `App` core. +It detects which PSR-7 implementation and ServerRequest creator is installed in your project root and enables you to instantiate an app via `AppFactory::create()` and use `App::run()` without having to pass in a `ServerRequest` object. +The following PSR-7 implementations and ServerRequest creator combos are supported: + - [Slim PSR-7](https://github.com/slimphp/Slim-Psr7) - [Nyholm PSR-7](https://github.com/Nyholm/psr7) and [Nyholm PSR-7 Server](https://github.com/Nyholm/psr7-server) - [Guzzle PSR-7](https://github.com/guzzle/psr7) and [Guzzle HTTP Factory](https://github.com/http-interop/http-factory-guzzle) - [Laminas Diactoros](https://github.com/laminas/laminas-diactoros) ## New Routing Middleware + The routing has been implemented as middleware. We are still using [FastRoute](https://github.com/nikic/FastRoute) for our routing needs. If you were using `determineRouteBeforeAppMiddleware`, you need to add the `Middleware\RoutingMiddleware` middleware to your application just before you call `run()` to maintain the previous behaviour. See [Pull Request #2288](https://github.com/slimphp/Slim/pull/2288) for more information. ```php run(); ``` ## New Error Handling Middleware + Error handling has also been implemented as middleware. See [Pull Request #2398](https://github.com/slimphp/Slim/pull/2398) for more information. + ```php run(); ## New Not Found- and Not Allowed Handler -The [404 Not Found Handler](http://www.slimframework.com/docs/v3/handlers/not-found.html) and -the [405 Not Allowed Handler](http://www.slimframework.com/docs/v3/handlers/not-allowed.html) from v3 -can be migrated as follows: +The [404 Not Found Handler](http://www.slimframework.com/docs/v3/handlers/not-found.html) and the [405 Not Allowed Handler](http://www.slimframework.com/docs/v3/handlers/not-allowed.html) from v3 can be migrated as follows: ```php setErrorHandler( ``` ## New Dispatcher & Routing Results + We created a wrapper around the FastRoute dispatcher which adds a result wrapper and access to a route's full list of allowed methods instead of only having access to those when an exception arises. The Request attribute `routeInfo` is now deprecated and replaced with `routingResults`. See [Pull Request #2405](https://github.com/slimphp/Slim/pull/2405) for more information. + ```php run(); ``` ## New Method Overriding Middleware + If you were overriding the HTTP method using either the custom header or the body param, you need to add the `Middleware\MethodOverrideMiddleware` middleware to be able to override the method like before. See [Pull Request #2329](https://github.com/slimphp/Slim/pull/2329) for more information. + ```php run(); ## New Content Length Middleware -The Content Length Middleware will automatically append a `Content-Length` header to the response. This is to replace the `addContentLengthHeader` setting that was removed from Slim 3. This middleware should be placed on the center of the middleware stack so it gets executed last. + +The Content Length Middleware will automatically append a `Content-Length` header to the response. +This is to replace the `addContentLengthHeader` setting that was removed from Slim 3. +This middleware should be placed on the center of the middleware stack so it gets executed last. + ```php run(); ``` ## New Output Buffering Middleware -The Output Buffering Middleware enables you to switch between two modes of output buffering: `APPEND` (default) and `PREPEND` mode. The `APPEND` mode will use the existing response body to append the content while `PREPEND` mode will create a new response body and append it to the existing response. This middleware should be placed on the center of the middleware stack so it gets executed last. + +The Output Buffering Middleware enables you to switch between two modes of output buffering: `APPEND` (default) and `PREPEND` mode. +The `APPEND` mode will use the existing response body to append the content while `PREPEND` mode will create a new response body and append it to the existing response. +This middleware should be placed on the center of the middleware stack so it gets executed last. + ```php run(); -``` +``` \ No newline at end of file diff --git a/docs/v4/start/web-servers.md b/docs/v4/start/web-servers.md index f230e9b7..72b83275 100644 --- a/docs/v4/start/web-servers.md +++ b/docs/v4/start/web-servers.md @@ -2,25 +2,24 @@ title: Web Servers --- -It is typical to use the front-controller pattern to funnel appropriate HTTP -requests received by your web server to a single PHP file. The instructions -below explain how to tell your web server to send HTTP requests to your PHP -front-controller file. +It is typical to use [the Front-Controller pattern][front-controller-pattern-url] to funnel appropriate HTTP requests received by your web server to a single PHP file. +The instructions below explain how to tell your web server to send HTTP requests to your PHP front-controller file. ## PHP built-in server -Run the following command in terminal to start localhost web server, -assuming `./public/` is public-accessible directory with `index.php` file: +Run the following command in terminal to start localhost web server, assuming *./public/* is public-accessible directory with *index.php* file: ```bash cd public/ php -S localhost:8888 ``` -If you are not using `index.php` as your entry point then change appropriately. +If you are not using *index.php* as your entry point then change appropriately. > **Warning:** The built-in web server was designed to aid application development. -It may also be useful for testing purposes or for application demonstrations that are run in controlled environments. It is not intended to be a full-featured web server. It should not be used on a public network. +It may also be useful for testing purposes or for application demonstrations that are run in controlled environments. +It is not intended to be a full-featured web server. +It should not be used on a public network. ## Apache configuration @@ -32,8 +31,8 @@ sudo a2enmod rewrite sudo a2enmod actions ``` -Ensure your `.htaccess` and `index.php` files are in the same -public-accessible directory. The `.htaccess` file should contain this code: +Ensure your `.htaccess` and `index.php` files are in the same public-accessible directory. +The `.htaccess` file should contain this code: ```bash RewriteEngine On @@ -42,9 +41,7 @@ RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^ index.php [QSA,L] ``` -To ensure that the `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: +To ensure that the `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: ```bash RewriteEngine on @@ -54,9 +51,8 @@ RewriteRule (.*) public/$1 [L] These `.htaccess` files require URL rewriting. -Make sure to enable Apache's `mod_rewrite` module and your virtual host is configured -with the `AllowOverride` option so that the `.htaccess` rewrite rules can be used: -To do this, the file `/etc/apache2/apache2.conf` must be opened in an editor with root privileges. +Make sure to enable Apache's `mod_rewrite` module and your virtual host is configured with the `AllowOverride` option so that the `.htaccess` rewrite rules can be used: +To do this, the file */etc/apache2/apache2.conf* must be opened in an editor with root privileges. Change the `` directive from `AllowOveride None` to `AllowOveride All`. @@ -78,16 +74,13 @@ sudo service apache2 restart ``` This command works on most Debian/Ubuntu variants. -For all other Linux distributions, please consult -the documentation of your specific Linux distribution -to find out how to restart Apache. +For all other Linux distributions, please consult the documentation of your specific Linux distribution to find out how to restart Apache. **Running in a sub-directory** This example assumes that the front controller is located in `public/index.php`. -To "redirect" the sub-directory to the front-controller create a second -`.htaccess` file above the `public/` directory. +To "redirect" the sub-directory to the front-controller create a second `.htaccess` file above the `public/` directory. The second `.htaccess` file should contain this code: @@ -97,8 +90,7 @@ RewriteRule ^$ public/ [L] RewriteRule (.*) public/$1 [L] ``` -You may also set the base path so that the router can -match the URL from the browser with the path set in the route registration. +You may also set the base path so that the router can match the URL from the browser with the path set in the route registration. This is done with the `setBasePath()` method. ```php @@ -113,11 +105,8 @@ $app->setBasePath('/myapp'); ## Nginx configuration This is an example Nginx virtual host configuration for the domain `example.com`. -It listens for inbound HTTP connections on port 80. It assumes a PHP-FPM server -is running on port 9123. You should update the `server_name`, `error_log`, -`access_log`, and `root` directives with your own values. The `root` directive -is the path to your application's public document root directory; your Slim app's -`index.php` front-controller file should be in this directory. +It listens for inbound HTTP connections on port 80. It assumes a PHP-FPM server is running on port 9123. You should update the `server_name`, `error_log`, `access_log`, and `root` directives with your own values. +The `root` directive is the path to your application's public document root directory; your Slim app's `index.php` front-controller file should be in this directory. ```bash server { @@ -150,6 +139,7 @@ The Caddy configuration is located in `/etc/caddy/Caddyfile`. Caddy requires `ph Assuming the FPM socket is at `/var/run/php/php-fpm.sock`, and your application is located in `/var/www`, the following configuration should work out of the box. ### HTTP configuration listening for any request + ```bash :80 { # Set-up the FCGI location @@ -160,6 +150,7 @@ Assuming the FPM socket is at `/var/run/php/php-fpm.sock`, and your application ``` ### HTTPS configuration with self-signed certificate + ```bash :443 { tls internal @@ -206,10 +197,8 @@ This assumes that Slim's `index.php` is in the root folder of your project (www ## Run From a Sub-Directory -If you want to run your Slim Application from a sub-directory in your Server's Root instead of creating a Virtual Host, -you can configure `$app->setBasePath('/path-to-your-app');` right after the `AppFactory::create();`. -Assuming that your Server's Root is `/var/www/html/` and path to your Slim Application is `/var/www/html/my-slim-app` -you can set the base path to `$app->setBasePath('/my-slim-app');`. +If you want to run your Slim Application from a sub-directory in your Server's Root instead of creating a Virtual Host, you can configure `$app->setBasePath('/path-to-your-app');` right after the `AppFactory::create();`. +Assuming that your Server's Root is `/var/www/html/` and path to your Slim Application is `/var/www/html/my-slim-app` you can set the base path to `$app->setBasePath('/my-slim-app');`. ```php setBasePath('/my-slim-app'); $app->run(); ``` + +[front-controller-pattern-url]: https://martinfowler.com/eaaCatalog/frontController.html \ No newline at end of file