PHPackages                             adamstipak/nette-rest-route - 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. adamstipak/nette-rest-route

ActiveLibrary[Framework](/categories/framework)

adamstipak/nette-rest-route
===========================

Rest route for Nette Framework

5.0.0(3mo ago)67150.8k↓12.5%25MITPHPPHP ^8.1CI failing

Since Mar 31Pushed 3mo ago10 watchersCompare

[ Source](https://github.com/newPOPE/Nette-RestRoute)[ Packagist](https://packagist.org/packages/adamstipak/nette-rest-route)[ Docs](https://github.com/newPOPE/Nette-RestRoute)[ RSS](/packages/adamstipak-nette-rest-route/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (3)Dependencies (6)Versions (23)Used By (0)

REST route for [Nette Framework](http://nette.org)
==================================================

[](#rest-route-for-nette-framework)

Route automatically maps CRUD to Presenters and actions in the defined module. And creates parameters which are accessible in Presenter.

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

[](#requirements)

- PHP 8.1+
- Nette 3.2+
- format
- id (autodetected)
- associations (an array with associations)
- data (raw data from the request)
- query (an array of items from the query string)

Format detection:
-----------------

[](#format-detection)

Variable `$format` is detected from HTTP header `Accept`. If header is not present Route try detect format from the URL (`.../foo.json`). If no format is in the URL Route use a default format `json`.

Installation:
-------------

[](#installation)

The best way to install Nette-RestRoute is using [Composer](http://getcomposer.org/):

```
$ composer require adamstipak/nette-rest-route
```

Usage:
------

[](#usage)

```
use AdamStipak\RestRoute;

// $router is an instance of Nette\Application\Routers\RouteList

// No parameters needed. Presenter name will be generated.
$router[] = new RestRoute;

// With module.
$router[] = new RestRoute('Api');

// With module and xml as a default format.
$router[] = new RestRoute('Api', 'xml');

// With URL module versioning
$router[] = (new RestRoute())
    ->useURLModuleVersioning(
        '/v[0-9\.]+/',     // Regex for URL version
        [                  // URL fragment to module mapping
          NULL => 'V1',    // Default version module is V1
          'v1' => 'V1',    // /v1 to module V1
          'v2' => 'V2'     // /v2 to module V2
        ]
    );
```

First parameter is a name of the module where the route will sends an Request. URL prefix will be generated. See examples. ####Examples:

```
NULL      => /
'Api'     => /api/
'My:Api'  => /my/api/
...

```

Second parameter is default format. By default the default format is `json`. RestRoute support only 2 formats:

- json *(default)*
- xml

Examples
--------

[](#examples)

### Read all:

[](#read-all)

**URL:** `/api/users` → `\ApiModule\UsersPresenter::actionReadAll`
**HTTP HEADER Accept:** `application/json`
**Method:** GET
**Request body:** Empty
**Params:**

```
format = json
associations = array(0)
data = ""
query = array(0)

```

> Flag `readAll` was dropped and `Route` automatically generate action `readAll` if no Resource ID was not found in the URL.

---

### Read with resource ID

[](#read-with-resource-id)

**URL:** `/api/users/123` → `\ApiModule\UsersPresenter::actionRead`
**HTTP HEADER Accept:** `application/json`
**Method:** GET
**Request body:** Empty
**Params:**

```
format = json
id = 123
associations = array(0)
data = ""
query = array(0)

```

---

### Query params:

[](#query-params)

**URL:** `/api/users?foo=bar&page=1` → `\ApiModule\UsersPresenter::actionReadAll`
**HTTP HEADER Accept:** `application/json`
**Method:** GET
**Request body:** Empty
**Params:**

```
format = json
associations = array(0)
data = ""
query = array(
	foo => "bar"
	page => 1
)

```

---

### Create:

[](#create)

**URL:** `/api/users` → `\ApiModule\UsersPresenter::actionCreate`
**HTTP HEADER Accept:** `application/json`
**Method:** POST
**Request body:**

```
{
	"foo": "bar",
	"nested": {
		"foo": "bar"
	}
}
```

**Params:**

```
format = json
associations = array(0)
data = {"foo": "bar", "nested": {"foo": "bar"}}
query = array(0)

```

---

### Update:

[](#update)

**URL:** `/api/users/123` → `\ApiModule\UsersPresenter::actionUpdate`
**HTTP HEADER Accept:** `application/json`
**Method:** PUT
**Request body:**

```
{
	"foo": "bar",
	"nested": {
		"foo": "bar"
	}
}
```

**Params:**

```
format = json
id = 123
associations = array(0)
data = {"foo": "bar", "nested": {"foo": "bar"}}
query = array(0)

```

---

### Partial update:

[](#partial-update)

**URL:** `/api/users/123` → `\ApiModule\UsersPresenter::actionPartialUpdate`
**HTTP HEADER Accept:** `application/json`
**Method:** PATCH
**Request body:**

```
{
	"foo": "bar",
	"nested": {
		"foo": "bar"
	}
}
```

**Params:**

```
format = json
id = 123
associations = array(0)
data = {"foo": "bar", "nested": {"foo": "bar"}}
query = array(0)

```

---

### Delete:

[](#delete)

**URL:** `/api/users/123` → `\ApiModule\UsersPresenter::actionDelete`
**HTTP HEADER Accept:** `application/json`
**Method:** DELETE
**Request body:** Empty
**Params:**

```
format = json
id = 123
associations = array(0)
data = ""
query = array(0)

```

---

### Options:

[](#options)

For more about OPTIONS documentation see [w3.org](http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.2).

**URL:** `/api/users` → `\ApiModule\UsersPresenter::actionOptions`
**HTTP HEADER Accept:** `application/json`
**Method:** OPTIONS
**Request body:** Empty
**Params:**

```
format = json
associations = array(0)
data = ""
query = array(0)

```

---

### Associations:

[](#associations)

Last item (pair) before . is main resource. Everything what is before the last item are associations ([apigee.com](http://apigee.com/about/)).

**URL:** `/api/users/1/comments` → `\ApiModule\CommentsPresenter::actionReadAll|actionCreate|actionUpdate|actionDelete`
**HTTP HEADER Accept:** `application/json`
**Method:** GET, POST, PUT, DELETE
**Request body:** Empty
**Params:**

```
format = json
associations = array(
	users => 1
)
data = ""
query = array(0)

```

**URL:** `/api/users/123/comments/456` → `\ApiModule\CommentsPresenter::actionRead|actionCreate|actionUpdate|actionDelete`
**HTTP HEADER Accept:** `application/json`
**Method:** GET, POST, PUT, DELETE
**Request body:** Empty
**Params:**

```
format = json
id = 456
associations = array(
	users => 123
)
data = ""
query = array(0)

```

**URL:** `/api/users/1/blogs/2/comments` → `\ApiModule\CommentsPresenter::actionReadAll|actionCreate|actionUpdate|actionDelete`
**HTTP HEADER Accept:** `application/json`
**Method:** GET, POST, PUT, DELETE
**Request body:** Empty
**Params:**

```
format = json
id = 1
associations = array(
	users => 1
	blogs => 2
)
data = ""
query = array(0)

```

---

### URL versioning:

[](#url-versioning)

RestRoute provides you with option to version your API in URL. Each version is represented by separate module in your application.

First, you define regexp which is used to detect if the version parameter is present in URL. It must be in the begging of the path. Then, you define version to module mapping. `NULL` key stands for default module, if version parameter doesn't get detected.

```
$router[] = (new RestRoute('Api')) // Optional module
    ->useURLModuleVersioning(
        RestRoute::MODULE_VERSION_PATH_PREFIX_PATTERN,     // Regex for URL version
        [                  // URL fragment to module mapping
          NULL => 'V1',    // Default version module is V1
          'v1' => 'V1',    // /v1 to module V1
          'v2' => 'V2'     // /v2 to module V2
        ]
    );
```

RestRoute will now map your requests to presenters like this (URL -&gt; Presenter):

```
/api/foo        ->  Api:V1:Foo
/api/v1/foo     ->  Api:V1:Foo
/api/v2/foo     ->  Api:V2:Foo

```

---

### File uploads:

[](#file-uploads)

RestRoute reads standard [PHP input](https://github.com/newPOPE/Nette-RestRoute/blob/master/src/RestRoute.php#L202) and data puts to `$data` param in action. This is fit for one file upload or upload with chunks because it is a RAW data.

For multiple file upload RestRoute just set files when creates [`\Nette\Application\Request`](https://github.com/newPOPE/Nette-RestRoute/blob/master/src/RestRoute.php#L125). In presenter just inject `\Nette\Application\Request` service and use these files.

```
class FooPresenter {
  /** @var \Nette\Application\Request @inject */
  public $request;

  public function actionCreate () {
    $files = $this->request->getFiles();
  }
}
```

Development
-----------

[](#development)

RestRoute is developed in [Docker](https://docker.com) container via `docker compose` command.

Example:

```
$ docker compose run --rm default install  # install deps via composer
$ docker compose run --rm default  # runs tests in container
```

Attach to container:

```
$ docker compose run --rm default bash # runs bash in container and attach tty
```

###  Health Score

62

—

FairBetter than 99% of packages

Maintenance82

Actively maintained with recent releases

Popularity46

Moderate usage in the ecosystem

Community23

Small or concentrated contributor base

Maturity81

Battle-tested with a long release history

 Bus Factor1

Top contributor holds 88.4% 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 ~224 days

Recently: every ~851 days

Total

22

Last Release

94d ago

Major Versions

1.2.0 → 2.0.02013-09-24

2.6.1 → 3.0.02016-02-17

3.1.1 → 4.0.02018-01-28

4.0.2 → 5.0.02026-02-14

PHP version history (4 changes)3.0.0PHP &gt;=5.6.0

3.1.0PHP ^5.6|^7.0

4.0.0PHP ^7.0

5.0.0PHP ^8.1

### Community

Maintainers

![](https://www.gravatar.com/avatar/bd08d54312d99f264d4d7a8234b009ef3f6321b018c6b44209921e90f4ce67cc?d=identicon)[newPOPE](/maintainers/newPOPE)

---

Top Contributors

[![newPOPE](https://avatars.githubusercontent.com/u/484382?v=4)](https://github.com/newPOPE "newPOPE (122 commits)")[![freezy-sk](https://avatars.githubusercontent.com/u/661637?v=4)](https://github.com/freezy-sk "freezy-sk (5 commits)")[![michal-loksik](https://avatars.githubusercontent.com/u/7481736?v=4)](https://github.com/michal-loksik "michal-loksik (3 commits)")[![klimesf](https://avatars.githubusercontent.com/u/5357636?v=4)](https://github.com/klimesf "klimesf (2 commits)")[![jsifalda](https://avatars.githubusercontent.com/u/1549390?v=4)](https://github.com/jsifalda "jsifalda (2 commits)")[![skrivy](https://avatars.githubusercontent.com/u/19331294?v=4)](https://github.com/skrivy "skrivy (1 commits)")[![fabiancz](https://avatars.githubusercontent.com/u/1045330?v=4)](https://github.com/fabiancz "fabiancz (1 commits)")[![khorsky](https://avatars.githubusercontent.com/u/160295?v=4)](https://github.com/khorsky "khorsky (1 commits)")[![f3l1x](https://avatars.githubusercontent.com/u/538058?v=4)](https://github.com/f3l1x "f3l1x (1 commits)")

---

Tags

netterouting

###  Code Quality

TestsPHPUnit

Code StylePHP\_CodeSniffer

### Embed Badge

![Health badge](/badges/adamstipak-nette-rest-route/health.svg)

```
[![Health](https://phpackages.com/badges/adamstipak-nette-rest-route/health.svg)](https://phpackages.com/packages/adamstipak-nette-rest-route)
```

###  Alternatives

[nette/application

🏆 Nette Application: a full-stack component-based MVC kernel for PHP that helps you write powerful and modern web applications. Write less, have cleaner code and your work will bring you joy.

44615.4M983](/packages/nette-application)[nette/web-project

Nette: Standard Web Project

10991.8k](/packages/nette-web-project)[nasext/dependent-select-box

Dependent Select Box for Nette Framework.

21262.8k2](/packages/nasext-dependent-select-box)[o5/grido

Grido - DataGrid for Nette Framework

87290.5k4](/packages/o5-grido)[kdyby/autowired

Syntax sugar for working with services in Nette Framework

30885.7k9](/packages/kdyby-autowired)[nextras/form-components

Form components for Nette Framework.

10242.9k](/packages/nextras-form-components)

PHPackages © 2026

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