PHPackages                             foxdie/rest - 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. foxdie/rest

ActiveLibrary[API Development](/categories/api)

foxdie/rest
===========

PHP RESTful API microframework

0.3.4(5y ago)10834[1 issues](https://github.com/foxdie/plankton/issues)[1 PRs](https://github.com/foxdie/plankton/pulls)MITPHPPHP &gt;=7.2.0

Since Jun 30Pushed 5y ago1 watchersCompare

[ Source](https://github.com/foxdie/plankton)[ Packagist](https://packagist.org/packages/foxdie/rest)[ RSS](/packages/foxdie-rest/feed)WikiDiscussions master Synced 3d ago

READMEChangelogDependencies (1)Versions (20)Used By (0)

Plankton: a RESTful API microframework
======================================

[](#plankton-a-restful-api-microframework)

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

[](#requirements)

- PHP &gt;= 7.2
- PHP cURL extension
- Apache HTTP Server &gt;= 2.4
- Apache mod\_rewrite enabled

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

[](#installation)

composer require foxdie/rest

Table of content
----------------

[](#table-of-content)

- [Client](#client)
    - [Creating a client](#creating-a-client)
    - [GET example](#get-example)
        - [using callback](#using-callback)
        - [using magic](#using-magic)
    - [POST example](#post-example)
        - [using callback](#using-callback-1)
        - [using magic](#using-magic-1)
    - [PUT, PATCH and DELETE examples](#put--patch-and-delete-examples)
    - [Content types](#content-types)
    - [Custom request example](#custom-request-example)
    - [Magic calls](#magic-calls)
        - [Spinal case](#spinal-case)
        - [Examples](#examples)
    - [Authentication strategy](#authentication-strategy)
        - [anonymous auth](#anonymous-auth)
        - [basic auth](#basic-auth)
        - [client credentials](#client-credentials)
- [Server](#server)
    - [Creating a server](#creating-a-server)
    - [Handling requests](#handling-requests)
        - [Using a config file](#using-a-config-file)
            - [Example of config file](#example-of-config-file)
            - [Configure the server](#configure-the-server)
        - [Using annotations](#using-annotations)
            - [@Route annotation](#-route-annotation)
            - [@Method annotation](#-method-annotation)
            - [@Exception annotation](#-exception-annotation)
    - [Registering controllers](#registering-controllers)
    - [Creating middlewares](#creating-middlewares)
    - [Registering the middlewares](#registering-the-middlewares)
- [OAuth2](#oauth2)
    - [Client Credentials Grant](#client-credentials-grant)
        - [Client](#client-1)
        - [Server](#server-1)
            - [Creating your own Access Token Provider](#creating-your-own-access-token-provider)
- [Logging](#logging)
    - [Client side](#client-side)
        - [Simple logger](#simple-logger)
        - [XML logger](#xml-logger)
        - [Custom logger](#custom-logger)
    - [Server side](#server-side)

Client
------

[](#client)

### Creating a client

[](#creating-a-client)

```
use Plankton\Client\Client;

$client = new Client(API_ENDPOINT);
```

Full example here:

### GET example

[](#get-example)

```
$response = $client->get("/users");
```

#### using callback

[](#using-callback)

```
$client->get("/users", function(Response $response){
	echo $response;
});
```

#### using magic

[](#using-magic)

```
$response = $client->getUsers();
```

### POST example

[](#post-example)

```
$response = $client->post("/users", ["email" => "foo@bar.com"]);
```

#### using callback

[](#using-callback-1)

```
$client->post("/users", ["email" => "foo@bar.com"], function(Response $response){
	echo $response->getLocation();
});
```

#### using magic

[](#using-magic-1)

```
$response = $client->postUsers(["email" => "foo@bar.com"]);
```

### PUT, PATCH and DELETE examples

[](#put-patch-and-delete-examples)

Full example here:

### Magic calls

[](#magic-calls)

#### Spinal case

[](#spinal-case)

If you want to use magic calls, your routes must use the spinal case Example:

```
$client->getUserAccounts()

```

will match the following route:

```
GET /user-accounts

```

camel case and snake case are not supported

#### Examples

[](#examples)

callroute$client-&gt;getUsers();GET /users$client-&gt;groups(1)-&gt;getUsers();GET /groups/1/users$client-&gt;groups(1)-&gt;getUsers(2);GET /groups/1/users/2$client-&gt;postUsers(\[\]);POST /users$client-&gt;groups(1)-&gt;postUsers(\[\]);POST /groups/1/users$client-&gt;deleteUsers(1);DELETE /users/1$client-&gt;users(1)-&gt;delete();DELETE /users/1$client-&gt;groups(1)-&gt;deleteUsers(2);DELETE /groups/1/users/2$client-&gt;groups(1)-&gt;users(2)-&gt;delete();DELETE /groups/1/users/2$client-&gt;groups(1)-&gt;users()-&gt;delete(2);DELETE /groups/1/users/2### Content types

[](#content-types)

When you are using magic calls (e.g. `$client->postUsers([]);`) or one of the methods `Client::post()`, `Client::put()`, `Client::patch()`, a `Content-Type` header is automatically added to the request. The `Content-Type` is automatically guessed according to the data you send to the server :

data typeContent-Typearrayapplication/x-www-form-urlencodedobjectapplication/jsonvalid json stringapplication/jsonvalid xml stringapplication/xmlstringtext/plainHowever, you still can set the `Content-Type` manually with a [customized request](#custom-request-example)

### Custom request example

[](#custom-request-example)

```
use Plankton\Client\Client;
use Plankton\Request;

$request = new Request(API_ENDPOINT . "/users");
$request
    ->setMethod(Request::METHOD_POST)
    ->setParameter("foo", "bar")
    ->setHeader("User-Agent", "Mozilla/5.0")
    ->setContentType(Request::CONTENT_TYPE_JSON)
    ->setData(["email" => "foo@bar.com"]);

$client = new Client(API_ENDPOINT);
$client->send($request, function(Response $response){
    // ...
});
```

#### Automatic data conversion

[](#automatic-data-conversion)

For readability reasons, you can use `arrays` or `objects` with the `Request::setData()` method, regardless of the content-type you use. The data will be automatically converted according to the rules below :

Content-TypeData typeConversionRequest::CONTENT\_TYPE\_JSONarrayjson stringRequest::CONTENT\_TYPE\_JSONobjectjson stringotherarrayURL-encoded query stringotherobjectURL-encoded query string### Authentication strategy

[](#authentication-strategy)

#### anonymous auth

[](#anonymous-auth)

```
$client = new Client(API_ENDPOINT);
```

#### basic auth

[](#basic-auth)

```
use Plankton\Client\Strategy\BasicAuthentication;

$client = new Client(API_ENDPOINT, new BasicAuthentication(USER, PASSWORD));
```

#### client credentials

[](#client-credentials)

```
use Plankton\Client\Strategy\ClientCredentialsAuthentication;

$client = new Client(API_ENDPOINT, new ClientCredentialsAuthentication(
	CLIENT_ID,
	CLIENT_SECRET,
	AUTHENTICATION_URL
));
```

The authorize and access/refresh token requests will be performed automatically. The 3rd parameter is optionnal, the default value is "/token"

Server
------

[](#server)

### Creating a server

[](#creating-a-server)

```
use Plankton\Server\Server;

$server = new Server();
$server->run();
```

Full example here:

### Creating controllers

[](#creating-controllers)

You must create at least one controller which extends the abstract class Plankton\\Server\\Controller

```
use Plankton\Server\Controller;

class APIController extends Controller{
	public function getUsers(int $id, Request $request): Response{
	}

	public function postUsers(Request $request): Response{
	}
}
```

Your controller will contain one public method for each action of your API.

You can create routes in 2 different ways:

- using a config file
- using annotations

#### Using a config file

[](#using-a-config-file)

This will automatically disable the annotation parser. The routes are described in a YAML file

##### Example of config file

[](#example-of-config-file)

```
routes:
    get-user:
        path: /users/{id}
        method: GET
        controller: Test\Controller\APIController::getUser
    create-user:
        path: /users
        method: POST
        controller: Test\Controller\APIController::createUser
```

Full example here:

##### Configuring the server

[](#configuring-the-server)

```
use Plankton\Server\{Server, Config};

$server = new Server(new Config(CONFIG_PATH));
```

Full example here:

#### Using annotations

[](#using-annotations)

```
use Plankton\Server\Controller;

class APIController extends Controller{
	/**
	 * @Route(/users/{id})
	 * @Method(GET)
	 */
	public function getUser(int $id, Request $request): Response{
	}

	/**
	 * @Route(/users)
	 * @Method(POST)
	 */
	public function createUser(Request $request): Response{
	}
}
```

The routes will be created automatically according to the annotations @Route and @Method.

Full example here :

##### @Route annotation

[](#route-annotation)

- accepts regular expresssions
- accepts placeholders: they will be passed as argument in the same order as they appear
- the spinal case is strongly recommended

You can add a route prefix to your controller:

```
/**
 * @Route(/users)
 */
class APIController extends Controller{
	/**
	 * @Route(/{id})
	 * @Method(GET)
	 */
	public function getUser(int $id, Request $request): Response{
	}

	/**
	 * @Route(/)
	 * @Method(POST)
	 */
	public function createUser(Request $request): Response{
	}
}
```

##### @Method annotation

[](#method-annotation)

Possible values are:

- GET
- POST
- PUT
- PATCH
- DELETE

##### @Exception annotation

[](#exception-annotation)

```
class APIController extends Controller{
	/**
	 * This will catch any \CustomNameSpace\CustomException
	 * @Exception(CustomNameSpace\CustomException)
	 */
	public function catchCustomException(Exception $e, Request $request): Response{
	}

	/**
	 * This will catch all other exceptions
	 * @Exception(*)
	 */
	public function catchException(Exception $e, Request $request): Response{
	}
}
```

### Registering controllers

[](#registering-controllers)

```
use Plankton\Server\Server;

$server = new Server();
$server
	->registerController(new APIController());
	->registerController(...);
	->run();
```

Full example here:

### Creating middlewares

[](#creating-middlewares)

(this is optionnal) You must implement the Plankton\\Server\\Middleware interface. The middlewares can handle both incoming requests and outgoing responses.

```
use Plankton\Server\{Request, Response};
use Plankton\Server\{Middleware, RequestDispatcher};

class BasicAuthenticationMiddleware implements Middleware{
	public function process(Request $request, RequestDispatcher $dispatcher): Response{
		// ...
		return $dispatcher->process($request);
	}
}
```

Full example here:

### Registering the middlewares

[](#registering-the-middlewares)

```
use Plankton\Server\Server;

$server = new Server();
$server
	->addMiddleware(new BasicAuthenticationMiddleware())
	->addMiddleware(...)
	->registerController(new APIController())
	->run();
```

OAuth2
------

[](#oauth2)

### Client Credentials Grant

[](#client-credentials-grant)

#### Client

[](#client-1)

```
use Plankton\Client\Client;
use Plankton\Client\Strategy\ClientCredentialsAuthentication;
use Plankton\Response;

$client = new Client(API_ENDPOINT, new ClientCredentialsAuthentication(
	CLIENT_ID,
	CLIENT_SECRET,
	AUTHENTICATION_URL
));
```

Full example here:

#### Server

[](#server-1)

```
use Plankton\Server\Server;
use OAuth2\Middleware\ClientCredentialsMiddleware;
use OAuth2\Provider\MemoryProvider;
use Test\Controller\APIController;

// Access Token provider
$provider = new MemoryProvider();
$provider->addClient(CLIENT_ID, CLIENT_SECRET);

$server = new Server();
$server
	->addMiddleware(new ClientCredentialsMiddleware($provider))
	->registerController(new APIController())
	->run();
```

Full example here:

##### Creating your own Access Token Provider

[](#creating-your-own-access-token-provider)

All you have to do is to implement the AccessTokenProvider interface:

```
use Plankton\OAuth2\Provider\AccessTokenProvider;
use Plankton\OAuth2\Token\{AccessToken, BearerToken};

class PDOProvider implements AccessTokenProvider{
	/**
	 * return a new/issued Access Token if you find a client matching the authentication parameters (id + secret)
	 */
	public function getAccessToken(string $client_id, string $client_secret): ?AccessToken{
	}

	/**
	 * return a new Access Token if the Refresh Token is valid
	 */
	public function refreshToken(string $refreshToken): ?AccessToken{
	}

	/**
	 * authorize or not the given Access Token
	 */
	public function isValidAccessToken(string $token): bool{
	}
}
```

Logging
-------

[](#logging)

### Client side

[](#client-side)

#### Simple logger

[](#simple-logger)

```
use Plankton\Logging\SimpleLogger;

$client->setLogger(new SimpleLogger());

// ... do some requests

foreach ($client->getLogger()->getLogs() as $request) {
	$response = $client->getLogger()->getLogs()[$request];
}
```

Full example here:

#### XML logger

[](#xml-logger)

```
use Plankton\Logging\XMLLogger;

$client->setLogger(new XMLLogger());

// ... do some requests

header("Content-type: text/xml");
echo $client->getLogger()->getLogs()->asXML();
```

Full example here:

#### Custom logger

[](#custom-logger)

You have to implement the Plankton\\Request\\Logger interface:

```
use Plankton\{Request,Response};
use Plankton\Request\Logger

class CustomLogger implements Logger{
	public function log(Request $request, Response $response = NULL): void{
	}
}
```

### Server side

[](#server-side)

You can easily log requests and responses by [adding a middleware](#creating-middlewares):

```
use Plankton\{Request,Response};
use Plankton\Server\{Middleware, RequestDispatcher};

class LogMiddleware implements Middleware{
	public function process(Request $request, RequestDispatcher $dispatcher): Response{
		$response = $dispatcher->process($request);

		// log $request and $response here

		return $response
	}
}
```

and then register the middleware(#registering-the-middlewares)

```
use Plankton\Server\Server;
use Test\Controller\APIController;
use Test\Middleware\LogMiddleware;

$server = new Server();
$server
	->addMiddleware(new LogMiddleware())
	->registerController(new APIController())
	->run();
```

###  Health Score

28

—

LowBetter than 54% of packages

Maintenance18

Infrequent updates — may be unmaintained

Popularity18

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity57

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 ~62 days

Recently: every ~167 days

Total

18

Last Release

2179d ago

PHP version history (2 changes)0.1.0PHP &gt;=5.6.0

0.1.7PHP &gt;=7.2.0

### Community

Maintainers

![](https://www.gravatar.com/avatar/54102a5289ef5c60523dcb24119f263bcfcad6494034daf09dd87ebf159a326f?d=identicon)[foxdie](/maintainers/foxdie)

---

Top Contributors

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

---

Tags

apiclientmiddlewarephprestrestfullserver

### Embed Badge

![Health badge](/badges/foxdie-rest/health.svg)

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

###  Alternatives

[sylius/sylius

E-Commerce platform for PHP, based on Symfony framework.

8.4k5.6M651](/packages/sylius-sylius)[darkaonline/l5-swagger

OpenApi or Swagger integration to Laravel

2.9k34.0M112](/packages/darkaonline-l5-swagger)[statamic/cms

The Statamic CMS Core Package

4.8k3.2M720](/packages/statamic-cms)[knuckleswtf/scribe

Generate API documentation for humans from your Laravel codebase.✍

2.3k12.2M45](/packages/knuckleswtf-scribe)[currency-cloud/client

A PHP library which implements the complete functionality of v2 of the The Currency Cloud API.

17327.2k](/packages/currency-cloud-client)

PHPackages © 2026

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