PHPackages                             a7-tech/laminas-attribute-controller - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Framework](/categories/framework)
4. /
5. a7-tech/laminas-attribute-controller

ActiveLibrary[Framework](/categories/framework)

a7-tech/laminas-attribute-controller
====================================

Package for Laminas Framework to use attributes sugar in controller.

v0.2.2(5mo ago)9921MITPHPPHP ^8.2CI passing

Since Jul 9Pushed 5mo ago1 watchersCompare

[ Source](https://github.com/aleks777777/laminas-attribute-controller)[ Packagist](https://packagist.org/packages/a7-tech/laminas-attribute-controller)[ RSS](/packages/a7-tech-laminas-attribute-controller/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (4)Dependencies (8)Versions (11)Used By (0)

Laminas Attribute Controller
============================

[](#laminas-attribute-controller)

Description
-----------

[](#description)

This package provides attribute-based controllers for use in Laminas applications. It simplifies route management, dependency injection, and input handling in controller arguments.

Installation
------------

[](#installation)

### Requirements

[](#requirements)

- PHP &gt;= 8.0
- Laminas MVC &gt;= 3.0
- Composer

### Instructions

[](#instructions)

1. Install the package: ```
    composer require a7-tech/laminas-attribute-controller

    ```
2. Set up the module in your Laminas application by adding it to the `application.config.php`: ```
    return [
        'modules' => [
            // other modules...
            LaminasAttributeController\Module::class,
        ],
    ];
    ```

Usage
-----

[](#usage)

### Example Controller with Attributes

[](#example-controller-with-attributes)

```
use LaminasAttributeController\AttributeActionController;
use LaminasAttributeController\Routing\Route;

#[Route('/user', name: 'user')]
final class UserController extends AttributeActionController
{
    #[Route('/list', name: 'user_list', methods: ['GET'])]
    public function listAction()
    {
        return ['users' => []];
    }

    #[Route('/add', name: 'user_add', methods: ['POST'])]
    public function addAction()
    {
        return ['status' => 'success'];
    }
}
```

### Route Registration

[](#route-registration)

Routes are automatically registered through attributes when the module is enabled.

Attributes Documentation
------------------------

[](#attributes-documentation)

### Route

[](#route)

The `Route` attribute defines routing for controller methods.

```
use LaminasAttributeController\Routing\Route;

#[Route('/api/users', name: 'users_route', methods: ['GET', 'POST'])]
public function usersAction()
{
    // Method implementation
}
```

**Parameters:**

- `path` (string): The URL path for the route
- `name` (string|null): Optional name for the route
- `methods` (array): HTTP methods allowed for this route, defaults to \['GET'\]

### QueryParam

[](#queryparam)

The `QueryParam` attribute extracts and validates query parameters from the request.

```
use LaminasAttributeController\Validation\QueryParam;
use Symfony\Component\Validator\Constraints as Assert;

public function searchAction(
    #[QueryParam('query', constraints: [new Assert\NotBlank(), new Assert\Length(min: 3)], required: true)] string $searchQuery
) {
    // Use $searchQuery which has been extracted from the request query parameters
    return ['results' => $this->searchService->search($searchQuery)];
}
```

**Parameters:**

- `name` (string): The name of the query parameter
- `constraints` (array): Array of Symfony validator constraints to apply
- `required` (bool): Whether the parameter is required, defaults to false

### Autowire

[](#autowire)

The `Autowire` attribute enables automatic dependency injection.

```
use LaminasAttributeController\Injection\Autowire;
use App\Service\UserService;

public function listAction(
    #[Autowire] UserService $userService,
    #[Autowire('custom.service.alias')] $customService
) {
    $users = $userService->getAllUsers();
    // Method implementation
}
```

**Parameters:**

- `alias` (string|null): Optional service alias for the container, defaults to null (uses the type hint)

### IsGranted

[](#isgranted)

The `IsGranted` attribute provides auth-based access control for controller methods.

```
use LaminasAttributeController\Security\IsGranted;

#[IsGranted('FULLY_AUTHENTICATED')]
public function authorizedAction()
{
    // Only accessible to authenticated users
    return ['message' => 'authorized area'];
}
```

**Parameters:**

- `role` (string): The role required to access the method

### MapRequestHeader

[](#maprequestheader)

The `MapRequestHeader` attribute maps a single HTTP request header to a controller argument. It supports mapping the value as a string, an array, or an `LaminasAttributeController\Validation\AcceptHeader` instance.

```
use LaminasAttributeController\Validation\AcceptHeader;
use LaminasAttributeController\Validation\MapRequestHeader;

public function showAction(
    #[MapRequestHeader('user-agent')] string $userAgent,
    #[MapRequestHeader] array $accept, // header name defaults to the parameter name
    #[MapRequestHeader('accept-language')] array $languages,
    #[MapRequestHeader('accept')] AcceptHeader $acceptHeader,
) {
    // $userAgent contains the raw header value
    // $accept is an array of acceptable content types
    // $languages contains normalised language codes such as en_US
    // $acceptHeader exposes the parsed Accept header instance
}
```

When the argument type is `array`, common negotiated headers receive special handling:

- `Accept` resolves to the ordered list of acceptable content types.
- `Accept-Charset` and `Accept-Encoding` resolve to arrays of the requested charsets or encodings.
- `Accept-Language` resolves to normalised language codes (`en_US`, `en`, ...).
- Other headers return all values for the header.

If the header is missing, default parameter values or nullable types are honoured. Otherwise, an `Laminas\\Http\\Exception\\InvalidArgumentException` is thrown.

### MapRequestPayload

[](#maprequestpayload)

The `MapRequestPayload` attribute maps the request body to a parameter.

```
use LaminasAttributeController\Validation\MapRequestPayload;
use App\DTO\UserCreateRequest;

public function createAction(
    #[MapRequestPayload] UserCreateRequest $request
) {
    // $request is populated from the request body
    return ['id' => $this->userService->createUser($request)];
}
```

This attribute automatically deserializes the request body into the specified type.

#### Example with Multiple Fields and Validators

[](#example-with-multiple-fields-and-validators)

```
use Symfony\Component\Validator\Constraints as Assert;
use JMS\Serializer\Annotation as Serializer;

class UserCreateRequest
{
    #[Assert\NotBlank(message: "Username is required")]
    #[Assert\Length(min: 3, max: 50, minMessage: "Username must be at least {{ limit }} characters", maxMessage: "Username cannot be longer than {{ limit }} characters")]
    public string $username;

    #[Assert\NotBlank(message: "Email is required")]
    #[Assert\Email(message: "The email '{{ value }}' is not a valid email")]
    public string $email;

    #[Assert\NotBlank(message: "Password is required")]
    #[Assert\Length(min: 8, minMessage: "Password must be at least {{ limit }} characters")]
    #[Assert\Regex(
        pattern: "/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).+$/",
        message: "Password must include at least one uppercase letter, one lowercase letter, and one number"
    )]
    public string $password;

    #[Assert\NotBlank(message: "Age is required")]
    #[Assert\Range(
        min: 18,
        max: 120,
        notInRangeMessage: "You must be between {{ min }} and {{ max }} years old"
    )]
    public int $age;
}
```

Using this DTO with the `MapRequestPayload` attribute will automatically validate all fields according to the specified constraints.

### MapQueryString

[](#mapquerystring)

The `MapQueryString` attribute maps the query string parameters to a typed object.

```
use LaminasAttributeController\Validation\MapQueryString;
use App\DTO\UserSearchRequest;

public function searchAction(
    #[MapQueryString] UserSearchRequest $searchCriteria
) {
    // $searchCriteria is populated from the query string parameters
    return ['results' => $this->userService->search($searchCriteria)];
}
```

This attribute automatically deserializes the query string parameters into the specified type, making it easy to work with structured query parameters in GET requests.

#### Example with Multiple Fields and Validators

[](#example-with-multiple-fields-and-validators-1)

```
use Symfony\Component\Validator\Constraints as Assert;
use JMS\Serializer\Annotation as Serializer;

class UserSearchRequest
{
    #[Assert\Length(min: 2, max: 50, minMessage: "Search term must be at least {{ limit }} characters")]
    public ?string $searchTerm = null;

    #[Assert\Range(
        min: 1,
        max: 100,
        notInRangeMessage: "Results per page must be between {{ min }} and {{ max }}"
    )]
    public int $limit = 20;

    #[Assert\PositiveOrZero(message: "Page number cannot be negative")]
    public int $page = 0;

    #[Assert\Choice(choices: ["asc", "desc"], message: "Sort direction must be either 'asc' or 'desc'")]
    public string $sortDirection = "asc";
}
```

Using this DTO with the `MapQueryString` attribute will automatically validate all query parameters according to the specified constraints. This example would handle a query like `?searchTerm=john&limit=50&page=2&sortDirection=desc`.

### CurrentUser

[](#currentuser)

The `CurrentUser` attribute injects the current authenticated user into a parameter. For implementation, you need to have a user entity and a service that retrieves the current user from the session or security context implemented `LaminasAttributeController\Security\GetCurrentUser`

```
use LaminasAttributeController\Security\CurrentUser;
use App\Entity\User;

public function profileAction(
    #[CurrentUser] User $user
) {
    // $user contains the currently authenticated user
    return ['user' => $user];
}
```

This attribute provides easy access to the authenticated user without manual retrieval.

Advanced Configuration
----------------------

[](#advanced-configuration)

### Custom Resolvers

[](#custom-resolvers)

The package allows you to create and configure your own parameter resolvers. This is useful when you need custom logic for resolving controller action parameters.

To create a custom resolver:

1. Create a class that implements `ParameterResolverInterface`:

```
use LaminasAttributeController\ParameterResolverInterface;
use LaminasAttributeController\ResolutionContext;

final class MyCustomResolver implements ParameterResolverInterface
{
    public function resolve(ResolutionContext $context): mixed
    {
        // Access parameter information
        $parameter = $context->parameter;

        // Access route match information
        $routeMatch = $context->routeMatch;

        // Access parameter attributes
        $attributes = $context->getAttributes();

        // Implement your custom resolution logic
        // ...

        // Return the resolved value
        return $resolvedValue;
    }
}
```

2. Register your resolver in the configuration:

```
// In your module.config.php or any other configuration file
return [
    'laminas-attribute-controller' => [
        'resolvers' => [
            // Default resolvers
            FromRouteResolver::class,
            MapRequestPayloadResolver::class,
            MapQueryStringResolver::class,
            QueryParamResolver::class,
            AutowireResolver::class,
            AutoInjectionResolver::class,
            CurrentUserValueResolver::class,
            DefaultValueResolver::class,
            // Your custom resolver
            MyCustomResolver::class,
        ],
    ],
    'service_manager' => [
        'factories' => [
            // Factory for your custom resolver
            MyCustomResolver::class => function (ContainerInterface $container) {
                return new MyCustomResolver(/* dependencies */);
            },
        ],
    ],
];
```

The order of resolvers in the configuration is important as they are tried in sequence until one returns a non-null value.

### Default Resolvers

[](#default-resolvers)

The package comes with the following default resolvers:

- `FromRouteResolver`: Resolves parameters from route matches
- `MapRequestPayloadResolver`: Maps request body to a parameter (POST, PUT, PATCH, etc)
- `MapQueryStringResolver`: Maps request to a parameter from query params (GET request)
- `QueryParamResolver`: Extracts and validates query parameters
- `AutowireResolver`: Provides automatic dependency injection
- `AutoInjectionResolver`: Provides automatic dependency injection
- `CurrentUserValueResolver`: Injects the current authenticated user
- `DefaultValueResolver`: Uses default parameter values

You can customize which resolvers are used by modifying the configuration:

```
return [
    'laminas-attribute-controller' => [
        'resolvers' => [
            // Only include the resolvers you need
            FromRouteResolver::class,
            MapRequestPayloadResolver::class,
            MapQueryStringResolver::class,
            QueryParamResolver::class,
            AutowireResolver::class,
            AutoInjectionResolver::class,
            CurrentUserValueResolver::class,
            DefaultValueResolver::class,
        ],
    ],
];
```

###  Health Score

38

—

LowBetter than 85% of packages

Maintenance70

Regular maintenance activity

Popularity18

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity45

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 96.7% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~47 days

Total

4

Last Release

167d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/3700cb1126409533a8768039eec30d147fe77f9315a04b59b61aa7d511fdbc38?d=identicon)[aleks777777](/maintainers/aleks777777)

---

Top Contributors

[![aleks777777](https://avatars.githubusercontent.com/u/5492244?v=4)](https://github.com/aleks777777 "aleks777777 (29 commits)")[![iWonderWho](https://avatars.githubusercontent.com/u/25483800?v=4)](https://github.com/iWonderWho "iWonderWho (1 commits)")

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/a7-tech-laminas-attribute-controller/health.svg)

```
[![Health](https://phpackages.com/badges/a7-tech-laminas-attribute-controller/health.svg)](https://phpackages.com/packages/a7-tech-laminas-attribute-controller)
```

###  Alternatives

[sulu/sulu

Core framework that implements the functionality of the Sulu content management system

1.3k1.3M152](/packages/sulu-sulu)[prestashop/prestashop

PrestaShop is an Open Source e-commerce platform, committed to providing the best shopping cart experience for both merchants and customers.

9.0k15.4k](/packages/prestashop-prestashop)[shopware/shopware

Shopware 5 is an open source e-commerce software made in Germany

1.3k746.6k35](/packages/shopware-shopware)[contao/core-bundle

Contao Open Source CMS

1231.6M2.4k](/packages/contao-core-bundle)[ec-cube/ec-cube

EC-CUBE EC open platform.

78527.0k1](/packages/ec-cube-ec-cube)[neos/flow

Flow Application Framework

862.0M451](/packages/neos-flow)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
