一月 30, 2019 | 後端和Drupal

【D8 教學】實作建立GET方法的Custom Resource

在D8的環境下,使用REST或使用JSONAPI都已經非常方便了,但有些時候,你會需要客製化自己的REST,搭配獨特的邏輯,這個時候也許就不是純粹的讀取API資料或寫入API資料這麼容易了。這篇文章主要將介紹使用Drupal Console來逐步完成有GET與POST方法的客製化API,將會讓你覺得輕鬆且寫意。

前言

在D8的環境下,使用REST或使用JSONAPI都已經非常方便了,但有些時候,你會需要客製化自己的REST,搭配獨特的邏輯,這個時候也許就不是純粹的讀取API資料或寫入API資料這麼容易了。這篇文章主要將介紹使用Drupal Console來逐步完成有GET與POST方法的客製化API,將會讓你覺得輕鬆且寫意。

首先建立客製化模組

這裡使用Drupal Console直接就可以建立一個空白且乾淨的模組,若你還不熟悉,可以參考Drupal 8 專用的CLI工具:Drupal Console,裡面將非常清楚的解釋,要如何安裝Drupal Console並且建立一個客製化模組。當然,如果你有點懶,想要直接看結果也可以參考下面指令

懶人一句指令建立法

$ drupal generate:module  \
--module="d8 custom resource" \
--machine-name="d8_custom_resource" \
--module-path="modules/custom" \
--description="My Awesome Module" \
--core="8.x" \
--package="Custom" \
--module-file --composer --test --twigtemplate --learning --\
uri="http://default" --no-interaction

建立一個Rest Resource的Plugin

再來就是建立一個Get方法的Plugin囉,不管程式是否熟悉的你,都可以通過以下指令一次將Get Plugin建立到剛剛建立的模組之中。

$ drupal generate:plugin:rest:resource  \
--module="d8_custom_resource" \
--class="DefaultRestResource" \
--plugin-id="default_rest_resource" \
--plugin-label="d8-custom-resource" \
--plugin-url="d8-custom-resource" \
--plugin-states='GET' \
--learning --uri="http://default" --no-interaction

建立完畢之後,可以先行啟用模組看看,是否運行正常

  • 使用Drush語法
$ drush en d8_custom_resource -y
  • 使用Drupal Console語法
$ drupal module:install d8_custom_resource

資料夾目前配置

檢查是否有剛建立的Resource在REST的列表

安裝好模組之後,進入到REST的UI畫面,若你在你的D8網站看不到,就代表你少裝一個REST UI的模組囉。補上模組以後,應該就可以從以下路徑看到剛剛建立的resource啦。

  • REST UI路徑
http://drupal8.demo.dev/admin/config/services/rest
  • REST UI 列表畫面

  • 啟用建立的Resource畫面

建立GET方法的內容

若你已經都有了上述的畫面,那基本上已經完成了九成囉,再來只需要剛剛建立的DefaultRestResource裡的Get方法,就做完啦。

<?php

namespace Drupal\d8_custom_resource\Plugin\rest\resource;

use Drupal\Core\Session\AccountProxyInterface;
use Drupal\rest\ModifiedResourceResponse;
use Drupal\rest\Plugin\ResourceBase;
use Drupal\rest\ResourceResponse;
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;

/**
 * Provides a resource to get view modes by entity and bundle.
 *
 * @RestResource(
 *   id = "default_rest_resource",
 *   label = @Translation("d8-custom-resource"),
 *   uri_paths = {
 *     "canonical" = "/d8-custom-resource"
 *   }
 * )
 */
class DefaultRestResource extends ResourceBase {

  /**
   * A current user instance.
   *
   * @var \Drupal\Core\Session\AccountProxyInterface
   */
  protected $currentUser;

  /**
   * Constructs a new DefaultRestResource object.
   *
   * @param array $configuration
   *   A configuration array containing information about the plugin instance.
   * @param string $plugin_id
   *   The plugin_id for the plugin instance.
   * @param mixed $plugin_definition
   *   The plugin implementation definition.
   * @param array $serializer_formats
   *   The available serialization formats.
   * @param \Psr\Log\LoggerInterface $logger
   *   A logger instance.
   * @param \Drupal\Core\Session\AccountProxyInterface $current_user
   *   A current user instance.
   */
  public function __construct(
    array $configuration,
    $plugin_id,
    $plugin_definition,
    array $serializer_formats,
    LoggerInterface $logger,
    AccountProxyInterface $current_user) {
    parent::__construct($configuration, $plugin_id, $plugin_definition, $serializer_formats, $logger);

    $this->currentUser = $current_user;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->getParameter('serializer.formats'),
      $container->get('logger.factory')->get('d8_custom_resource'),
      $container->get('current_user')
    );
  }

  /**
   * Responds to GET requests.
   *
   * @param \Drupal\Core\Entity\EntityInterface $entity
   *   The entity object.
   *
   * @return \Drupal\rest\ResourceResponse
   *   The HTTP response object.
   *
   * @throws \Symfony\Component\HttpKernel\Exception\HttpException
   *   Throws exception expected.
   */
  public function get() {

    $response = ['message' => 'Hello, This is a first GET Resource at HelloSanta'];
    return new ResourceResponse($response);

  }

}

最後將d8-custom-resource路徑輸入到網址內,應該就會得到以下的JSON Resource回傳,你就成功囉

結論

善用Drupal consle可以省去很多寫Code的時間,而且穩定多了,本來想要全部自己Hard Code,但是卻因為一個大小寫的問題,讓我要Debug好久,還是覺得直接打指令建立客製化的任何東西是方便又開心的。

最後,若你想要看看我的code,可以到以下來看看囉

範例Github

https://github.com/cobenash/d8-custom-resource

參考

  1. https://www.drupal.org/docs/8/api/restful-web-services-api/custom-rest-resources