saeedpooyanfar/laravel-annotation
A Laravel package that brings PHP annotation support to your app, letting you define and read metadata via docblocks. It enables cleaner, declarative configuration for routes, validation, and other framework features without bulky config files.
Install the package
composer require saeedpooyanfar/laravel-annotation
v5.0.0 targets Laravel 11. Confirm this before installing: if you're on Laravel 10 or older, you likely need the previous major (^4.0) instead — see Gotchas. Laravel's package discovery should register the service provider automatically.
Look here first
src/ — the #[Annotation] attribute class and any reader/resolver. This is your real API surface; the README is thin for a low-star package.config/ — check whether a config file ships (cache TTL, scan paths, whether annotations are read from cache). Publish with php artisan vendor:publish --tag=annotation-config if available.composer.json — check the require.php and require.illuminate/* constraints. v5.0.0's only stated change is Laravel 11 support, so expect something like php: ^8.2 and illuminate/support: ^11.0. Verify whether Laravel 10 support was dropped or merely not mentioned — a major bump usually means dropped.CHANGELOG.md / git tags — v5.0.0's notes are a single line, so the diff between v4.x..v5.0.0 is the only reliable record of what else moved (attribute targets, namespace, service provider FQCN).First use case — annotate a class or method and read the annotation back with reflection:
use SaeedPooyanfar\LaravelAnnotation\Annotation;
#[Annotation('audit')]
class InvoiceController
{
#[Annotation('log')]
public function store() { /* ... */ }
}
Then resolve the annotation from the container/reader the package exposes (check src/ for a reader façade or helper). The canonical "hello world" is: annotate a controller method, resolve the annotation at request time, and branch on its value (e.g. apply an audit middleware or feature toggle).
If discovery doesn't fire, note that Laravel 11 removed config/app.php provider registration — register manually in bootstrap/providers.php instead.
handle(), and mutate the request/response accordingly. This is the most idiomatic use: annotate, resolve, act.AnnotationReader) to the concrete implementation in AppServiceProvider (or bootstrap/app.php's withProviders on Laravel 11) to keep your app testable.tests/Fixtures/AnnotatedController.php) rather than the whole HTTP stack. Assert on the resolved annotation array/object.#[Route], #[Middleware], or #[Observed]; use it for your domain metadata, not for routing, to avoid fighting the framework.Http/Kernel.php, bootstrap/app.php middleware config) than the annotation code itself.illuminate/support moved to ^11.0 and older majors were dropped. If you're on Laravel 10, pin ^4.0; if you're mid-upgrade, do the framework upgrade first, then the package.require.php too. Check before bumping in a multi-runtime fleet.ReflectionClass/ReflectionMethod/ReflectionProperty. They are not inherited by child classes unless you explicitly walk the parent chain. If subclasses seem to lose annotations, that's why — not the package.#[Attribute] must decorate the attribute class. If Annotation isn't itself marked #[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD)], the package will emit deprecation/parse errors on newer PHP. Verify the target flags before relying on TARGET_PARAMETER or TARGET_CONSTANT — and re-verify after the major bump, since this is exactly the kind of thing a one-line changelog hides.app/ can dominate request time. Cache the resolved metadata (Laravel Cache::rememberForever) keyed by class + method, and flush on deploy.bootstrap/app.php doing more at boot, be careful not to trigger resolution during bootstrap.src/ end-to-end (it's small) and confirm:
require.php / illuminate/* constraints match your runtime.autoload PSR-4 map is correct.app/Support/ and write a ~20-line reflection reader yourself. That escape hatch also makes upgrading Laravel 12+ painless later.dd( (new ReflectionClass(MyController::class))->getAttributes() ) — if that's empty, the issue is the attribute binding/target, not the package.php artisan config:clear and any package cache-clear command before debugging "missing annotation" reports. On Laravel 11, also run php artisan optimize:clear — the consolidated caches (config, route, view, event) can each mask annotation changes differently.How can I help you explore Laravel packages today?