PHPackages                             zfcampus/zf-content-negotiation - 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. [API Development](/categories/api)
4. /
5. zfcampus/zf-content-negotiation

Abandoned → [laminas-api-tools/api-tools-content-negotiation](/?search=laminas-api-tools%2Fapi-tools-content-negotiation)ArchivedLibrary[API Development](/categories/api)

zfcampus/zf-content-negotiation
===============================

ZF Module providing content-negotiation features

1.4.0(8y ago)192.2M—8.9%31[7 issues](https://github.com/zfcampus/zf-content-negotiation/issues)[1 PRs](https://github.com/zfcampus/zf-content-negotiation/pulls)16BSD-3-ClausePHPPHP ^5.6 || ^7.0

Since Aug 5Pushed 6y ago10 watchersCompare

[ Source](https://github.com/zfcampus/zf-content-negotiation)[ Packagist](https://packagist.org/packages/zfcampus/zf-content-negotiation)[ RSS](/packages/zfcampus-zf-content-negotiation/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (9)Dependencies (14)Versions (34)Used By (16)

ZF Content Negotiation
======================

[](#zf-content-negotiation)

> ## Repository abandoned 2019-12-31
>
> [](#repository-abandoned-2019-12-31)
>
> This repository has moved to [laminas-api-tools/api-tools-content-negotiation](https://github.com/laminas-api-tools/api-tools-content-negotiation).

[![Build Status](https://camo.githubusercontent.com/4854ade60f4ad547b6bfef38cdadea78b90b0e82f959503d5ca7d71d0efecada/68747470733a2f2f7365637572652e7472617669732d63692e6f72672f7a6663616d7075732f7a662d636f6e74656e742d6e65676f74696174696f6e2e7376673f6272616e63683d6d6173746572)](https://secure.travis-ci.org/zfcampus/zf-content-negotiation)[![Coverage Status](https://camo.githubusercontent.com/e9e0a456dcd075862d9ddf1cf4a2c3ace1c486ca56b667e03302cc7e5bbd1cf9/68747470733a2f2f636f766572616c6c732e696f2f7265706f732f6769746875622f7a6663616d7075732f7a662d636f6e74656e742d6e65676f74696174696f6e2f62616467652e7376673f6272616e63683d6d6173746572)](https://coveralls.io/github/zfcampus/zf-content-negotiation?branch=master)

Introduction
------------

[](#introduction)

`zf-content-negotiation` is a module for automating content negotiation tasks within a Zend Framework application.

The following features are provided

- Mapping `Accept` header media types to specific view model types, and automatically casting controller results to those view model types.
- Defining `Accept` header media type whitelists; requests with `Accept` media types that fall outside the whitelist will be immediately rejected with a `406 Not Acceptable` response.
- Defining `Content-Type` header media type whitelists; requests sending content bodies with `Content-Type` media types that fall outside the whitelist will be immediately rejected with a `415 Unsupported Media Type` response.

Requirements
------------

[](#requirements)

Please see the [composer.json](composer.json) file.

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

[](#installation)

Run the following `composer` command:

```
$ composer require zfcampus/zf-content-negotiation
```

Alternately, manually add the following to your `composer.json`, in the `require` section:

```
"require": {
    "zfcampus/zf-content-negotiation": "^1.2"
}
```

And then run `composer update` to ensure the module is installed.

Finally, add the module name to your project's `config/application.config.php` under the `modules`key:

```
return [
    /* ... */
    'modules' => [
        /* ... */
        'ZF\ContentNegotiation',
    ],
    /* ... */
];
```

> ### zf-component-installer
>
> [](#zf-component-installer)
>
> If you use [zf-component-installer](https://github.com/zendframework/zf-component-installer), that plugin will install zf-content-negotiation as a module for you.

Configuration
-------------

[](#configuration)

### User Configuration

[](#user-configuration)

The top-level configuration key for user configuration of this module is `zf-content-negotiation`.

#### Key: `controllers`

[](#key-controllers)

The `controllers` key is utilized for mapping a content negotiation strategy to a particular controller service name (from the top-level `controllers` section). The value portion of the controller array can either be a *named selector* (see `selectors` below), or a selector definition.

A selector definition consists of an array with the key of the array being the name of a view model, and the value of it being an indexed array of media types that, when matched, will select that view model.

Example:

```
'controllers' => [
    // Named selector:
    'Application\Controller\HelloWorld1' => 'Json',

    // Selector definition:
    'Application\Controller\HelloWorld2' => [
        'ZF\ContentNegotiation\JsonModel' => [
            'application/json',
            'application/*+json',
        ],
    ],
],
```

#### Key: `selectors`

[](#key-selectors)

The `selectors` key is utilized to create named selector definitions for reuse between many different controllers. The key part of the selectors array will be a name used to correlate the selector definition (which uses the format described in the [controllers](#key-controllers) key).

Example:

```
'selectors' => [
    'Json' => [
        'ZF\ContentNegotiation\JsonModel' => [
            'application/json',
            'application/*+json',
        ],
    ],
],
```

A selector can contain multiple view models, each associated with different media types, allowing you to provide multiple representations. As an example, the following selector would allow a given controller to return either JSON or HTML output:

```
'selectors' => [
    'HTML-Json' => [
        'ZF\ContentNegotiation\JsonModel' => [
            'application/json',
            'application/*+json',
        ],
        'ZF\ContentNegotiation\ViewModel' => [
            'text/html',
        ],
    ],
],
```

#### Key: `accept_whitelist`

[](#key-accept_whitelist)

The `accept_whitelist` key is utilized to instruct the content negotiation module which media types are acceptable for a given controller service name. When a controller service name is configured in this key, along with an indexed array of matching media types, only media types that match the `Accept` header of a given request will be allowed to be dispatched. Unmatched media types will receive a `406 Cannot honor Accept type specified` response.

The value of each controller service name key can either be a string or an array of strings.

Example:

```
'accept_whitelist' => [
    'Application\\Controller\\HelloApiController' => [
        'application/vnd.application-hello+json',
        'application/hal+json',
        'application/json',
    ],
],
```

#### Key: `content_type_whitelist`

[](#key-content_type_whitelist)

The `content_type_whitelist` key is utilized to instruct the content negotiation module which media types are valid for the `Content-Type` of a request. When a controller service name is configured in this key, along with an indexed array of matching media types, only media types that match the `Content-Type` header of a given request will be allowed to be dispatched. Unmatched media types will receive a `415 Invalid content-type specified` response.

The value of each controller service name key can either be a string or an array of strings.

Example:

```
'content_type_whitelist' => [
    'Application\\Controller\\HelloWorldController' => [
        'application/vnd.application-hello-world+json',
        'application/json',
    ],
],
```

#### Key: `x_http_method_override_enabled`

[](#key-x_http_method_override_enabled)

- Since 1.3.0

This boolean flag determines whether or not the `HttpMethodOverrideListener`will be enabled by default.

#### Key: `http_override_methods`

[](#key-http_override_methods)

- Since 1.3.0

The `http_override_methods` key is utilized to provide the `HttpMethodOverrideListener` with a map of allowed override methods for a given HTTP method, as specified via the `X-HTTP-Method-Override` header. Essentially, the values are:

```
'Incoming HTTP request method' => $arrayOfAllowedOverrideMethods,
```

As an example, if you want to allow the `X-HTTP-Method-Override` header to allow overriding HTTP `GET` requests with an alternate method, you might define this as follows:

```
'x_http_method_override_enabled' => true,
'http_override_methods' => [
    'GET' => [
        'HEAD',
        'POST',
        'PUT',
        'DELETE',
        'PATCH',
    ],
];
```

Then, to make a request, you could do the following:

```
GET /foo HTTP/1.1
Host: example.com
X-HTTP-Method-Override: PATCH

some=content&more=content
```

The above would then be interpreted as a `PATCH` request. If the same request were made via HTTP `POST`, or if a `GET` request were made with an override value of `OPTIONS`, the listener would raise a problem, as, in the former case, no maps are defined for `POST`, and, in the latter, `OPTIONS` is not in the map for `GET`.

### System Configuration

[](#system-configuration)

The following configuration is provided in `config/module.config.php` to enable the module to function:

```
'filters' => [
    'aliases'   => [
        'Zend\Filter\File\RenameUpload' => 'filerenameupload',
    ],
    'factories' => [
        'filerenameupload' => Factory\RenameUploadFilterFactory::class,
    ],
],

'validators' => [
    'aliases'   => [
        'Zend\Validator\File\UploadFile' => 'fileuploadfile',
    ],
    'factories' => [
        'fileuploadfile' => Factory\UploadFileValidatorFactory::class,
    ],
],

'service_manager' => [
    'factories' => [
        ContentTypeListener::class        => InvokableFactory::class,
        'Request'                         => Factory\RequestFactory::class,
        AcceptListener::class             => Factory\AcceptListenerFactory::class,
        AcceptFilterListener::class       => Factory\AcceptFilterListenerFactory::class,
        ContentTypeFilterListener::class  => Factory\ContentTypeFilterListenerFactory::class,
        ContentNegotiationOptions::class  => Factory\ContentNegotiationOptionsFactory::class,
        HttpMethodOverrideListener::class => Factory\HttpMethodOverrideListenerFactory::class,
    ],
],

'controller_plugins' => [
    'aliases' => [
        'routeParam'  => ControllerPlugin\RouteParam::class,
        'queryParam'  => ControllerPlugin\QueryParam::class,
        'bodyParam'   => ControllerPlugin\BodyParam::class,
        'routeParams' => ControllerPlugin\RouteParams::class,
        'queryParams' => ControllerPlugin\QueryParams::class,
        'bodyParams'  => ControllerPlugin\BodyParams::class,
    ],
    'factories' => [
        ControllerPlugin\RouteParam::class  => InvokableFactory::class,
        ControllerPlugin\QueryParam::class  => InvokableFactory::class,
        ControllerPlugin\BodyParam::class   => InvokableFactory::class,
        ControllerPlugin\RouteParams::class => InvokableFactory::class,
        ControllerPlugin\QueryParams::class => InvokableFactory::class,
        ControllerPlugin\BodyParams::class  => InvokableFactory::class,
    ],
],
```

ZF Events
---------

[](#zf-events)

### Listeners

[](#listeners)

#### ZF\\ContentNegotiation\\AcceptListener

[](#zfcontentnegotiationacceptlistener)

This listener is attached to the `MvcEvent::EVENT_DISPATCH` event with priority `-10`. It is responsible for performing the actual selection and casting of a controller's view model based on the content negotiation configuration.

#### ZF\\ContentNegotiation\\ContentTypeListener

[](#zfcontentnegotiationcontenttypelistener)

This listener is attached to the `MvcEvent::EVENT_ROUTE` event with a priority of `-625`. It is responsible for examining the `Content-Type` header in order to determine how the content body should be deserialized. Values are then persisted inside of a `ParameterDataContainer` which is stored in the `ZFContentNegotiationParameterData` key of the `MvcEvent` object.

#### ZF\\ContentNegotiation\\AcceptFilterListener

[](#zfcontentnegotiationacceptfilterlistener)

This listener is attached to the `MvcEvent::EVENT_ROUTE` event with a priority of `-625`. It is responsible for ensuring the controller selected by routing is configured to respond to the specific media type in the current request's `Accept` header. If it cannot, it will short-circuit the MVC dispatch process by returning a `406 Cannot honor Accept type specified` response.

#### ZF\\ContentNegotiation\\ContentTypeFilterListener

[](#zfcontentnegotiationcontenttypefilterlistener)

This listener is attached to the `MvcEvent::EVENT_ROUTE` event with a priority of `-625`. It is responsible for ensuring the route matched controller can accept content in the request body specified by the media type in the current request's `Content-Type` header. If it cannot, it will short-circuit the MVC dispatch process by returning a `415 Invalid content-type specified` response.

#### ZF\\ContentNegotiation\\HttpMethodOverrideListener

[](#zfcontentnegotiationhttpmethodoverridelistener)

- Since 1.3.0

This listener is attached to the `MvcEvent::EVENT_ROUTE` event with a priority of `-40`, but only if the `x_http_method_override_enabled` configuration flag was toggle on. It is responsible for checking if an `X-HTTP-Method-Override`header is present, and, if so, if it contains a value in the set allowed for the current HTTP request method invoked. If so, it resets the HTTP request method to the header value.

ZF Services
-----------

[](#zf-services)

### Controller Plugins

[](#controller-plugins)

#### ZF\\ContentNegotiation\\ControllerPlugin\\RouteParam (a.k.a "routeParam")

[](#zfcontentnegotiationcontrollerpluginrouteparam-aka-routeparam)

A controller plugin (`Zend\Mvc\Controller\AbstractActionController` callable) that will return a single parameter with a particular name from the route match.

```
use Zend\Mvc\Controller\AbstractActionController;

class IndexController extends AbstractActionController
{
    public function indexAction()
    {
        return $this->routeParam('id', 'someDefaultValue');
    }
}
```

#### ZF\\ContentNegotiation\\ControllerPlugin\\QueryParam (a.k.a "queryParam")

[](#zfcontentnegotiationcontrollerpluginqueryparam-aka-queryparam)

A controller plugin (`Zend\Mvc\Controller\AbstractActionController` callable) that will return a single parameter from the current request query string.

```
use Zend\Mvc\Controller\AbstractActionController;

class IndexController extends AbstractActionController
{
    public function indexAction()
    {
        return $this->queryParam('foo', 'someDefaultValue');
    }
}
```

#### ZF\\ContentNegotiation\\ControllerPlugin\\BodyParam (a.k.a "bodyParam")

[](#zfcontentnegotiationcontrollerpluginbodyparam-aka-bodyparam)

A controller plugin (`Zend\Mvc\Controller\AbstractActionController` callable) that will return a single parameter from the content-negotiated content body.

```
use Zend\Mvc\Controller\AbstractActionController;

class IndexController extends AbstractActionController
{
    public function indexAction()
    {
        return $this->bodyParam('foo', 'someDefaultValue');
    }
}
```

#### ZF\\ContentNegotiation\\ControllerPlugin\\RouteParams (a.k.a "routeParams")

[](#zfcontentnegotiationcontrollerpluginrouteparams-aka-routeparams)

A controller plugin (`Zend\Mvc\Controller\AbstractActionController` callable) that will return a all the route parameters.

```
use Zend\Mvc\Controller\AbstractActionController;

class IndexController extends AbstractActionController
{
    public function indexAction()
    {
        return $this->routeParams()
    }
}
```

#### ZF\\ContentNegotiation\\ControllerPlugin\\QueryParams (a.k.a "queryParams")

[](#zfcontentnegotiationcontrollerpluginqueryparams-aka-queryparams)

A controller plugin (`Zend\Mvc\Controller\AbstractActionController` callable) that will return a all the query parameters.

```
use Zend\Mvc\Controller\AbstractActionController;

class IndexController extends AbstractActionController
{
    public function indexAction()
    {
        return $this->queryParams()
    }
}
```

#### ZF\\ContentNegotiation\\ControllerPlugin\\BodyParams (a.k.a "bodyParams")

[](#zfcontentnegotiationcontrollerpluginbodyparams-aka-bodyparams)

A controller plugin (`Zend\Mvc\Controller\AbstractActionController` callable) that will return a all the content-negotiated body parameters.

```
use Zend\Mvc\Controller\AbstractActionController;

class IndexController extends AbstractActionController
{
    public function indexAction()
    {
        return $this->bodyParams()
    }
}
```

###  Health Score

45

—

FairBetter than 93% of packages

Maintenance13

Infrequent updates — may be unmaintained

Popularity51

Moderate usage in the ecosystem

Community36

Small or concentrated contributor base

Maturity69

Established project with proven stability

 Bus Factor1

Top contributor holds 85.1% 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 ~59 days

Recently: every ~143 days

Total

29

Last Release

2933d ago

Major Versions

0.9.1 → 1.0.0beta12014-03-18

PHP version history (6 changes)0.6.0PHP &gt;=5.3.3

0.8.0PHP &gt;=5.4.8

0.9.0PHP &gt;=5.3.23

1.1.0PHP &gt;=5.5

1.1.2PHP ^5.5

1.2.0PHP ^5.6 || ^7.0

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/296074?v=4)[Zend Framework](/maintainers/zendframework)[@zendframework](https://github.com/zendframework)

---

Top Contributors

[![weierophinney](https://avatars.githubusercontent.com/u/25943?v=4)](https://github.com/weierophinney "weierophinney (338 commits)")[![ralphschindler](https://avatars.githubusercontent.com/u/76674?v=4)](https://github.com/ralphschindler "ralphschindler (15 commits)")[![michalbundyra](https://avatars.githubusercontent.com/u/7423207?v=4)](https://github.com/michalbundyra "michalbundyra (15 commits)")[![func0der](https://avatars.githubusercontent.com/u/529819?v=4)](https://github.com/func0der "func0der (7 commits)")[![MichaelGooden](https://avatars.githubusercontent.com/u/1275012?v=4)](https://github.com/MichaelGooden "MichaelGooden (3 commits)")[![neeckeloo](https://avatars.githubusercontent.com/u/1768645?v=4)](https://github.com/neeckeloo "neeckeloo (3 commits)")[![Wilt](https://avatars.githubusercontent.com/u/2419627?v=4)](https://github.com/Wilt "Wilt (3 commits)")[![ezimuel](https://avatars.githubusercontent.com/u/475967?v=4)](https://github.com/ezimuel "ezimuel (2 commits)")[![pdaw](https://avatars.githubusercontent.com/u/8472239?v=4)](https://github.com/pdaw "pdaw (1 commits)")[![samsonasik](https://avatars.githubusercontent.com/u/459648?v=4)](https://github.com/samsonasik "samsonasik (1 commits)")[![TomHAnderson](https://avatars.githubusercontent.com/u/493920?v=4)](https://github.com/TomHAnderson "TomHAnderson (1 commits)")[![matiasfuster](https://avatars.githubusercontent.com/u/10004100?v=4)](https://github.com/matiasfuster "matiasfuster (1 commits)")[![bakura10](https://avatars.githubusercontent.com/u/1198915?v=4)](https://github.com/bakura10 "bakura10 (1 commits)")[![boteeka](https://avatars.githubusercontent.com/u/877397?v=4)](https://github.com/boteeka "boteeka (1 commits)")[![ddubau](https://avatars.githubusercontent.com/u/75494?v=4)](https://github.com/ddubau "ddubau (1 commits)")[![kusmierz](https://avatars.githubusercontent.com/u/404344?v=4)](https://github.com/kusmierz "kusmierz (1 commits)")[![leogr](https://avatars.githubusercontent.com/u/3390997?v=4)](https://github.com/leogr "leogr (1 commits)")[![marc-mabe](https://avatars.githubusercontent.com/u/302689?v=4)](https://github.com/marc-mabe "marc-mabe (1 commits)")[![adamculp](https://avatars.githubusercontent.com/u/284451?v=4)](https://github.com/adamculp "adamculp (1 commits)")

---

Tags

ZendFrameworkzfmodulecontent negotiation

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/zfcampus-zf-content-negotiation/health.svg)

```
[![Health](https://phpackages.com/badges/zfcampus-zf-content-negotiation/health.svg)](https://phpackages.com/packages/zfcampus-zf-content-negotiation)
```

###  Alternatives

[stroker/form

ZF2 module for extending forms with live clientside validation

4157.1k](/packages/stroker-form)[hrevert/ht-img-module

Image manipulation module for Zend Framework 2

1829.6k2](/packages/hrevert-ht-img-module)[evandotpro/edp-github

Github API integration module for Zend Framework 2

241.6k](/packages/evandotpro-edp-github)

PHPackages © 2026

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