PHPackages                             geeky/request-objects - 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. geeky/request-objects

ActiveLibrary[Framework](/categories/framework)

geeky/request-objects
=====================

Custom request objects for Symfony made to make life less painful

1.0.5(5y ago)81.3k↓50%1[2 issues](https://github.com/TheGeekyM/symfony-object-request-validation/issues)MITPHPPHP &gt;=7.1.0CI failing

Since Jun 18Pushed 5y ago1 watchersCompare

[ Source](https://github.com/TheGeekyM/symfony-object-request-validation)[ Packagist](https://packagist.org/packages/geeky/request-objects)[ RSS](/packages/geeky-request-objects/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (6)Dependencies (5)Versions (6)Used By (0)

Symfony Request Objects
=======================

[](#symfony-request-objects)

[![Build Status](https://camo.githubusercontent.com/d163ed054731e47655c80e4ea61fb02595b13476145e3fa970a09c4d40a433ce/68747470733a2f2f7472617669732d63692e6f72672f6665736f722f726571756573742d6f626a656374732e7376673f6272616e63683d6d6173746572)](https://travis-ci.org/fesor/request-objects)[![Scrutinizer Code Quality](https://camo.githubusercontent.com/fd8f5f2bc683ccb003bde6d1c35435088f9f6916dc6c1fc3ed78861092ed98c5/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f6665736f722f726571756573742d6f626a656374732f6261646765732f7175616c6974792d73636f72652e706e673f623d6d6173746572)](https://scrutinizer-ci.com/g/fesor/request-objects/?branch=master)[![Latest Stable Version](https://camo.githubusercontent.com/879a8a82571096008183d92ab0c968c81a4543340dbe3452d4a4ee2353fb156b/68747470733a2f2f706f7365722e707567782e6f72672f6665736f722f726571756573742d6f626a656374732f762f737461626c65)](https://packagist.org/packages/fesor/request-objects)[![Total Downloads](https://camo.githubusercontent.com/40d3178480b78473413115729d4b5c61bee5a373771718203945843bd12a8702/68747470733a2f2f706f7365722e707567782e6f72672f6665736f722f726571756573742d6f626a656374732f646f776e6c6f616473)](https://packagist.org/packages/fesor/request-objects)[![License](https://camo.githubusercontent.com/1b3f266cf755e7c439a2e12af5081e790c53b1e7fb8fb01c72f890e2d2c51bbe/68747470733a2f2f706f7365722e707567782e6f72672f6665736f722f726571756573742d6f626a656374732f6c6963656e7365)](https://packagist.org/packages/fesor/request-objects)

**Note**: The library is taken from this library [fesor/request-objects](https://github.com/fesor/request-objects) but this library is working on symfony v5+ . with a few updates

Why?
----

[](#why)

Symfony Forms component is a very powerful tool for handling forms. But nowadays things have changed. Complex forms are handled mostly on the client side. As for simple forms `symfony/forms` has very large overhead.

And in some cases you just don't have forms. For example, if you are developing an HTTP API, you probably just need to interact with request payload. So why not just wrap request payload in some user defined object and validate just it? This also encourages separation of concerns and will help you in case of API versioning.

Usage
-----

[](#usage)

First of all, we need to install this package via composer:

```
composer require geeky/request-objects

```

And register the bundle in `config/bundels.php`:

```
    return [
     ....
     Fesor\RequestObject\Bundle\RequestObjectBundle::class => ['all' => true],
    ];

```

Bundle doesn't require any additional configuration, but you could also specify an error response provider service in bundle config. We will come back to this in "Handle validation errors" section.

### Define your request objects

[](#define-your-request-objects)

All user defined requests should extend `Fesor\RequestObject\RequestObject`. Let's create a simple request object for user registration action:

```
use Fesor\RequestObject\RequestObject;
use Symfony\Component\Validator\Constraints as Assert;

class RegisterUserRequest extends RequestObject
{
    public function rules()
    {
        return new Assert\Collection([
            'email' => new Assert\Email(['message' => 'Please fill in valid email']),
            'password' => new Assert\Length(['min' => 4, 'minMessage' => 'Password is to short']),
            'first_name' => new Assert\NotNull(['message' => 'Please provide your first name']),
            'last_name' => new Assert\NotNull(['message' => 'Please provide your last name'])
        ]);
    }
}
```

After that we can just use it in our action:

```
public function registerUserAction(RegisterUserRequest $request)
{
    // Do Stuff! Data is already validated!
}
```

This bundle will bind validated request object to the `$request` argument. Request object has very simple interface for data interaction. It is very similar to Symfony's request object but is considered immutable by default (although you can add some setters if you wish so)

```
// returns value from payload by specific key or default value if provided
$request->get('key', 'default value');

// returns whole payload
$request->all();
```

### Where payload comes from?

[](#where-payload-comes-from)

This library has default implementation of `PayloadResolver` interface, which acts this way:

1. If a request can have a body (i.e. it is POST, PUT, PATCH or whatever request with body) it uses union of `$request->request->all()` and `$request->files->all()` arrays as payload.
2. If request can't have a body (i.e. GET, HEAD verbs), then it uses `$request->query->all()`.

If you wish to apply custom logic for payload extraction, you could implement `PayloadResolver` interface within your request object:

```
class CustomizedPayloadRequest extends RequestObject implements PayloadResolver
{
    public function resolvePayload(Request $request)
    {
        $query = $request->query->all();
        // turn string to array of relations
        if (isset($query['includes'])) {
            $query['includes'] = explode(',', $query['includes']);
        }

        return $query;
    }
}
```

This will allow you to do some crazy stuff with your requests and DRY a lot of stuff.

### Validating payload

[](#validating-payload)

As you can see from previous example, the `rules` method should return validation rules for [symfony validator](http://symfony.com/doc/current/book/validation.html). Your request payload will be validated against it and you will get valid data in your action.

If you have some validation rules which depend on payload data, then you can handle it via validation groups.

**Please note**: due to limitations in `Collection` constraint validator it is not so handy to use groups. So instead it is recommended to use `Callback` validator in tricky cases with dependencies on payload data. See [example](examples/Request/ContextDependingRequest.php) for details about problem.

You may provide validation group by implementing `validationGroup` method:

```
public function validationGroup(array $payload)
{
    return isset($payload['context']) ?
        ['Default', $payload['context']] : null;
}
```

### Handling validation errors

[](#handling-validation-errors)

If validated data is invalid, library will throw exception which will contain validation errors and request object.

But if you don't want to handle it via `kernel.exception` listener, you have several options.

First is to use your controller action to handle errors:

```
public function registerUserAction(RegisterUserRequest $request, ConstraintViolationList $errors)
{
    if (0 !== count($errors)) {
        // handle errors
    }
}
```

But this not so handy and will break DRY if you just need to return common error response. Thats why library provides you `ErrorResponseProvider` interface. You can implement it in your request object and move this code to `getErrorResponse` method:

```
public function getErrorResponse(ConstraintViolationListInterface $errors)
{
    return new JsonResponse([
        'message' => 'Please check your data',
        'errors' => array_map(function (ConstraintViolation $violation) {

            return [
                'path' => $violation->getPropertyPath(),
                'message' => $violation->getMessage()
            ];
        }, iterator_to_array($errors))
    ], 400);
}
```

Exception Listner Handling
--------------------------

[](#exception-listner-handling)

If you need to handle the validaion exception from the exception itself you can take a look at this example [Excetion Example](https://github.com/TheGeekyM/symfony-object-request-validation/blob/master/examples/src/EventListener/ExceptionListener.php)

So the first thing you should create the `src/EventListener/ExceptionListener.php` file or anywhere you want then paste the example file in it and you can customize the response as you want,

secondly you must register the created file into `services.yaml` file like this:

```
parameters:

services:
    App\EventListener\ExceptionListener: #here you can create your file anywhere else
            tags:
                - { name: kernel.event_listener, event: kernel.exception }

```

More examples
-------------

[](#more-examples)

If you're still not sure is it useful for you, please see the `examples` directory for more use cases. Didn't find your case? Then share your use case in issues!

Contribution
------------

[](#contribution)

Feel free to give feedback and feature requests or post issues. PR's are welcomed!

###  Health Score

28

—

LowBetter than 54% of packages

Maintenance15

Infrequent updates — may be unmaintained

Popularity23

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity54

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% 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 ~0 days

Total

5

Last Release

2159d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/969bfcf4457bc5199ca47192dfcb06c61991739f2968f748e41f4ad83e8e2df0?d=identicon)[TheGeeky](/maintainers/TheGeeky)

---

Top Contributors

[![TheGeekyM](https://avatars.githubusercontent.com/u/8965415?v=4)](https://github.com/TheGeekyM "TheGeekyM (14 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/geeky-request-objects/health.svg)

```
[![Health](https://phpackages.com/badges/geeky-request-objects/health.svg)](https://phpackages.com/packages/geeky-request-objects)
```

###  Alternatives

[shopware/platform

The Shopware e-commerce core

3.3k1.5M3](/packages/shopware-platform)[drupal/core

Drupal is an open source content management platform powering millions of websites and applications.

19562.3M1.3k](/packages/drupal-core)[sulu/sulu

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

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

The SilverStripe framework

7213.5M2.5k](/packages/silverstripe-framework)[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)[laravel/reverb

Laravel Reverb provides a real-time WebSocket communication backend for Laravel applications.

1.6k9.4M48](/packages/laravel-reverb)

PHPackages © 2026

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