1

I wrote my custom rest endpoint. I need to 2 URI both called with GET

  • /api/item/{id} to get single item identified by ID
  • /api/item to get the list of items.

i try with

  @RestResource(
    id = "my_id",
    label = @Translation("My label"),
    uri_paths = {
      "canonical" = "/api/item",
      "https://www.drupal.org/link-relations/index" = "/api/item/{id}",
    }

into my class i have

class ApiRestResource extends ResourceBase {

    public function get($id = NULL) {

but only canonical URI is found. the message for the second URI is

"message": "No route found for \"GET /api/item/1\""

how can i have 2 GET in my class? thanks in advance

4 Answers 4

3

you can create two resource files, one that receives the parameter and another that does not.

Example:

demo_rest_api.info.yml.

name: Demo REST API
description: Define's a custom REST Resource
package: Custom
type: module
core: 8.x

/src/Plugin/rest/resource/DemoResource.php

<?php

namespace Drupal\demo_rest_api\Plugin\rest\resource;

use Drupal\rest\Plugin\ResourceBase;
use Drupal\rest\ResourceResponse;

/**
 * Provides a Demo Resource
 *
 * @RestResource(
 *   id = "demo_resource",
 *   label = @Translation("Demo Resource"),
 *   uri_paths = {
 *     "canonical" = "/api/item"
 *   }
 * )
 */
class DemoResource extends ResourceBase {

  /**
   * Responds to entity GET requests.
   * @return \Drupal\rest\ResourceResponse
   */
  public function get() {


      $response = ['message' => 'Hello, this is a rest service:'];

    return new ResourceResponse($response);

  }
}

/src/Plugin/rest/resource/DemoResource_item_id.php

<?php

namespace Drupal\demo_rest_api\Plugin\rest\resource;

use Drupal\rest\Plugin\ResourceBase;
use Drupal\rest\ResourceResponse;

/**
 * Provides a Demo Resource
 *
 * @RestResource(
 *   id = "DemoResource_item_id",
 *   label = @Translation("Demo Resource item id"),
 *   uri_paths = {
 *     "canonical" = "/api/item/{id}"
 *   }
 * )
 */
class DemoResource_item_id extends ResourceBase {

  /**
   * Responds to entity GET requests.
   * @return \Drupal\rest\ResourceResponse
   */
  public function get($id= null) {


      $response = ['message' => 'Hello, this is a rest service and parameter is: '.$id];

    return new ResourceResponse($response);

  }
}
3
  • Thanks David. I know but i don't understand why i can't manage multiple GET in the same class. core.link_relation_types.yml works fine for "create" => POST and "edit" => PUT. It's a bug?
    – Fabio Riva
    Commented Dec 8, 2017 at 15:00
  • @FabioRiva if canonical is the only link that works for GET, per your own comment on my answer... then you will definitely need two resources.
    – Darvanen
    Commented Dec 10, 2017 at 23:32
  • You're either returning one resource of a list of them. Resource and ResourceList are 2 separate functions so should be separate resources anyway.
    – imclean
    Commented Mar 5, 2018 at 4:07
0

According to the RestResource documentation, uri_paths are:

Key-value pairs, with link relation type plugin IDs as keys, and URL templates as values.

Your second uri_paths item needs a key to tell Drupal what kind of endpoint it is.

core.link_relation_types.yml contains the available types. In your case I'm going to hazard a guess that item is the most appropriate.

If that doesn't work, maybe try creating two classes.

1
  • Thank you Darvaner, i try item, index .... but only canonical path works for GET. PUT and POST work fine.
    – Fabio Riva
    Commented Dec 8, 2017 at 9:28
0

this page , contains information that may interest you.

Just modify the path in your file: .routing.yml

test_api.getitemid:
  path: '/api/item/{id}'
  defaults: { _controller: '\Drupal\test_api\Controller\TestAPIController::getitemid_example' }
  methods:  [GET]
  requirements:
    _access: 'TRUE'

test_api.getallitem:
  path: '/api/item'
  defaults: { _controller: '\Drupal\test_api\Controller\TestAPIController::get_example' }
  methods:  [GET]
  requirements:
    _access: 'TRUE'

In your file: TestAPIController

add the functions

getitemid_example

public function getitemid_example( Request $request, $id=null ) {

    $response['data'] = 'your id parameter is:'.$id;
    $response['method'] = 'GET';

    return new JsonResponse( $response );
  }
2
  • Hi David, thank you for your answer but this is not a RESTful resource. i would like to implement with a @RestResource-annotated plugin implementing ResourceInterface.
    – Fabio Riva
    Commented Dec 8, 2017 at 9:08
  • The problem has the "canonical" parameter. The idea of using resources is that if you want to use the methods: GET, POST, PUT, and DELETE it has to be without parameters or with parameters. Commented Dec 8, 2017 at 15:20
0

I do not think for the same operation, We need to create multiple files.

Request URL: http://localhost/drupal/product-list?search=abc

use Symfony\Component\HttpFoundation\Request;

/**
 * Provides a resource to get view modes by entity and bundle.
 *
 * @RestResource(
 *   id = "drupal_rest_api",
 *   label = @Translation("rest  api"),
 *   uri_paths = {
 *     "canonical" = "/product-list"
 *   }
 * )
 */


public function get( Request $request) {                        
        $search = \Drupal::request()->query->get('search');
        kint($search)   

}

You can be added multiple arguments without creating multiple files

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.