Drupal REST API
Piotr Woszczyk @ 2018
Paradyż
Do przygotowania API w projekcie Paradyż użyto nastepujacych komponentów:
- Routing
- Controller
- Service
Routing
makolab.awards:
path: '/json/api/awards'
defaults:
_controller: '\Drupal\makolab\Controller\AwardController::awardsList'
_title: 'Awards listing'
requirements:
_permission: 'access content'Controller
class AwardController extends JsonController
{
protected $awardsService;
public function __construct(
AwardsService $awardsService
) {
$this->awardsService = $awardsService;
}
public static function create(ContainerInterface $container)
{
return new static(
$container->get('makolab.service.awards')
);
}
public function awardsList()
{
$queryParams = \Drupal::request()->query->all();
$results = json_encode($this->awardsService->get($queryParams));
return $this->jsonResponse($results);
}
}
Service
class AwardsService
{
public function get($params)
{
$languageCode = \Drupal::languageManager()->getCurrentLanguage()->getId();
$result = ['results' => [], 'total' => 0];
$query = \Drupal::database()->select('node');
$query->condition('type', 'award');
// Tab filter
$map = [
'1' => 'dla_produktu',
'2' => 'dla_firmy'
];
$tab = isset($params['TAB']) ? $params['TAB'] : 1;
$query->leftJoin('node__field_award_type', 'field_award_type', 'field_award_type.entity_id = node.nid');
$query->condition('field_award_type.field_award_type_value', $map[$tab]);
$query->condition('field_award_type.langcode', $languageCode);
if (isset($params['featured'])) {
$query->leftJoin('node__field_award_distinction', 'field_award_distinction', 'field_award_distinction.entity_id = node.nid');
$query->condition('field_award_distinction.field_award_distinction_value', $params['featured']);
$query->condition('field_award_distinction.langcode', $languageCode);
}
//...
$elements = $countQuery->execute()->fetchAllKeyed(0, 0);
$result['total'] = reset($elements);
return $result;
}
}ECC
- Rest resource + config
Rest resource
/**
* @RestResource(
* id = "ecc:locations",
* label = @Translation("ECC Get Locations"),
* description = @Translation(
* "Used by search engine part, on the step 2 - download popup"
* ),
* uri_paths = {
* "canonical" = "/locations"
* }
* )
*/
class RestResourceLocations extends ResourceBase {
//...
}Config
#web/sites/default/config/rest.resource.search_products_results.yml
uuid: 6587b361-d46a-4f8b-b343-90820f60b466
langcode: fr
status: true
dependencies:
module:
- ecc_search
- serialization
- user
id: ecc.search_products_results
plugin_id: 'ecc:search_products_results'
granularity: resource
configuration:
methods:
- GET
formats:
- json
authentication:
- cookieParadyż
Zalety:
- Prosta implementacja
- Separacja logiki biznesowej w serwisach
Wady:
- Nie ma to wiele wspólnego z REST
- Problem z włączeniem cache / autoryzacji / formatów / CSRF protection
ECC
Zalety:
- Użycie gotowego rozwiązania
- Łatwość dodania cache, zmiany sposobu autoryzacji etc.
Wady:
- Ogromne metody
- Błędna implementacja response
ECC - response
protected function getJson($output) {
/**
* @todo wylaczyc
*/
return (new JsonResponse($output));
if (! isset($output['#cache'])) {
$output['#cache'] = [
'max-age' => 1200,
'contexts' => [
'url',
'url.query_args'
],
];
}
$response = new CacheableJsonResponse($output);
$response->addCacheableDependency(CacheableMetadata::createFromRenderArray($output));
return $response;
}ResourceResponse
public function get() {
$response = ['message' => 'Hello, this is a rest service'];
return new ResourceResponse($response);
}Drupal REST API (Paradyż vs ECC)
By Piotr Woszczyk
Drupal REST API (Paradyż vs ECC)
Prezentacja opisująca różnice w podejściu do implementacji API w projekcie Paradyż i ECC.
- 62