From 4e5b7907fd2524ffe441f2ae72f0dbfb244d1b1a Mon Sep 17 00:00:00 2001
From: Arman <407448+armanist@users.noreply.github.com>
Date: Fri, 23 Oct 2026 21:32:03 +0400
Subject: [PATCH 1/2] [#208] Require PHP 8.1 and test on PHP 8.1 to 8.3
---
.github/workflows/php.yml | 2 +-
CHANGELOG.md | 1 +
README.md | 2 +-
composer.json | 2 +-
phpstan.neon.dist | 2 +-
rector.php | 2 +-
6 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml
index f5a1a64..305016a 100644
--- a/.github/workflows/php.yml
+++ b/.github/workflows/php.yml
@@ -14,7 +14,7 @@ jobs:
strategy:
matrix:
operating-system: [ ubuntu-latest ]
- php-versions: ['8.0', '8.1', '8.2' ]
+ php-versions: ['8.1', '8.2', '8.3']
runs-on: ${{ matrix.operating-system }}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7a01445..877625d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -17,6 +17,7 @@ The format is based on Keep a Changelog and this project adheres to Semantic Ver
- `shared/config/lang.php` uses the 3.1 Lang format: `default` adapter (`file`, `deepl` or `google_translate`), `default_locale` and a section per remote adapter.
- `save_remote_image()` uses the fluent `httpRequest()` helper.
- CI runs `composer rector:check` after PHPStan.
+- **Breaking:** the minimum PHP version is 8.1 (`composer.json`, README, PHPStan `phpVersion` and the Rector level set), and CI runs on PHP 8.1, 8.2 and 8.3, following the framework (quantum-php/framework#595).
### Removed
- The `Hook`, `Loader` and `libraries/` leftovers: the `hooks/` and `libraries/` folders, `shared/config/hooks.php` and the hooks and loader entries in the dependencies config.
diff --git a/README.md b/README.md
index c489ea4..3fcb952 100644
--- a/README.md
+++ b/README.md
@@ -32,7 +32,7 @@
Installation
-Requirements: PHP 8.0 or newer.
+Requirements: PHP 8.1 or newer.
1. Create new project
diff --git a/composer.json b/composer.json
index d1c01f7..0d88aa5 100644
--- a/composer.json
+++ b/composer.json
@@ -25,7 +25,7 @@
},
"type": "project",
"require": {
- "php": "^8.0",
+ "php": "^8.1",
"quantum/framework": "dev-master",
"fakerphp/faker": "^1.15",
"bluemmb/faker-picsum-photos-provider": "^2.0",
diff --git a/phpstan.neon.dist b/phpstan.neon.dist
index 4fc4a06..6870cdb 100644
--- a/phpstan.neon.dist
+++ b/phpstan.neon.dist
@@ -1,5 +1,5 @@
parameters:
- phpVersion: 80000
+ phpVersion: 80100
level: 5
paths:
- shared
diff --git a/rector.php b/rector.php
index cacb402..6a2a654 100644
--- a/rector.php
+++ b/rector.php
@@ -20,7 +20,7 @@
ClassPropertyAssignToConstructorPromotionRector::class,
])
->withSets([
- LevelSetList::UP_TO_PHP_80,
+ LevelSetList::UP_TO_PHP_81,
SetList::TYPE_DECLARATION,
])
->withRules([
From 8fc2532933ac98a8c8275f627f1983e4be27cb1b Mon Sep 17 00:00:00 2001
From: Arman <407448+armanist@users.noreply.github.com>
Date: Fri, 23 Oct 2026 21:41:04 +0400
Subject: [PATCH 2/2] [#208] Apply the Rector PHP 8.1 level set to the project
code
---
CHANGELOG.md | 1 +
helpers/functions.php | 2 +-
shared/Commands/CommentCreateCommand.php | 2 +-
shared/Commands/DemoCommand.php | 2 +-
shared/DTOs/CommentDTO.php | 6 +++---
shared/DTOs/PostDTO.php | 10 +++++-----
shared/DTOs/UserDTO.php | 14 +++++++-------
shared/Services/AuthService.php | 2 +-
shared/Services/CommentService.php | 2 +-
shared/Services/PostService.php | 2 +-
shared/Transformers/CommentTransformer.php | 2 +-
shared/Transformers/PostTransformer.php | 2 +-
12 files changed, 24 insertions(+), 23 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 877625d..fee6414 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -17,6 +17,7 @@ The format is based on Keep a Changelog and this project adheres to Semantic Ver
- `shared/config/lang.php` uses the 3.1 Lang format: `default` adapter (`file`, `deepl` or `google_translate`), `default_locale` and a section per remote adapter.
- `save_remote_image()` uses the fluent `httpRequest()` helper.
- CI runs `composer rector:check` after PHPStan.
+- The DTOs and services use `readonly` properties, and null values are cast to strings where they reach string functions (`trim()`, `strtotime()`, `preg_replace()`), as the Rector PHP 8.1 level set proposes.
- **Breaking:** the minimum PHP version is 8.1 (`composer.json`, README, PHPStan `phpVersion` and the Rector level set), and CI runs on PHP 8.1, 8.2 and 8.3, following the framework (quantum-php/framework#595).
### Removed
diff --git a/helpers/functions.php b/helpers/functions.php
index 2fa65bc..f4c5aea 100644
--- a/helpers/functions.php
+++ b/helpers/functions.php
@@ -30,7 +30,7 @@ function url_with_lang(string $lang): string
}
if (preg_match('/' . preg_quote(current_lang(), '/') . '/', route_uri())) {
- return base_url() . preg_replace('/' . preg_quote(current_lang(), '/') . '/', $lang, route_uri(), 1);
+ return base_url() . preg_replace('/' . preg_quote(current_lang(), '/') . '/', (string) $lang, route_uri(), 1);
}
$url = base_url(true);
diff --git a/shared/Commands/CommentCreateCommand.php b/shared/Commands/CommentCreateCommand.php
index 2959a98..7ab2e28 100644
--- a/shared/Commands/CommentCreateCommand.php
+++ b/shared/Commands/CommentCreateCommand.php
@@ -75,7 +75,7 @@ public function exec(): void
$commentDto = new CommentDTO(
$this->getArgument('post_uuid'),
$this->getArgument('user_uuid'),
- trim($this->getArgument('content'))
+ trim((string) $this->getArgument('content'))
);
service(CommentService::class)->addComment($commentDto);
diff --git a/shared/Commands/DemoCommand.php b/shared/Commands/DemoCommand.php
index 42c0ffb..f50d117 100644
--- a/shared/Commands/DemoCommand.php
+++ b/shared/Commands/DemoCommand.php
@@ -223,7 +223,7 @@ private function createModule(string $moduleName, string $template, bool $withAs
]);
} catch (ProcessFailedException $e) {
throw new RuntimeException(
- trim($e->getProcess()->getOutput()) ?: $e->getMessage()
+ trim((string) $e->getProcess()->getOutput()) ?: $e->getMessage()
);
}
}
diff --git a/shared/DTOs/CommentDTO.php b/shared/DTOs/CommentDTO.php
index edc50e2..e067a33 100644
--- a/shared/DTOs/CommentDTO.php
+++ b/shared/DTOs/CommentDTO.php
@@ -21,17 +21,17 @@ class CommentDTO
/**
* @var string
*/
- private string $postUuid;
+ private readonly string $postUuid;
/**
* @var string
*/
- private string $userUuid;
+ private readonly string $userUuid;
/**
* @var string
*/
- private string $content;
+ private readonly string $content;
/**
* @param string $postUuid
diff --git a/shared/DTOs/PostDTO.php b/shared/DTOs/PostDTO.php
index cbe428c..17f4d7a 100644
--- a/shared/DTOs/PostDTO.php
+++ b/shared/DTOs/PostDTO.php
@@ -21,27 +21,27 @@ class PostDTO
/**
* @var string
*/
- private string $title;
+ private readonly string $title;
/**
* @var string
*/
- private string $content;
+ private readonly string $content;
/**
* @var string|null
*/
- private ?string $userUuid;
+ private readonly ?string $userUuid;
/**
* @var string|null
*/
- private ?string $image;
+ private readonly ?string $image;
/**
* @var string|null
*/
- private ?string $uuid;
+ private readonly ?string $uuid;
/**
* @param string $title
diff --git a/shared/DTOs/UserDTO.php b/shared/DTOs/UserDTO.php
index 7dd9df4..e5ba02d 100644
--- a/shared/DTOs/UserDTO.php
+++ b/shared/DTOs/UserDTO.php
@@ -21,37 +21,37 @@ class UserDTO
/**
* @var string
*/
- private string $email;
+ private readonly string $email;
/**
* @var string
*/
- private string $password;
+ private readonly string $password;
/**
* @var string
*/
- private string $firstname;
+ private readonly string $firstname;
/**
* @var string
*/
- private string $lastname;
+ private readonly string $lastname;
/**
* @var string
*/
- private string $role;
+ private readonly string $role;
/**
* @var string|null
*/
- private ?string $uuid;
+ private readonly ?string $uuid;
/**
* @var string
*/
- private string $image;
+ private readonly string $image;
/**
* @param string $email
diff --git a/shared/Services/AuthService.php b/shared/Services/AuthService.php
index f4d04dc..25203c2 100644
--- a/shared/Services/AuthService.php
+++ b/shared/Services/AuthService.php
@@ -30,7 +30,7 @@ class AuthService extends Service implements AuthServiceInterface
/**
* @var User
*/
- private User $model;
+ private readonly User $model;
/**
* @throws BaseException
diff --git a/shared/Services/CommentService.php b/shared/Services/CommentService.php
index 14415f1..74b7dcb 100644
--- a/shared/Services/CommentService.php
+++ b/shared/Services/CommentService.php
@@ -29,7 +29,7 @@ class CommentService extends Service
* @var Comment
*/
private $model;
- private CommentTransformer $transformer;
+ private readonly CommentTransformer $transformer;
/**
* @param CommentTransformer $transformer
diff --git a/shared/Services/PostService.php b/shared/Services/PostService.php
index 26a1509..22ad0a5 100644
--- a/shared/Services/PostService.php
+++ b/shared/Services/PostService.php
@@ -43,7 +43,7 @@ class PostService extends Service
/**
* @var PostTransformer
*/
- private PostTransformer $transformer;
+ private readonly PostTransformer $transformer;
/**
* @param PostTransformer $transformer
diff --git a/shared/Transformers/CommentTransformer.php b/shared/Transformers/CommentTransformer.php
index 88d3a5d..607f206 100644
--- a/shared/Transformers/CommentTransformer.php
+++ b/shared/Transformers/CommentTransformer.php
@@ -28,7 +28,7 @@ public function transform($item): array
'image' => $item->image,
],
'content' => $item->content,
- 'date' => date('Y-m-d H:i', strtotime($item->created_at)),
+ 'date' => date('Y-m-d H:i', strtotime((string) $item->created_at)),
];
}
}
diff --git a/shared/Transformers/PostTransformer.php b/shared/Transformers/PostTransformer.php
index 92f3de1..f624513 100644
--- a/shared/Transformers/PostTransformer.php
+++ b/shared/Transformers/PostTransformer.php
@@ -30,7 +30,7 @@ public function transform($item): array
'title' => $item->title,
'content' => markdown_to_html($item->content, true),
'image' => $this->buildImagePath($item),
- 'date' => date('Y/m/d H:i', strtotime($item->updated_at)),
+ 'date' => date('Y/m/d H:i', strtotime((string) $item->updated_at)),
'author' => $item->firstname . ' ' . $item->lastname,
];
}