nbo / rest-api-bundle
Out of the box generic Symfony 5 REST API backend, transform any Doctrine entity and his relations onto API resources.
Requires
- php: >=7.2.5
- ext-iconv: *
- sensio/framework-extra-bundle: ^5.1
- stof/doctrine-extensions-bundle: ^1.3
- symfony/asset: ^5.1
- symfony/cache: ^5.1
- symfony/debug-pack: ^1.0
- symfony/dotenv: ^5.1
- symfony/expression-language: ^5.1
- symfony/flex: ^1.3.1
- symfony/form: ^5.1
- symfony/framework-bundle: ^5.1
- symfony/http-client: ^5.1
- symfony/intl: ^5.1
- symfony/monolog-bundle: ^3.1
- symfony/orm-pack: *
- symfony/process: ^5.1
- symfony/property-info: 5.1.*
- symfony/security-bundle: ^5.1
- symfony/security-csrf: ^5.1
- symfony/serializer-pack: *
- symfony/translation: ^5.1
- symfony/validator: ^5.1
- symfony/web-link: ^5.1
- symfony/yaml: ^5.1
Requires (Dev)
- doctrine/doctrine-fixtures-bundle: ^3.2
- fzaninotto/faker: ^1.8
- phpunit/phpunit: ^9.3
- symfony/browser-kit: ^5.1
- symfony/console: ^5.1
- symfony/css-selector: ^5.1
- symfony/maker-bundle: ^1.12
- symfony/phpunit-bridge: ^5.1
- symfony/profiler-pack: ^1.0
- symfony/twig-bundle: ^5.1
- symfony/var-dumper: ^5.1
Conflicts
- dev-master
- 1.5.2
- 1.5.1
- 1.5.0
- 1.4.9
- 1.4.8
- 1.4.7
- 1.4.6
- 1.4.5
- 1.4.4
- 1.4.3
- 1.4.2
- 1.4.1
- 1.4.0
- 1.3.3
- 1.3.2
- 1.3.1
- 1.3.0
- 1.2.9
- 1.2.8
- 1.2.7
- 1.2.6
- 1.2.5
- 1.2.4
- 1.2.3
- 1.2.2
- 1.2.1
- 1.2.0
- 1.1.9
- 1.1.8
- 1.1.7
- 1.1.6
- 1.1.5
- 1.1.4
- 1.1.3
- 1.1.3-RC
- 1.1.3-BETA
- 1.1.2
- 1.1.2-RC
- 1.1.2-BETA
- 1.1.1
- 1.1.0
- 1.0.2
- 1.0.1
- 1.0.0
- dev-api-errors
- dev-symfony5
This package is auto-updated.
Last update: 2024-12-16 18:21:24 UTC
README
This bundle is a generic REST API, easily create and configure your API resources using your Doctrine entities.
Setup
$ composer req nbo/restapibundle
Documentation
Getting started
First you need to compose your api. Add a config/packages/rest_api.yml
configuration onto your project.
Here's an example for a simple REST API, with a "user" and a "page" resources.
rest_api:
default_limit: 10
default_offset: 0
default_order: {'id':'desc'}
resources:
user:
classname: 'App\Entity\User'
methods:
get:
authenticated: true
roles: ['ROLE_ADMIN']
post:
authenticated: true
roles: ['ROLE_ADMIN']
put:
authenticated: true
roles: ['ROLE_ADMIN']
delete:
authenticated: true
roles: ['ROLE_ADMIN']
page:
classname: 'App\Entity\Page'
methods:
get: ~
post:
authenticated: true
roles: ['ROLE_CMS']
put:
authenticated: true
roles: ['ROLE_CMS']
delete:
authenticated: true
roles: ['ROLE_CMS']
In this example, all resource endpoints need an authenticated user with specific roles, except the GET /page which is public.
Use cases
Endpoint that require authenticated users
To restrict an endpoint to authenticated users, regardless of their roles, juste use the authenticated
option.
Endpoint that require authenticated users and one or more specific roles
To restrict an endpoint to authenticated users with one or more specific roles, juste use the roles
array option with the needed role(s).
User scoped resource
Sometimes, you need to scope a specific resource at a user level, where users can only see their own resources. Use the owner_restricted
option.to do so.
Public endpoints
By default with no option, the endpoint is public. No authentication is needed.
Update your Doctrine entities
The next step is to transform your Doctrine entities onto API resources.
Here's an example of the User entity transformed onto an API resource.
<?php
namespace App\Entity;
use App\Entity\Traits\TimestampableEntity;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\SoftDeleteable\Traits\SoftDeleteableEntity;
use Nbo\RestApiBundle\Annotations\Resource;
use Nbo\RestApiBundle\Entity\AbstractResource;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Serializer\Annotation\Groups;
/**
* @Resource(name="user")
* @ORM\Entity(repositoryClass="App\Repository\UserRepository")
* @ORM\HasLifecycleCallbacks()
*/
class User extends AbstractResource implements UserInterface
{
const ROLE_ADMIN = 'ROLE_ADMIN';
use TimestampableEntity;
use SoftDeleteableEntity;
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
* @Groups("public")
*/
private $id;
/**
* @ORM\Column(type="string", length=180, unique=true)
* @Groups("public")
*/
private $email;
/**
* @ORM\Column(type="string", length=180)
* @Groups("public")
*/
private $displayName;
/**
* @ORM\Column(type="json")
* @Groups("public")
*/
private $roles = [];
/**
* @var string The hashed password
* @ORM\Column(type="string")
* @Groups("private")
*/
private $password;
public function __toString()
{
return (string) $this->getDisplayName();
}
public function getId(): ?int
{
return $this->id;
}
public function getEmail(): ?string
{
return $this->email;
}
public function setEmail(string $email): self
{
$this->email = $email;
return $this;
}
/**
* @return string
*/
public function getUsername(): string
{
return (string) $this->getEmail();
}
/**
* @return mixed
*/
public function getDisplayName(): ?string
{
return $this->displayName;
}
/**
* @param mixed $displayName
* @return User
*/
public function setDisplayName($displayName = null)
{
$this->displayName = $displayName;
return $this;
}
/**
* @see UserInterface
*/
public function getRoles(): array
{
$roles = $this->roles;
$roles[] = 'ROLE_USER';
return array_unique($roles);
}
public function setRoles(array $roles): self
{
$this->roles = $roles;
return $this;
}
/**
* @see UserInterface
*/
public function getPassword(): string
{
return (string) $this->password;
}
public function setPassword(string $password): self
{
$this->password = $password;
return $this;
}
/**
* @see UserInterface
*/
public function getSalt()
{
}
/**
* @see UserInterface
*/
public function eraseCredentials()
{
}
}
This is a simple User business object in a Symfony project. To turn it to an API resource, you just need to add the @Resource(name="your_api_resource_name")
annotation.
Then you have to extends the AbstractResource
or AbstractTranslatableResource
abstract layers.
At this level, the API response is empty, to add data you need to add the @Groups("public")
on the entity class members you want to expose.
This is it, your "user" resource REST API is now ready! An authenticated user with "ROLE_ADMIN" can now GET, POST, PUT or DELETE any user on "http://yourdomain/api/user" endpoint.
In a near future the @Group()
annotation groups will become more flexible, to allow different levels of resource attributes access depending of the authenticated user roles.
Filter API resources
You can filter the API resources using the "q" query string parameter with the following filters:
Greater operator
Here we query all product resources, with a price greater than 150
GET https://localhost:8000/api/product?page=1&limit=50&count=1&q={"price":{">":150}}
Lesser operator
Here we query all product resources, with a price lesser than 150
GET https://localhost:8000/api/product?page=1&limit=50&count=1&q={"price":{"<":150}}
Equal operator
Here we query all product resources, with a price equal to 150
GET https://localhost:8000/api/product?page=1&limit=50&count=1&q={"price":{"=":150}}
Different operator
Here we query all product resources, with a color different than yellow
GET https://localhost:8000/api/product?page=1&limit=50&count=1&q={"color":{"!=":"yellow"}}
Is null operator
Here we query all product resources, with a category null
GET https://localhost:8000/api/product?page=1&limit=50&count=1&q={"category":{"IS NULL":"null"}}
Is not null operator
Here we query all product resources, with a category not null
GET https://localhost:8000/api/product?page=1&limit=50&count=1&q={"category":{"IS NOT NULL":"null"}}
LIKE operator
Here we query all product resources, with a name that start with "bag"
GET https://localhost:8000/api/product?page=1&limit=50&count=1&q={"name":{"LIKE":"bag%"}}
Here we query all product resources, with a name that end with "bag"
GET https://localhost:8000/api/product?page=1&limit=50&count=1&q={"name":{"LIKE":"%bag"}}
Here we query all product resources, with a name that contain "bag"
GET https://localhost:8000/api/product?page=1&limit=50&count=1&q={"name":{"LIKE":"%bag%"}}
Sort API resources
You can sort API resource by one or more fields, using the "sort" query parameter with the following syntax.
GET https://localhost:8000/api/media?page=1&limit=50&count=1&q={"platform":{"=":52}}&sort[updated]=desc&sort[otherfield]=asc
Count total API resources
To build a pagination system client side, you'll need to know for a given request how many API resources are available. To count API resources for a given request simply add the count
query parameter.
GET http://localhost:8000/api/todo?page=5&limit=10&count=1
The API will add a "Count" response header, with the resources count for the given request.
Translatable resource
When your business object need to support i18n, you can GET, POST and PUT with a locale parameter:
GET http://localhost:8000/api/blog?page=5&limit=10
Become
GET http://localhost:8000/api/fr/blog?page=5&limit=10
To enable this behavior, you need to install the stof/doctrine-extensions-bundle
, and update your Doctrine entity to extends the AbstractTranslatableResource
layer and add the * @Gedmo\Translatable()
annotation onto the translatable entity fields.
The stof/doctrine-extensions-bundle
is the officially supported Doctrine extension bundle, but a future release will allow any Doctrine behavior extension.