-
-
Notifications
You must be signed in to change notification settings - Fork 18
feat(router): add php 8 attributes support for route definition #349
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
b5884fd
fix: handle unloaded environment in app_env and replace deprecated do…
gessyken 11b8094
fix: resolve deprecation warnings and improve test stability
gessyken ada1bed
feat(router): add php 8 attributes support for route definition
gessyken ad04f56
fix(config): restore env error visibility for observability
gessyken 0f70e1d
Merge branch '5.x' into 5.x
papac File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,4 +9,5 @@ composer.lock | |
| .phpunit.result.cache | ||
| bob | ||
| .phpunit.cache | ||
| .vscode/ | ||
| .vscode | ||
| .idea | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,207 @@ | ||
| # Roadmap BowPHP Framework | ||
|
|
||
| > Document évolutif basé sur l'analyse du code source (branche 5.x) et le manifeste du projet. | ||
| > Dernière mise à jour : Janvier 2026 | ||
|
|
||
| --- | ||
|
|
||
| ## État Actuel du Framework | ||
|
|
||
| ### Modules Existants (Analyse du `/src`) | ||
|
|
||
| | Module | Statut | Description | | ||
| | ---------------------- | --------- | ---------------------------------------------- | | ||
| | **Application** | ✅ Stable | Bootstrap, exception handling, kernel | | ||
| | **Auth** | ✅ Stable | Guards (Session, JWT), Authentication | | ||
| | **Cache** | ✅ Stable | Adapters: Database, Filesystem, Redis | | ||
| | **Configuration** | ✅ Stable | Loader, Env, Logger configuration | | ||
| | **Console** | ✅ Stable | 26 commandes, générateurs, stubs | | ||
| | **Container** | ✅ Stable | DI container, middleware dispatcher | | ||
| | **Database/Barry ORM** | ✅ Stable | MySQL, PostgreSQL, SQLite + Relations | | ||
| | **Event** | ✅ Stable | Event dispatcher, listeners, queue integration | | ||
| | **Http** | ✅ Stable | Request, Response, Client, Exceptions | | ||
| | **Mail** | ✅ Stable | SMTP, Native adapters, queue support | | ||
| | **Messaging** | ✅ Stable | SMS, Mail, Slack, Telegram, Database channels | | ||
| | **Middleware** | ✅ Stable | Auth, CSRF, Base middleware | | ||
| | **Queue** | ✅ Stable | Beanstalkd, Database, SQS, Sync adapters | | ||
| | **Router** | ✅ Stable | REST methods, prefixes, middlewares, resources | | ||
| | **Security** | ✅ Stable | Crypto, Hash, Sanitize, Tokenize | | ||
| | **Session** | ✅ Stable | Cookie, File, Database, Redis adapters | | ||
| | **Storage** | ✅ Stable | Disk, FTP, S3 services | | ||
| | **Support** | ✅ Stable | Helpers, Collection, Str, Log, Env | | ||
| | **Testing** | ✅ Stable | TestCase, Assertions, KernelTesting | | ||
| | **Translate** | ✅ Stable | i18n support | | ||
| | **Validation** | ✅ Stable | Règles de validation, messages custom | | ||
| | **View** | ✅ Stable | Tintin (default), Twig support | | ||
|
|
||
| ### Dépendances Actuelles | ||
|
|
||
| **Requises :** | ||
|
|
||
| - PHP ^8.1 | ||
| - bowphp/tintin ^3.0 (template engine) | ||
| - filp/whoops ^2.1 (error handling) | ||
| - nesbot/carbon 3.8.4 (dates) | ||
| - fakerphp/faker ^1.20 (testing data) | ||
| - ramsey/uuid ^4.7 (UUIDs) | ||
|
|
||
| **Dev/Suggérées :** | ||
|
|
||
| - pda/pheanstalk ^5.0 (Beanstalkd) | ||
| - aws/aws-sdk-php ^3.87 (S3) | ||
| - bowphp/policier ^3.0 (JWT) | ||
| - predis/predis ^2.1 (Redis) | ||
| - twilio/sdk ^8.3 (SMS) | ||
| - bowphp/slack-webhook ^1.0 (Slack) | ||
|
|
||
| --- | ||
|
|
||
| ## 🔴 NOW — 0 à 3 mois (Stabilisation & Consolidation) | ||
|
|
||
| ### Tests et CI/CD | ||
|
|
||
| | Tâche | Statut | Priorité | Notes | | ||
| | --------------------------------------------------- | ---------- | -------- | ------------------------------------------------------ | | ||
| | Séparer les tests unitaires des tests d'intégration | ⏳ À faire | Haute | Les tests DB/FTP/S3 nécessitent des services externes | | ||
| | Ajouter `@group` PHPUnit pour isoler les tests | ⏳ À faire | Haute | `@group unit`, `@group integration`, `@group database` | | ||
| | Configurer GitHub Actions avec services Docker | ⏳ À faire | Haute | MySQL, PostgreSQL, Redis pour CI | | ||
| | Augmenter couverture tests unitaires > 80% | ⏳ À faire | Moyenne | Focus sur modules critiques | | ||
| | Intégrer PHPStan niveau 5+ | ⏳ À faire | Moyenne | Actuellement niveau 0.12.87 | | ||
|
|
||
| ### Corrections de Code | ||
|
|
||
| | Tâche | Statut | Priorité | Notes | | ||
| | ----------------------------------------------- | ---------- | -------- | ------------------------------------- | | ||
| | Fixer les tests SQLite qui échouent (isolation) | ⏳ À faire | Haute | Problème de state partagé entre tests | | ||
| | Uniformiser les signatures de méthodes | ✅ Fait | - | PHP 8.1+ nullable types | | ||
| | Fixer le cast `(double)` → `(float)` | ✅ Fait | - | Model.php ligne 924 | | ||
| | Gérer `array_key_exists` avec clé null | ✅ Fait | - | Console.php | | ||
| | Créer le répertoire de test si inexistant | ✅ Fait | - | CustomCommand.php | | ||
|
|
||
| ### Documentation | ||
|
|
||
| | Tâche | Statut | Priorité | Notes | | ||
| | -------------------------------------------- | ---------- | -------- | -------------------------- | | ||
| | Mettre à jour README avec exemples API-first | ⏳ À faire | Moyenne | Aligner avec le manifeste | | ||
| | Documenter les configurations requises | ⏳ À faire | Moyenne | Chaque module | | ||
| | Créer guide de contribution détaillé | ⏳ À faire | Basse | Au-delà du CONTRIBUTING.md | | ||
|
|
||
| --- | ||
|
|
||
| ## 🟠 NEXT — 3 à 6 mois (Nouvelles Fonctionnalités) | ||
|
|
||
| ### Queue - Adapter Redis | ||
|
|
||
| | Tâche | Statut | Priorité | Notes | | ||
| | ---------------------------------------- | ---------- | -------- | ------------------------------ | | ||
| | Créer `RedisAdapter` pour Queue | ⏳ À faire | Haute | predis/predis déjà en dev-deps | | ||
| | Implémenter delayed jobs avec Redis ZADD | ⏳ À faire | Haute | | | ||
| | Ajouter monitoring des queues via CLI | ⏳ À faire | Moyenne | `bow queue:status` | | ||
|
|
||
| ### Router - Attributs PHP 8 | ||
|
|
||
| | Tâche | Statut | Priorité | Notes | | ||
| | ------------------------------------------------------ | ---------- | -------- | --------------------- | | ||
| | Créer namespace `Bow\Router\Attributes` | ⏳ À faire | Haute | | | ||
| | Implémenter `#[Controller]` | ⏳ À faire | Haute | prefix, middleware | | ||
| | Implémenter `#[Get]`, `#[Post]`, `#[Put]`, `#[Delete]` | ⏳ À faire | Haute | | | ||
| | Ajouter `$router->register(Controller::class)` | ⏳ À faire | Haute | Auto-discovery routes | | ||
|
|
||
| ### Cache - Adapter Memcached | ||
|
|
||
| | Tâche | Statut | Priorité | Notes | | ||
| | --------------------------------------------- | ---------- | -------- | ----- | | ||
| | Créer `MemcachedAdapter` | ⏳ À faire | Moyenne | | | ||
| | Améliorer résilience Redis (reconnexion auto) | ⏳ À faire | Moyenne | | | ||
|
|
||
| ### Messaging - Push Notifications | ||
|
|
||
| | Tâche | Statut | Priorité | Notes | | ||
| | ------------------------------------ | ---------- | -------- | ------------- | | ||
| | Créer `FcmChannelAdapter` (Firebase) | ⏳ À faire | Moyenne | | | ||
| | Créer `ApnsChannelAdapter` (Apple) | ⏳ À faire | Moyenne | | | ||
| | Améliorer `TelegramChannelAdapter` | ⏳ À faire | Basse | Déjà existant | | ||
| | Améliorer `SlackChannelAdapter` | ⏳ À faire | Basse | Déjà existant | | ||
|
|
||
| ### Database | ||
|
|
||
| | Tâche | Statut | Priorité | Notes | | ||
| | ----------------------------------------- | ---------- | -------- | ---------------------------- | | ||
| | Ajouter support SQL Server | ⏳ À faire | Moyenne | | | ||
| | Créer adapter Array/FileWriter pour tests | ⏳ À faire | Moyenne | Évite dépendance DB en tests | | ||
|
|
||
| --- | ||
|
|
||
| ## 🟢 LATER — 6 à 12 mois (Vision Long Terme) | ||
|
|
||
| ### Performance et Modernisation | ||
|
|
||
| | Tâche | Statut | Priorité | Notes | | ||
| | -------------------------------------------- | ---------- | -------- | -------------------------- | | ||
| | Support Swoole/FrankenPHP | ⏳ À faire | Moyenne | Serveurs non-bloquants | | ||
| | Images Docker officielles | ⏳ À faire | Moyenne | Optimisées pour production | | ||
| | Support serverless (Lambda, Cloud Functions) | ⏳ À faire | Basse | HTTP Handler adapté | | ||
|
|
||
| ### Écosystème | ||
|
|
||
| | Tâche | Statut | Priorité | Notes | | ||
| | ------------------------------------------------ | ---------- | -------- | -------------------- | | ||
| | Package `bowphp/payment` | ⏳ À faire | Haute | Mobile money Afrique | | ||
| | Package `bowphp/logviewer` ou `bowphp/telescope` | ⏳ À faire | Moyenne | Observabilité | | ||
| | Adapter laravel-notify pour Bow | ⏳ À faire | Basse | UI notifications | | ||
|
|
||
| ### Observabilité | ||
|
|
||
| | Tâche | Statut | Priorité | Notes | | ||
| | ------------------------------ | ---------- | -------- | ------------------------------- | | ||
| | Module OpenTelemetry optionnel | ⏳ À faire | Moyenne | Tracing requests, jobs, queries | | ||
| | Intégration Prometheus/Grafana | ⏳ À faire | Basse | Métriques production | | ||
|
|
||
| --- | ||
|
|
||
| ## Légende | ||
|
|
||
| - ✅ **Fait** : Tâche complétée | ||
| - ⏳ **À faire** : Tâche planifiée | ||
| - 🔄 **En cours** : Travail en progression | ||
| - ❌ **Annulé** : Tâche abandonnée | ||
|
|
||
| --- | ||
|
|
||
| ## Comment Contribuer | ||
|
|
||
| 1. Choisir une tâche de la section **NOW** (priorité haute) | ||
| 2. Ouvrir une issue pour discuter de l'implémentation | ||
| 3. Créer une branche `feature/nom-de-la-tache` | ||
| 4. Suivre les conventions du projet (voir CONTRIBUTING.md) | ||
| 5. Soumettre une PR avec tests | ||
|
|
||
| --- | ||
|
|
||
| ## Notes Importantes | ||
|
|
||
| ### Concernant les Tests | ||
|
|
||
| Les erreurs actuelles lors de `composer test` sont principalement dues à : | ||
|
|
||
| 1. **Services externes non disponibles** (pas des bugs du framework) : | ||
|
|
||
| - MySQL : Connection refused / Access denied | ||
| - PostgreSQL : Connection refused | ||
| - FTP : Connection refused | ||
| - S3 : Invalid endpoint | ||
| - Beanstalkd : Connection refused | ||
|
|
||
| 2. **Isolation des tests SQLite** : Certains tests partagent l'état de la base, causant des échecs intermittents. | ||
|
|
||
| **Solution recommandée** : Séparer les tests en groupes (`@group unit`, `@group integration`) et configurer CI avec Docker Compose pour les tests d'intégration. | ||
|
|
||
| ### Philosophie du Projet | ||
|
|
||
| Toute contribution doit respecter le manifeste : | ||
|
|
||
| - **Simplicité** > Sophistication | ||
| - **Lisibilité** > Concision extrême | ||
| - **API-first** : Priorité aux backends JSON | ||
| - **Performance** : Bootstrap minimal, réponse rapide | ||
| - **Contrôle** : Le développeur garde le contrôle de son architecture |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,106 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| namespace Bow\Router; | ||
|
|
||
| use Bow\Router\Attributes\Controller; | ||
| use Bow\Router\Attributes\Route as RouteAttribute; | ||
| use ReflectionClass; | ||
| use ReflectionMethod; | ||
|
|
||
| class AttributeRouteRegistrar | ||
| { | ||
| /** | ||
| * The router instance | ||
| * | ||
| * @var Router | ||
| */ | ||
| private Router $router; | ||
|
|
||
| /** | ||
| * @param Router $router | ||
| */ | ||
| public function __construct(Router $router) | ||
| { | ||
| $this->router = $router; | ||
| } | ||
|
|
||
| /** | ||
| * Register routes from controller classes | ||
| * | ||
| * @param string|array $controllers | ||
| * @return void | ||
| */ | ||
| public function register(string|array $controllers): void | ||
| { | ||
| $controllers = is_array($controllers) ? $controllers : [$controllers]; | ||
|
|
||
| foreach ($controllers as $controller) { | ||
| $this->registerController($controller); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Register routes from controller | ||
| * | ||
| * @param string $controllerClass | ||
| * @return void | ||
| */ | ||
| private function registerController(string $controllerClass): void | ||
| { | ||
| $reflection = new ReflectionClass($controllerClass); | ||
|
|
||
| // Get controller attribute | ||
| $controllerAttributes = $reflection->getAttributes(Controller::class); | ||
| $controllerAttribute = !empty($controllerAttributes) ? $controllerAttributes[0]->newInstance() : null; | ||
|
|
||
| $prefix = $controllerAttribute?->getPrefix() ?? ''; | ||
| $controllerMiddleware = $controllerAttribute?->getMiddleware() ?? []; | ||
|
|
||
|
papac marked this conversation as resolved.
|
||
| // Scan methods | ||
| foreach ($reflection->getMethods(ReflectionMethod::IS_PUBLIC) as $method) { | ||
| if (str_starts_with($method->getName(), '__')) { | ||
| continue; | ||
| } | ||
|
papac marked this conversation as resolved.
|
||
|
|
||
| // Get route attributes | ||
| $routeAttributes = $method->getAttributes( | ||
| RouteAttribute::class, | ||
| \ReflectionAttribute::IS_INSTANCEOF | ||
| ); | ||
|
|
||
| foreach ($routeAttributes as $attribute) { | ||
| /** @var RouteAttribute $routeAttr */ | ||
| $routeAttr = $attribute->newInstance(); | ||
|
|
||
| // Build path | ||
| $routePath = $routeAttr->getPath(); | ||
| $routePath = '/' . ltrim($routePath, '/'); | ||
| $fullPath = $prefix !== '' ? rtrim($prefix, '/') . $routePath : $routePath; | ||
|
|
||
| // Merge middleware | ||
| $middleware = array_merge($controllerMiddleware, $routeAttr->getMiddleware()); | ||
|
|
||
| // Register route | ||
| $route = $this->router->match( | ||
| $routeAttr->getMethods(), | ||
| $fullPath, | ||
| [$controllerClass, $method->getName()] | ||
| ); | ||
|
|
||
| if (!empty($middleware)) { | ||
| $route->middleware($middleware); | ||
| } | ||
|
|
||
| if (!empty($routeAttr->getWhere())) { | ||
| $route->where($routeAttr->getWhere()); | ||
| } | ||
|
|
||
| if ($routeAttr->getName() !== null) { | ||
| $route->name($routeAttr->getName()); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| namespace Bow\Router\Attributes; | ||
|
|
||
| use Attribute; | ||
|
|
||
| #[Attribute(Attribute::TARGET_CLASS)] | ||
| class Controller | ||
| { | ||
| /** | ||
| * @param string $prefix | ||
| * @param array $middleware | ||
| * @param string|null $name | ||
| */ | ||
| public function __construct( | ||
| public readonly string $prefix = '', | ||
| public readonly array $middleware = [], | ||
| public readonly ?string $name = null | ||
| ) {} | ||
|
|
||
| /** | ||
| * Get the prefix | ||
| * | ||
| * @return string | ||
| */ | ||
| public function getPrefix(): string | ||
| { | ||
| return $this->prefix; | ||
| } | ||
|
|
||
| /** | ||
| * Get the middleware | ||
| * | ||
| * @return array | ||
| */ | ||
| public function getMiddleware(): array | ||
| { | ||
| return $this->middleware; | ||
| } | ||
|
|
||
| /** | ||
| * Get the route name | ||
| * | ||
| * @return string|null | ||
| */ | ||
| public function getName(): ?string | ||
| { | ||
| return $this->name; | ||
| } | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.