Skip to content

Commit fb6b8a2

Browse files
authored
5.x - Refactor internals to improve routing and middleware handling
1 parent 626bbbd commit fb6b8a2

File tree

107 files changed

+1985
-2471
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

107 files changed

+1985
-2471
lines changed

.cs.php

Lines changed: 42 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -9,70 +9,74 @@
99
[
1010
'@PSR1' => true,
1111
'@PSR2' => true,
12-
'@Symfony' => true,
13-
'psr_autoloading' => true,
14-
// custom rules
15-
'align_multiline_comment' => ['comment_type' => 'phpdocs_only'], // psr-5
16-
'phpdoc_to_comment' => false,
17-
'no_superfluous_phpdoc_tags' => false,
12+
'align_multiline_comment' => ['comment_type' => 'phpdocs_only'],
1813
'array_indentation' => true,
1914
'array_syntax' => ['syntax' => 'short'],
15+
'blank_line_between_import_groups' => true,
2016
'cast_spaces' => ['space' => 'none'],
21-
'concat_space' => ['spacing' => 'one'],
17+
'class_definition' => [
18+
'space_before_parenthesis' => true,
19+
],
2220
'compact_nullable_type_declaration' => true,
23-
'declare_equal_normalize' => ['space' => 'single'],
21+
'concat_space' => ['spacing' => 'one'],
22+
'declare_equal_normalize' => ['space' => 'none'],
23+
'declare_strict_types' => false,
24+
'echo_tag_syntax' => ['format' => 'long'],
25+
'fully_qualified_strict_types' => true,
26+
'function_declaration' => [
27+
'closure_fn_spacing' => 'none',
28+
],
2429
'general_phpdoc_annotation_remove' => [
2530
'annotations' => [
2631
'author',
2732
'package',
2833
],
2934
],
35+
'global_namespace_import' => [
36+
'import_classes' => true,
37+
'import_constants' => null,
38+
'import_functions' => null,
39+
],
3040
'increment_style' => ['style' => 'post'],
3141
'list_syntax' => ['syntax' => 'short'],
32-
'echo_tag_syntax' => ['format' => 'long'],
33-
'phpdoc_add_missing_param_annotation' => ['only_untyped' => false],
34-
'phpdoc_align' => false,
35-
'phpdoc_no_empty_return' => false,
36-
'phpdoc_order' => true, // psr-5
37-
'phpdoc_no_useless_inheritdoc' => false,
38-
'protected_to_private' => false,
39-
'yoda_style' => false,
4042
'method_argument_space' => ['on_multiline' => 'ensure_fully_multiline'],
41-
'ordered_imports' => [
42-
'sort_algorithm' => 'alpha',
43-
'imports_order' => ['class', 'function', 'const'],
44-
],
45-
'single_line_throw' => false,
46-
'declare_strict_types' => false,
47-
'blank_line_between_import_groups' => true,
48-
'fully_qualified_strict_types' => true,
4943
'no_null_property_initialization' => false,
44+
'no_superfluous_phpdoc_tags' => false,
45+
'no_unused_imports' => true,
5046
'nullable_type_declaration_for_default_null_value' => false,
5147
'operator_linebreak' => [
5248
'only_booleans' => true,
5349
'position' => 'beginning',
5450
],
55-
'global_namespace_import' => [
56-
'import_classes' => true,
57-
'import_constants' => null,
58-
'import_functions' => null
51+
'ordered_imports' => [
52+
'sort_algorithm' => 'alpha',
53+
'imports_order' => ['class', 'function', 'const'],
5954
],
60-
'class_definition' => [
61-
'space_before_parenthesis' => true,
55+
'phpdoc_add_missing_param_annotation' => ['only_untyped' => false],
56+
'phpdoc_align' => false,
57+
'phpdoc_no_empty_return' => false,
58+
'phpdoc_no_useless_inheritdoc' => false,
59+
'phpdoc_order' => true,
60+
'phpdoc_to_comment' => false,
61+
'protected_to_private' => false,
62+
'psr_autoloading' => true,
63+
'single_line_throw' => false,
64+
'trailing_comma_in_multiline' => [
65+
'after_heredoc' => true,
66+
'elements' => ['array_destructuring', 'arrays', 'match'],
67+
],
68+
'yoda_style' => [
69+
'equal' => false,
70+
'identical' => false,
71+
'less_and_greater' => false,
6272
],
63-
'declare_equal_normalize' => false,
64-
'phpdoc_summary' => false,
65-
'phpdoc_add_missing_param_annotation' => false,
66-
'no_useless_concat_operator' => false,
67-
'fully_qualified_strict_types' => false,
68-
'trailing_comma_in_multiline' => ['elements' => ['arrays']],
69-
]
73+
],
7074
)
7175
->setFinder(
7276
PhpCsFixer\Finder::create()
7377
->in(__DIR__ . '/Slim')
7478
->in(__DIR__ . '/tests')
7579
->name('*.php')
7680
->ignoreDotFiles(true)
77-
->ignoreVCS(true)
81+
->ignoreVCS(true),
7882
);

.github/workflows/tests.yml

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,14 @@ jobs:
1616
strategy:
1717
fail-fast: false
1818
matrix:
19-
php: [ 8.2, 8.3, 8.4 ]
19+
php: [ 8.2, 8.3, 8.4, 8.5 ]
2020
include:
21-
- php: 8.2
21+
- php: 8.4
2222
analysis: true
2323

2424
steps:
2525
- name: Checkout
26-
uses: actions/checkout@v4
26+
uses: actions/checkout@v6
2727

2828
- name: Set up PHP ${{ matrix.php }}
2929
uses: shivammathur/setup-php@v2
@@ -37,9 +37,6 @@ jobs:
3737
- name: Coding standards
3838
run: composer cs:check
3939

40-
- name: Code sniffer
41-
run: composer sniffer:check
42-
4340
- name: Static analysis
4441
run: composer stan
4542

CHANGELOG.md

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111

1212
#### New Features
1313

14-
- New `AppBuilder` to create a Slim App instance for different scenarios. Replaces the `AppFactory`.
1514
- Unified DI container resolution. All the factory logic has been removed and moved to the DI container. This reduces the internal complexity by delegating the building logic into the DI container.
1615
- Provide FIFO (first in, first out) middleware order support. LIFO is not supported anymore.
1716
- Optimized internal routing concept for better separation of concern and flexibility.
@@ -73,7 +72,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7372

7473
### Added
7574

76-
- `Slim/Builder/AppBuilder.php`: Introduced to replace `Slim/Factory/AppFactory.php`.
7775
- `Slim/Container/CallableResolver.php`: New implementation of the Callable Resolver.
7876
- `Slim/Container/DefaultDefinitions.php`: Default container definitions.
7977
- `Slim/Handlers/ExceptionHandler.php`: New Exception Handler for better error handling.
@@ -115,7 +113,6 @@ New files for routing, middleware, and factories, including:
115113

116114
- `Slim/CallableResolver.php`
117115
- `Slim/Handlers/ErrorHandler.php`
118-
- `Slim/Factory/AppFactory.php` and related `Psr17` factories.
119116
- `Slim/Interfaces/AdvancedCallableResolverInterface.php`
120117
- `Slim/Interfaces/RouteCollectorInterface.php`,
121118
- `RouteCollectorProxyInterface.php`,

README.md

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,16 +56,15 @@ Then create file `public/index.php`.
5656

5757
use Psr\Http\Message\ResponseInterface as Response;
5858
use Psr\Http\Message\ServerRequestInterface as Request;
59-
use Slim\Builder\AppBuilder;
59+
use Slim\Factory\AppFactory;
6060
use Slim\Middleware\EndpointMiddleware;
6161
use Slim\Middleware\ExceptionHandlingMiddleware;
6262
use Slim\Middleware\RoutingMiddleware;
6363

6464
require __DIR__ . '/../vendor/autoload.php';
6565

66-
// Instantiate App using the builder
67-
$builder = new AppBuilder();
68-
$app = $builder->build();
66+
// Instantiate the App
67+
$app = AppFactory::build();
6968

7069
// Add middleware
7170
$app->add(ExceptionHandlingMiddleware::class);

Slim/App.php

Lines changed: 49 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,16 @@
1616
use Psr\Http\Server\MiddlewareInterface;
1717
use Psr\Http\Server\RequestHandlerInterface;
1818
use Slim\Interfaces\EmitterInterface;
19-
use Slim\Interfaces\RouteCollectionInterface;
19+
use Slim\Interfaces\RouterInterface;
2020
use Slim\Interfaces\ServerRequestCreatorInterface;
21-
use Slim\RequestHandler\MiddlewareRequestHandler;
21+
use Slim\Middleware\EndpointMiddleware;
22+
use Slim\Middleware\ErrorExceptionMiddleware;
23+
use Slim\Middleware\HtmlExceptionMiddleware;
24+
use Slim\Middleware\JsonExceptionMiddleware;
25+
use Slim\Middleware\RoutingMiddleware;
2226
use Slim\Routing\Route;
2327
use Slim\Routing\RouteCollectionTrait;
2428
use Slim\Routing\RouteGroup;
25-
use Slim\Routing\Router;
2629

2730
/**
2831
* App
@@ -31,11 +34,9 @@
3134
* running the application. It provides methods for defining routes, adding middleware, and managing
3235
* the application's lifecycle, including handling HTTP requests and emitting responses.
3336
*
34-
* @template TContainerInterface of (ContainerInterface|null)
35-
*
3637
* @api
3738
*/
38-
class App implements RequestHandlerInterface, RouteCollectionInterface
39+
class App implements RequestHandlerInterface
3940
{
4041
use RouteCollectionTrait;
4142

@@ -64,7 +65,7 @@ class App implements RequestHandlerInterface, RouteCollectionInterface
6465
/**
6566
* The router instance for handling route definitions and matching.
6667
*/
67-
private Router $router;
68+
private RouterInterface $router;
6869

6970
/**
7071
* The emitter instance for sending the HTTP response to the client.
@@ -84,14 +85,12 @@ public function __construct(ContainerInterface $container)
8485
$this->container = $container;
8586
$this->serverRequestCreator = $container->get(ServerRequestCreatorInterface::class);
8687
$this->requestHandler = $container->get(RequestHandlerInterface::class);
87-
$this->router = $container->get(Router::class);
88+
$this->router = $container->get(RouterInterface::class);
8889
$this->emitter = $container->get(EmitterInterface::class);
8990
}
9091

9192
/**
9293
* Get the dependency injection container.
93-
*
94-
* @return ContainerInterface The DI container instance
9594
*/
9695
public function getContainer(): ContainerInterface
9796
{
@@ -101,7 +100,7 @@ public function getContainer(): ContainerInterface
101100
/**
102101
* Define a new route with the specified HTTP methods and URI pattern.
103102
*
104-
* @param array $methods The HTTP methods the route should respond to
103+
* @param array<string> $methods The HTTP methods the route should respond to
105104
* @param string $path The URI pattern for the route
106105
* @param callable|string $handler The route handler callable or controller method
107106
*
@@ -125,22 +124,9 @@ public function group(string $path, callable $handler): RouteGroup
125124
return $this->router->group($path, $handler);
126125
}
127126

128-
/**
129-
* Get the base path used for routing.
130-
*
131-
* @return string The base path used for routing
132-
*/
133-
public function getBasePath(): string
134-
{
135-
return $this->router->getBasePath();
136-
}
137-
138127
/**
139128
* Set the base path used for routing.
140-
*
141-
* @param string $basePath The base path to use for routing
142-
*
143-
* @return self The current App instance for method chaining
129+
* @param string $basePath
144130
*/
145131
public function setBasePath(string $basePath): self
146132
{
@@ -149,8 +135,17 @@ public function setBasePath(string $basePath): self
149135
return $this;
150136
}
151137

138+
/**
139+
* Get the base path used for routing.
140+
*/
141+
public function getBasePath(): string
142+
{
143+
return $this->router->getBasePath();
144+
}
145+
152146
/**
153147
* Add a new middleware to the stack.
148+
* @param MiddlewareInterface|callable|string $middleware
154149
*/
155150
public function add(MiddlewareInterface|callable|string $middleware): self
156151
{
@@ -161,10 +156,7 @@ public function add(MiddlewareInterface|callable|string $middleware): self
161156

162157
/**
163158
* Add a new middleware to the application's middleware stack.
164-
*
165-
* @param MiddlewareInterface $middleware The middleware to add
166-
*
167-
* @return self The current App instance for method chaining
159+
* @param MiddlewareInterface $middleware
168160
*/
169161
public function addMiddleware(MiddlewareInterface $middleware): self
170162
{
@@ -173,42 +165,56 @@ public function addMiddleware(MiddlewareInterface $middleware): self
173165
return $this;
174166
}
175167

168+
/**
169+
* Add routing middleware.
170+
*
171+
* @return self
172+
*/
173+
public function addRoutingMiddleware(): self
174+
{
175+
return $this
176+
->add(RoutingMiddleware::class)
177+
->add(EndpointMiddleware::class);
178+
}
179+
180+
/**
181+
* Add set of default error handling middleware.
182+
*
183+
* @return self
184+
*/
185+
public function addErrorMiddleware(): self
186+
{
187+
return $this
188+
->add(ErrorExceptionMiddleware::class)
189+
->add(HtmlExceptionMiddleware::class)
190+
->add(JsonExceptionMiddleware::class);
191+
}
192+
176193
/**
177194
* Run the Slim application.
178195
*
179196
* This method traverses the application's middleware stack, processes the incoming HTTP request,
180197
* and emits the resultant HTTP response to the client.
181-
*
182-
* @param ServerRequestInterface|null $request The HTTP request to handle.
183-
* If null, it creates a request from globals.
184-
*
185-
* @return void
198+
* @param ?ServerRequestInterface $request
186199
*/
187200
public function run(?ServerRequestInterface $request = null): void
188201
{
189202
if (!$request) {
190203
$request = $this->serverRequestCreator->createServerRequestFromGlobals();
191204
}
192205

193-
$response = $this->handle($request);
194-
195-
$this->emitter->emit($response);
206+
$this->emitter->emit($this->handle($request));
196207
}
197208

198209
/**
199210
* Handle an incoming HTTP request.
200211
*
201212
* This method processes the request through the application's middleware stack and router,
202213
* returning the resulting HTTP response.
203-
*
204-
* @param ServerRequestInterface $request The HTTP request to handle
205-
*
206-
* @return ResponseInterface The HTTP response
214+
* @param ServerRequestInterface $request
207215
*/
208216
public function handle(ServerRequestInterface $request): ResponseInterface
209217
{
210-
$request = $request->withAttribute(MiddlewareRequestHandler::MIDDLEWARE, $this->router->getMiddlewareStack());
211-
212218
return $this->requestHandler->handle($request);
213219
}
214220
}

0 commit comments

Comments
 (0)