Skip to content
This repository was archived by the owner on Apr 17, 2019. It is now read-only.
Open
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
37 changes: 37 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,43 @@ You need to give the path to the `RAML` file describing your API. You can find a

Then, browse your new API REST on the url defined in the `baseUrl` configuration of your `RAML` api file.

## Using request parameters

You can specify some get request parameters. For example:

Request param | Description | Type / Example | Default
--------------|--------------|--------------|--------------
`_start` | specify start bound of selection | `number` | `0`
`_end` | specify **length** of selection | `number` |`20`
`_sort` | specify key ordering | `string` |
`_sortDir` | specify order direction | `ASC`, `DESC` | `ASC`
`_fields` | specify comma separated set of fields in result set | `string` | `*`
`_strongFilter[]` | specify conjunction filter like a ````id` = 8 AND `post_id` = 2``` as request params array | `array` |
`_strongFilterIn[]` | specify `IN` condition like a ````id` IN (1,2,3)``` | array |
`_searchOr[]` | specify search disjunction filter like a ````title` LIKE '%foo%' OR `post` LIKE '%bar%'``` | `array` |
`_searchAnd[]` | specify search conjunction filter like a ````title` LIKE '%foo%' AND `post` LIKE '%bar%'``` | `array` |
`_group` | set group part | `string` |

You can combine one of `_strongFilter[]`, `_strongFilterIn[]`, `_searchOr[]`, `_searchAnd[]` with `_sort`, `_sortDir`, `_fields`, `_start` and `_end` params

#### Warning!
You should use **only** one filer from
`_strongFilter[]`, `_strongFilterIn[]`, `_searchOr[]`, `_searchAnd[]` or you will get an HTTP error `400 Bad request`.

### Query string examples

Query string | Description
-------------|------------
`/posts?_start=10&_end=15` | you will receive a 15 posts from 10 position as result set
`/posts?_sort=title&_sortDir=DESC` | you will receive a list sorted by `title` descending
`/posts?_fields=id,title` | you will receive a list with `id` and `title` field in response
`/posts?_strongFilter[id]=8&_strongFilter[title]=foo` | you will receive a list of items where ````id` = 8 AND `title` = 'foo'```
`/posts?_strongFilterIn[id]=1,2,3` | you will receive a list of items with `id` in list: `1`, `2`, `3`
`/posts?_searchOr[title]=foo&_searchOr[body]=bar` | you will receive a list of items where ````title` LIKE '%foo%' OR `body` LIKE '%bar%'```
`/posts?_searchAnd[title]=foo&_searchAnd[body]=bar` | you will receive a list of items where ````title` LIKE '%foo%' AND `body` LIKE '%bar%'```
`/posts?_group=title` | should use for request distinct values of column instead
`/posts?_searchAnd[title]=foo&_searchOr[body]=bar` | you will receive HTTP error `400 Bad request`

## Tests

Run the tests suite with the following commands:
Expand Down
125 changes: 122 additions & 3 deletions src/RestController.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,130 @@ public function homeAction($availableRoutes)

public function getListAction($objectType, Request $request)
{
// Prepare-prefixes
$strongFilterKeyPrefix = 'strong_filter_';
$searchOrKeyPrefix = 'search_or_';
$searchAndKeyPrefix = 'search_and_';

$queryBuilder = $this->dbal
->createQueryBuilder()
->select('o.*')
->from($objectType, 'o')
;
->from($objectType, 'o');

$filterNames = array(
'_strongFilter',
'_strongFilterIn',
'_searchOr',
'_searchAnd',
);

// Fetching filters from request
$filters = array_combine(
$filterNames,
array_map(
function ($filter) use ($request) {
return $request->query->get($filter);
},
$filterNames
)
);

// Throw expression when count of filters in request greater then one
$count = array_reduce(
$filters,
function ($carry, $item) {
return $carry + ($item !== null);
},
0
);
if ($count > 1) {
return new JsonResponse(
array(
'status' => 'ERROR',
'status_code' => 400,
'message' => 'You should use only one type of filters per request',
), 400
);
}

// Return only assigned fields
$fields = $request->query->get('_fields');
$queryBuilder->select(
$fields ? preg_replace('/([^,]+)/', 'o.$1', $fields) : 'o.*'
);

// Strong filter implementing
// o.f1 = 'val1' AND o.f2 = 'val2' ...
if ($filters['_strongFilter']) {
$queryBuilder
->where(
implode(
' and ',
array_map(
function ($item) use ($strongFilterKeyPrefix) {
return "{$item} = :{$strongFilterKeyPrefix}{$item}";
},
array_keys($filters['_strongFilter'])
)
)
)
->setParameters(
array_combine(
array_map(
function ($key) use ($strongFilterKeyPrefix) {
return $strongFilterKeyPrefix . $key;
},
array_keys($filters['_strongFilter'])
),
$filters['_strongFilter']
)
);
}

// Searching with OR:
// o.f1 LIKE '%val1%' OR o.f2 LIKE '%val2%'
if ($filters['_searchOr']) {
foreach ($filters['_searchOr'] as $key => $value) {
$queryBuilder
->orWhere(
$queryBuilder->expr()->like(
$key,
":" . $searchOrKeyPrefix . $key
)
)
->setParameter($searchOrKeyPrefix . $key, "%{$value}%");
}
}

if ($filters['_strongFilterIn']) {
foreach ($filters['_strongFilterIn'] as $key => $value) {
$queryBuilder
->andWhere(
$queryBuilder->expr()->in(
$key,
explode(',', $value)
)
);
}
}

// Searching with AND:
// o.f1 LIKE '%val1%' AND o.f2 LIKE '%val2%'
if ($filters['_searchAnd']) {
foreach ($filters['_searchAnd'] as $key => $value) {
$queryBuilder
->andWhere(
$queryBuilder->expr()->like(
$key,
":" . $searchAndKeyPrefix . $key
)
)
->setParameter($searchAndKeyPrefix . $key, "%{$value}%");
}
}

if ($group = $request->query->get('_group')) {
$queryBuilder->groupBy($group);
}

if ($sort = $request->query->get('_sort')) {
$queryBuilder->orderBy($sort, $request->query->get('_sortDir', 'ASC'));
Expand Down