Hello,

How I can create a post Resource that can accept values by the body, this is my code:


namespace Drupal\custom_rest\Plugin\rest\resource;

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

/**
 * Provides a resource to get view modes by entity and bundle.
 *
 * @RestResource(
 *   id = "custom_rest_resource_user_check",
 *   label = @Translation("Custom User Check"),
 *   uri_paths = {
 *     "canonical" = "/api/v1/custom/user_check",
 *     "https://www.drupal.org/link-relations/create" = "/api/v1/custom/user_check"
 *   }
 * )
 */
class CustomRestResourceUserCheck extends ResourceBase {

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

  /**
   * Constructs a Drupal\rest\Plugin\ResourceBase 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('custom_rest'),
      $container->get('current_user')
    );
  }

  /**
   * Responds to POST requests.
   *
   * Returns a list of bundles for specified entity.
   *
   * @throws \Symfony\Component\HttpKernel\Exception\HttpException
   *   Throws exception expected.
   */
  public function post() {

    // You must to implement the logic of your REST Resource here.
    // Use current user after pass authentication to validate access.
    if (!$this->currentUser->hasPermission('access content')) {
      throw new AccessDeniedHttpException();
    }

    return new ResourceResponse("Implement REST State POST!");
  }

}

Greetings.

Comments

rpayanm created an issue. See original summary.

wim leers’s picture

Title: Create a post method in Drupal 8 » Create a post method in Drupal 8: how to receive data?
Issue tags: -REST, -REST API

You already posted an issue at #2799383: Create a post method in Drupal 8: route not found with the exact same title. Please write sane issue titles. That ensures you get better help. I now retitled that other issue. And retitling this one too.

wim leers’s picture

Status: Active » Fixed

You must specify a serialization_class in the annotation. See \Drupal\rest\Annotation\RestResource.

Or, if there is no serialization class, then you can just do:

  public function post(array $data = []) {
    …
  }

As you can see in \Drupal\rest_test\Plugin\rest\resource\NoSerializationClassTestResource.

rpayanm’s picture

Status: Fixed » Active
StatusFileSize
new52.05 KB

Sorry for the title :(

Now I write a serialization class:

namespace Drupal\custom_rest\Plugin\rest\Annotation;

use \Drupal\Component\Annotation\Plugin;

/**
 * Defines a REST resource annotation object.
 */
class UserResource extends Plugin {
  /**
   * The resource plugin username.
   *
   * @var string
   */
  public $username;
  
}

And in the annotation:

/**
 * Provides a resource to get view modes by entity and bundle.
 *
 * @RestResource(
 *   id = "custom_rest_resource_user_check",
 *   label = @Translation("Custom User Check"),
 *   serialization_class = "Drupal\custom_rest\Plugin\rest\Annotation\UserResource",
 *   uri_paths = {
 *     "canonical" = "/api/v1/custom/user_check",
 *     "https://www.drupal.org/link-relations/create" = "/api/v1.0/custom/user_check"
 *   }
 * )
 */

In the method:

public function post(UserResource $user) {
    return new ResourceResponse($user->username);
  }

But now I got this error for postman:
REST

rpayanm’s picture

StatusFileSize
new69.17 KB
rpayanm’s picture

StatusFileSize
new4.71 KB
new66.65 KB

Already implement serialization_class.

Here my implementation:

namespace Drupal\custom_rest\Plugin\rest\resource;

use Drupal\custom_rest\Plugin\rest\annotation\TestResource;
use Drupal\rest\Plugin\ResourceBase;
use Drupal\rest\ResourceResponse;


/**
 * Provides a resource to get view modes by entity and bundle.
 *
 * @RestResource(
 *   id = "custom_rest_resource_test",
 *   label = @Translation("Test Rest"),
 *   serialization_class = "Drupal\custom_rest\Plugin\rest\annotation\TestResource",
 *   uri_paths = {
 *     "canonical" = "/api/v1.0/custom/test",
 *     "https://www.drupal.org/link-relations/create" = "/api/v1.0/custom/test"
 *   }
 * )
 */
class RestResourceTest extends ResourceBase {
  /**
   * Responds to POST requests.
   */
  public function post(TestResource $test) {
    return new ResourceResponse($test->title);
  }

}

My Normalize class:

namespace Drupal\custom_rest\Plugin\rest\normalizer;

use Drupal\custom_rest\Plugin\rest\annotation\TestResource;
use Drupal\serialization\Normalizer\NormalizerBase;

class TestDenormalizer extends NormalizerBase   {
  /**
   * The interface or class that this Normalizer supports.
   *
   * @var array
   */
  protected $supportedInterfaceOrClass = ['Drupal\custom_rest\Plugin\rest\annotation\TestResource'];

  /**
   * Denormalizes data back into an object of the given class.
   *
   * @param mixed $data data to restore
   * @param string $class the expected class to instantiate
   * @param string $format format the given data was extracted from
   * @param array $context options available to the denormalizer
   *
   * @return object
   */
  public function denormalize($data, $class, $format = NULL, array $context = array()) {
    $test = new TestResource();

    $test->title = $data['title'];

    return $test;
  }

  /**
   * Normalizes an object into a set of arrays/scalars.
   *
   * @param object $object object to normalize
   * @param string $format format the normalization result will be encoded as
   * @param array $context Context options for the normalizer
   *
   * @return array
   */
  public function normalize($object, $format = NULL, array $context = array()) {
    // TODO: Implement normalize() method.
  }
}

My annotation class:

namespace Drupal\custom_rest\Plugin\rest\annotation;

/**
 * Defines a REST resource annotation object.
 */
class TestResource {
  /**
   * The resource plugin title.
   *
   * @var string
   */
  public $title;

  public function __construct() {

  }

}

My services.yml

services:
  custom_rest.denormalizer.test:
    class: Drupal\custom_rest\Plugin\rest\normalizer\TestDenormalizer
    tags:
      - { name: normalizer }

I have activated:
rest

I tested this functionality in Postman but I get the following error:
rest

dawehner’s picture

If you want to make life easier, provide a module we can just download :)

wim leers’s picture

Status: Active » Postponed (maintainer needs more info)

serialization_class = “Drupal\custom_rest\Plugin\rest\annotation\TestResource”,

This is not at all a serialization class. Look at the examples in Drupal core. The serialization class is the PHP object that this must be deserialized to from JSON, or is serialized from.

rpayanm’s picture

Status: Postponed (maintainer needs more info) » Active
StatusFileSize
new1.4 KB

@Wim Leers I changed the serialization class but dont work :(

I attached the module.
Thank you.

dawehner’s picture

You misunderstood the concept of the serialization class, its the class you are trying to serialize to, not the class which does the normalization/denormalization.

The main problem was that \Drupal\custom_rest\Normalizer\TestDenormalizer had to implement DenormalizerInterface as well.

Note: Personal contact emails are not meant for asking for support.

dawehner’s picture

Status: Active » Fixed
StatusFileSize
new3.58 KB

Here is a patch for your module which also moves stuff around.

rpayanm’s picture

Thank you so much @dawehner

wim leers’s picture

Note: Personal contact emails are not meant for asking for support.

Indeed. @rpayanm also contacted me.

You're already getting support here.

dawehner’s picture

Especially don't expect people to react in any timeframe where you need it. If you need payed support times, pay for it :)

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.