Skip to content

Merge 2.0 on master #201

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
May 15, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 96 additions & 6 deletions core/filters.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ constant directly.

The boolean filter allows you to search on boolean fields and values.

Syntax: `?property=[on|off|true|false|0|1]`
Syntax: `?property=[true|false|1|0]`

You can either use TRUE or true, the parameters are case insensitive.

Expand Down Expand Up @@ -422,15 +422,105 @@ It means that the filter will be **silently** ignored if the property:
Custom filters can be written by implementing the `ApiPlatform\Core\Api\FilterInterface`
interface.

If you use [custom data providers](data-providers.md), they must support filtering and be aware of active filters to work
properly.
API Platform provides a convenient way to create Doctrine ORM filters. If you use [custom data providers](data-providers.md),
you can still create filters by implementing the previously mentioned interface, but - as API Platform isn't aware of your
persistence system's internals - you have to create the filtering logic by yourself.

### Creating Custom Doctrine ORM Filters

Doctrine ORM filters must implement the `ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\FilterInterface`.
They can interact directly with the Doctrine `QueryBuilder`.
Doctrine filters can access to the HTTP request (Symfony's `Request` object) and to the `QueryBuilder` instance used to
retrieve data from the database. They are only applied to collections. If you want to deal with the DQL query generated
to retrieve items, or don't need to access the HTTP request, [extensions](extensions.md) are the way to go.

A convenient abstract class is also shipped with the bundle: `ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\AbstractFilter`
A Doctrine ORM filter is basically a class implementing the `ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\FilterInterface`.
API Platform includes a convenient abstract class implementing this interface and providing utility methods: `ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\AbstractFilter`

In the following example, we create a class to filter a collection by applying a regexp to a property. The `REGEXP` DQL
function used in this example can be found in the [`DoctrineExtensions`](https://github.com/beberlei/DoctrineExtensions)
library. This library must be properly installed and registered to use this example (works only with MySQL).

```php
<?php

// src/AppBundle/Filter/RegexpFilter.php

namespace AppBundle\Filter;

use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\AbstractFilter;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Util\QueryNameGeneratorInterface;
use Doctrine\ORM\QueryBuilder;

final class RegexpFilter extends AbstractFilter
{
protected function filterProperty(string $property, $value, QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, string $operationName = null)
{
$parameterName = $queryNameGenerator->generateParameterName($property); // Generate a unique parameter name to avoid collisions with other filters
$queryBuilder
->andWhere(sprintf('REGEXP(o.%s, :%s) = 1', $property, $parameterName))
->setParameter($parameterName, $value);
}

// This function is only used to hook in documentation generators (supported by Swagger and Hydra)
public function getDescription(string $resourceClass): array
{
$description = [];
foreach ($this->properties as $property => $strategy) {
$description['regexp_'.$property] = [
'property' => $property,
'type' => 'string',
'required' => false,
'swagger' => ['description' => 'Filter using a regex. This will appear in the Swagger documentation!'],
];
}

return $description;
}
}
```

Then, register this filter as a service:

```yaml
services:
'AppBundle\Filter\RegexpFilter':
class: 'AppBundle\Filter\RegexpFilter'
autowire: true # See the next example for a plain old definition
tags: [ { name: 'api_platform.filter', id: 'regexp' } ]
```

In the previous example, the filter can be applied on any property. However, thanks to the `AbstractFilter` class,
it can also be enabled for some properties:

```yaml
services:
'AppBundle\Filter\RegexpFilter':
class: 'AppBundle\Filter\RegexpFilter'
arguments: [ '@doctrine', '@request_stack', '@?logger', { email: ~, anOtherProperty: ~ } ]
tags: [ { name: 'api_platform.filter', id: 'regexp' } ]
```

Finally, add this filter to resources you want to be filtered:

```php
<?php

// src/AppBundle/Entity/Offer.php

namespace AppBundle\Entity;

use ApiPlatform\Core\Annotation\ApiResource;

/**
* @ApiResource(attributes={"filters"={"regexp"}})
*/
class Offer
{
// ...
}
```

You can now enable this filter using URLs like `http://example.com/offers?regexp_email=^[FOO]`. This new filter will also
appear in Swagger and Hydra documentations.

### Overriding Extraction of Properties from the Request

Expand Down
9 changes: 6 additions & 3 deletions core/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ API Platform Core is able to automatically expose entities mapped as "API resour
operations.
To expose your entities, you can use Docblock annotations, XML and YAML configuration files.

Here is an example of entities mapped using annotations which will be exposed trough a REST API:
Here is an example of entities mapped using annotations which will be exposed through a REST API:

```php
<?php
Expand Down Expand Up @@ -138,7 +138,7 @@ class Offer
}
```

It is the minimal configuration required to expose `Product` and `Offer` entities as JSON-LD documents trough an hypermedia
It is the minimal configuration required to expose `Product` and `Offer` entities as JSON-LD documents through an hypermedia
web API.

If you are familiar with the Symfony ecosystem, you noticed that entity classes are also mapped with Doctrine ORM annotations
Expand Down Expand Up @@ -173,7 +173,10 @@ As an alternative to annotations, you can map entity classes using XML or YAML:
<!-- src/AppBundle/Resources/config/api_resources/resources.xml -->

<?xml version="1.0" encoding="UTF-8" ?>
<resources>
<resources xmlns="https://api-platform.com/schema/metadata"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://api-platform.com/schema/metadata
https://api-platform.com/schema/metadata/metadata-2.0.xsd">
<resource class="AppBundle\Entity\Product" />
<resource
class="AppBundle\Entity\Offer"
Expand Down
4 changes: 2 additions & 2 deletions core/serialization-groups-and-relations.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ In the following JSON document, the relation from a book to an author is represe
### Normalization

To improve the application's performance, it is sometimes necessary to avoid issuing extra HTTP requests. It is possible
to embed related objects (or only some of their properties) directly in the parent response trough serialization groups.
to embed related objects (or only some of their properties) directly in the parent response through serialization groups.
By using the following serialization groups annotations (`@Groups`), a JSON representation of the author is embedded in
the book response:

Expand Down Expand Up @@ -239,7 +239,7 @@ class Book

The following rules apply when denormalizating embedded relations:

* If a `@id` key is present in the embedded resource, the object corresponding to the given URI will be retrieved trough
* If a `@id` key is present in the embedded resource, the object corresponding to the given URI will be retrieved through
the data provider and any changes in the embedded relation will be applied to that object.
* If no `@id` key exists, a new object will be created containing data provided in the embedded JSON document.

Expand Down
2 changes: 1 addition & 1 deletion deployment/heroku.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Deploying an API Platform App on Heroku

[Heroku](http://heroku.com) is a popular, fast, scalable and reliable *Platform As A Service* (PaaS). As Heroku offers a
free plan including database support trough [Heroku Postgres](https://www.heroku.com/postgres), it's
free plan including database support through [Heroku Postgres](https://www.heroku.com/postgres), it's
a very convenient way to experiment with the API Platform.

The API Platform Heroku integration also supports MySQL databases provided by [the ClearDB add-on](https://addons.heroku.com/cleardb).
Expand Down
2 changes: 1 addition & 1 deletion deployment/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
As an API Platform application is basically a standard Symfony application, [all Symfony deployment cookbooks](http://symfony.com/doc/current/cookbook/deployment/index.html)
apply.

However, API Platform also provide facilities to deploy applications trough containers and Platforms as a Service (PaaS):
However, API Platform also provide facilities to deploy applications through containers and Platforms as a Service (PaaS):

* [Deploying an API Platform App on Heroku](heroku.md)
* [Using API Platform with Docker](docker.md)
Expand Down
6 changes: 3 additions & 3 deletions distribution/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ the API without having to write a single line of PHP.
Feature: Manage books and their reviews
In order to manage books and their reviews
As a client software developer
I need to be able to retrieve, create, update and delete them trough the API.
I need to be able to retrieve, create, update and delete them through the API.

# the "@createSchema" annotation provided by API Platform creates a temporary SQLite database for testing the API
@createSchema
Expand Down Expand Up @@ -162,10 +162,10 @@ Clear the cache of the `test` environment:

$ docker-compose exec web bin/console cache:clear --env=test

Then run:
Then run:

$ docker-compose run --rm web vendor/bin/behat`.

Everything should be green now. Your Linked Data API is now specified and tested thanks to Behat!

You may also be interested by those alternative testing tools (not included in the API Platform distribution):
Expand Down
Loading