diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index cd83ec5e..2d0533e9 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -10,10 +10,10 @@ jobs: strategy: fail-fast: false matrix: - php: [7.4, 8.0, 8.1, 8.2] + php: [8.2, 8.3] experimental: [false] include: - - php: 8.1 + - php: 8.3 analysis: true steps: diff --git a/README.md b/README.md index 63f99725..09681f18 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ This skeleton application was built for Composer. This makes setting up a new Sl ## Install the Application -Run this command from the directory in which you want to install your new Slim Framework application. You will require PHP 7.4 or newer. +Run this command from the directory in which you want to install your new Slim Framework application. You will require PHP 8.3 or newer. ```bash composer create-project slim/slim-skeleton [my-app-name] diff --git a/composer.json b/composer.json index b74219b9..37a3f127 100644 --- a/composer.json +++ b/composer.json @@ -22,7 +22,7 @@ } ], "require": { - "php": "^7.4 || ^8.0", + "php": "^8.2", "ext-json": "*", "monolog/monolog": "^2.9", "php-di/php-di": "^6.4", diff --git a/public/index.php b/public/index.php index bc583c82..75a37322 100644 --- a/public/index.php +++ b/public/index.php @@ -16,7 +16,7 @@ $containerBuilder = new ContainerBuilder(); if (false) { // Should be set to true in production - $containerBuilder->enableCompilation(__DIR__ . '/../var/cache'); + $containerBuilder->enableCompilation(__DIR__ . '/../var/cache'); } // Set up settings diff --git a/src/Application/Actions/Action.php b/src/Application/Actions/Action.php index 1021c202..bd146cbb 100644 --- a/src/Application/Actions/Action.php +++ b/src/Application/Actions/Action.php @@ -13,17 +13,17 @@ abstract class Action { - protected LoggerInterface $logger; - protected Request $request; protected Response $response; + /** + * @var array + */ protected array $args; - public function __construct(LoggerInterface $logger) + public function __construct(protected LoggerInterface $logger) { - $this->logger = $logger; } /** @@ -49,10 +49,7 @@ public function __invoke(Request $request, Response $response, array $args): Res */ abstract protected function action(): Response; - /** - * @return array|object - */ - protected function getFormData() + protected function getFormData(): array|object|null { return $this->request->getParsedBody(); } @@ -70,10 +67,7 @@ protected function resolveArg(string $name) return $this->args[$name]; } - /** - * @param array|object|null $data - */ - protected function respondWithData($data = null, int $statusCode = 200): Response + protected function respondWithData(array|object|null $data = null, int $statusCode = 200): Response { $payload = new ActionPayload($statusCode, $data); @@ -87,6 +81,6 @@ protected function respond(ActionPayload $payload): Response return $this->response ->withHeader('Content-Type', 'application/json') - ->withStatus($payload->getStatusCode()); + ->withStatus($payload->statusCode); } } diff --git a/src/Application/Actions/ActionError.php b/src/Application/Actions/ActionError.php index 3a81cc53..8b36f36c 100644 --- a/src/Application/Actions/ActionError.php +++ b/src/Application/Actions/ActionError.php @@ -18,36 +18,10 @@ class ActionError implements JsonSerializable public const VALIDATION_ERROR = 'VALIDATION_ERROR'; public const VERIFICATION_ERROR = 'VERIFICATION_ERROR'; - private string $type; - - private ?string $description; - - public function __construct(string $type, ?string $description = null) - { - $this->type = $type; - $this->description = $description; - } - - public function getType(): string - { - return $this->type; - } - - public function setType(string $type): self - { - $this->type = $type; - return $this; - } - - public function getDescription(): ?string - { - return $this->description; - } - - public function setDescription(?string $description = null): self - { - $this->description = $description; - return $this; + public function __construct( + public readonly string $type, + public readonly ?string $description = null + ) { } #[\ReturnTypeWillChange] diff --git a/src/Application/Actions/ActionPayload.php b/src/Application/Actions/ActionPayload.php index cbf51104..6137e4a2 100644 --- a/src/Application/Actions/ActionPayload.php +++ b/src/Application/Actions/ActionPayload.php @@ -8,41 +8,11 @@ class ActionPayload implements JsonSerializable { - private int $statusCode; - - /** - * @var array|object|null - */ - private $data; - - private ?ActionError $error; - public function __construct( - int $statusCode = 200, - $data = null, - ?ActionError $error = null + public readonly int $statusCode = 200, + public readonly array|object|null $data = null, + public ?ActionError $error = null ) { - $this->statusCode = $statusCode; - $this->data = $data; - $this->error = $error; - } - - public function getStatusCode(): int - { - return $this->statusCode; - } - - /** - * @return array|null|object - */ - public function getData() - { - return $this->data; - } - - public function getError(): ?ActionError - { - return $this->error; } #[\ReturnTypeWillChange] diff --git a/src/Application/Actions/User/UserAction.php b/src/Application/Actions/User/UserAction.php index 4ea2d8ca..dbc7ae8f 100644 --- a/src/Application/Actions/User/UserAction.php +++ b/src/Application/Actions/User/UserAction.php @@ -10,11 +10,10 @@ abstract class UserAction extends Action { - protected UserRepository $userRepository; - - public function __construct(LoggerInterface $logger, UserRepository $userRepository) - { + public function __construct( + LoggerInterface $logger, + protected UserRepository $userRepository + ) { parent::__construct($logger); - $this->userRepository = $userRepository; } } diff --git a/src/Application/Handlers/HttpErrorHandler.php b/src/Application/Handlers/HttpErrorHandler.php index 64e02b1e..275bbad9 100644 --- a/src/Application/Handlers/HttpErrorHandler.php +++ b/src/Application/Handlers/HttpErrorHandler.php @@ -26,27 +26,25 @@ protected function respond(): Response { $exception = $this->exception; $statusCode = 500; - $error = new ActionError( - ActionError::SERVER_ERROR, - 'An internal error has occurred while processing your request.' - ); + $errorType = ActionError::SERVER_ERROR; + $description = 'An internal error has occurred while processing your request.'; if ($exception instanceof HttpException) { $statusCode = $exception->getCode(); - $error->setDescription($exception->getMessage()); + $description = $exception->getMessage(); if ($exception instanceof HttpNotFoundException) { - $error->setType(ActionError::RESOURCE_NOT_FOUND); + $errorType = ActionError::RESOURCE_NOT_FOUND; } elseif ($exception instanceof HttpMethodNotAllowedException) { - $error->setType(ActionError::NOT_ALLOWED); + $errorType = ActionError::NOT_ALLOWED; } elseif ($exception instanceof HttpUnauthorizedException) { - $error->setType(ActionError::UNAUTHENTICATED); + $errorType = ActionError::UNAUTHENTICATED; } elseif ($exception instanceof HttpForbiddenException) { - $error->setType(ActionError::INSUFFICIENT_PRIVILEGES); + $errorType = ActionError::INSUFFICIENT_PRIVILEGES; } elseif ($exception instanceof HttpBadRequestException) { - $error->setType(ActionError::BAD_REQUEST); + $errorType = ActionError::BAD_REQUEST; } elseif ($exception instanceof HttpNotImplementedException) { - $error->setType(ActionError::NOT_IMPLEMENTED); + $errorType = ActionError::NOT_IMPLEMENTED; } } @@ -55,9 +53,10 @@ protected function respond(): Response && $exception instanceof Throwable && $this->displayErrorDetails ) { - $error->setDescription($exception->getMessage()); + $description = $exception->getMessage(); } + $error = new ActionError($errorType, $description); $payload = new ActionPayload($statusCode, null, $error); $encodedPayload = json_encode($payload, JSON_PRETTY_PRINT); diff --git a/src/Application/Handlers/ShutdownHandler.php b/src/Application/Handlers/ShutdownHandler.php index 72b6d46e..2f9b58eb 100644 --- a/src/Application/Handlers/ShutdownHandler.php +++ b/src/Application/Handlers/ShutdownHandler.php @@ -10,20 +10,11 @@ class ShutdownHandler { - private Request $request; - - private HttpErrorHandler $errorHandler; - - private bool $displayErrorDetails; - public function __construct( - Request $request, - HttpErrorHandler $errorHandler, - bool $displayErrorDetails + private Request $request, + private HttpErrorHandler $errorHandler, + private bool $displayErrorDetails ) { - $this->request = $request; - $this->errorHandler = $errorHandler; - $this->displayErrorDetails = $displayErrorDetails; } public function __invoke() @@ -47,7 +38,10 @@ public function __invoke() $responseEmitter->emit($response); } - private function getErrorMessage(array $error): string + /** + * @param array{type: int, message: string, file: string, line: int} $error + */ + private function getErrorMessage(array $error = null): string { if (!$this->displayErrorDetails) { return 'An error while processing your request. Please try again later.'; @@ -58,18 +52,10 @@ private function getErrorMessage(array $error): string $errorMessage = $error['message']; $errorType = $error['type']; - if ($errorType === E_USER_ERROR) { - return "FATAL ERROR: {$errorMessage}. on line {$errorLine} in file {$errorFile}."; - } - - if ($errorType === E_USER_WARNING) { - return "WARNING: {$errorMessage}"; - } - - if ($errorType === E_USER_NOTICE) { - return "NOTICE: {$errorMessage}"; - } - - return "FATAL ERROR: {$errorMessage}. on line {$errorLine} in file {$errorFile}."; + return match ($errorType) { + E_USER_WARNING => "WARNING: {$errorMessage}", + E_USER_NOTICE => "NOTICE: {$errorMessage}", + default => "FATAL ERROR: {$errorMessage}. on line {$errorLine} in file {$errorFile}." + }; } } diff --git a/src/Application/Settings/Settings.php b/src/Application/Settings/Settings.php index 6da55e4e..40017532 100644 --- a/src/Application/Settings/Settings.php +++ b/src/Application/Settings/Settings.php @@ -6,18 +6,16 @@ class Settings implements SettingsInterface { - private array $settings; - - public function __construct(array $settings) + /** + * @param array $settings + */ + public function __construct(private array $settings) { $this->settings = $settings; } - /** - * @return mixed - */ - public function get(string $key = '') + public function get(string $key = ''): mixed { - return (empty($key)) ? $this->settings : $this->settings[$key]; + return empty($key) ? $this->settings : $this->settings[$key]; } } diff --git a/src/Application/Settings/SettingsInterface.php b/src/Application/Settings/SettingsInterface.php index 557d98b8..7867c592 100644 --- a/src/Application/Settings/SettingsInterface.php +++ b/src/Application/Settings/SettingsInterface.php @@ -6,9 +6,5 @@ interface SettingsInterface { - /** - * @param string $key - * @return mixed - */ - public function get(string $key = ''); + public function get(string $key = ''): mixed; } diff --git a/src/Domain/User/User.php b/src/Domain/User/User.php index 217bb9eb..e01e8366 100644 --- a/src/Domain/User/User.php +++ b/src/Domain/User/User.php @@ -8,17 +8,18 @@ class User implements JsonSerializable { - private ?int $id; - private string $username; private string $firstName; private string $lastName; - public function __construct(?int $id, string $username, string $firstName, string $lastName) - { - $this->id = $id; + public function __construct( + private int|null $id, + string $username, + string $firstName, + string $lastName + ) { $this->username = strtolower($username); $this->firstName = ucfirst($firstName); $this->lastName = ucfirst($lastName);