How to Override a REST Resource from Drupal Core
Knowledge Centre
Sometimes projects require us to find innovative solutions. Recently, we needed to override a core REST resource in Drupal 8, and given the limited documentation available, we decided to share our solution.
The Premises of a Drupal 8 Override
Drupal 8 handles configuration in a unified way, with more features stored in core than in previous versions. This architectural choice means that overriding core functionality requires careful consideration to avoid system damage.
While Drupal 8 supports global `$config` overrides through `Drupal\Core\Config\ConfigFactory::get()`, REST resource overrides require a different approach. Drupal 8's core provides basic REST resources for system entities, but complex operations often require extending these base classes.
Step-by-Step Guide to Override a REST Resource
1. Create a New Class
First, create a class that extends the `EntityResource` class:
- namespace Drupal\my_module\Plugin\rest\resource;
- use Drupal\rest\Plugin\ResourceBase;
- use Drupal\rest\ResourceResponse;
- use Drupal\node\Entity\Node;
- /**
- * @RestResource(
- * id = "my_custom_node_rest_resource",
- * label = @Translation("Custom Node REST Resource"),
- * uri_paths = {
- * "canonical" = "/api/v1/node/{node}",
- * "create" = "/api/v1/node"
- * }
- * )
- */
- class MyCustomNodeResource extends EntityResource {
- ....
- }
2. Implement Required Methods
Override the necessary methods from the parent class:
- /**
- * Responds to POST requests.
- *
- * @param array $data
- * The request data.
- *
- * @return \Drupal\rest\ResourceResponse
- * The response containing the node.
- */
- public function post($data) {
- // Your custom POST logic here
- $response = new ResourceResponse($result, 201);
- return $response;
- }
- /**
- * Responds to PATCH requests.
- *
- * @param \Drupal\Core\Entity\EntityInterface $entity
- * The entity.
- * @param array $data
- * The request data.
- *
- * @return \Drupal\rest\ResourceResponse
- * The response.
- */
- public function patch($entity, array $data) {
- // Your custom PATCH logic here
- return new ResourceResponse($entity, 200);
- }
3. Configure REST Resource Settings
Add the following to your module's configuration:
- # config/install/rest.resource.my_custom_node_rest_resource.yml
- langcode: en
- status: true
- dependencies:
- module:
- - my_module
- - serialization
- id: my_custom_node_rest_resource
- plugin_id: my_custom_node_rest_resource
- granularity: resource
- configuration:
- methods:
- - GET
- - POST
- - PATCH
- formats:
- - json
- authentication:
- - basic_auth
4. Implement Access Controls
Add proper access checking:
- /**
- * {@inheritdoc}
- */
- public function access($operation, array $args = []) {
- $entity = isset($args['entity']) ? $args['entity'] : NULL;
- switch ($operation) {
- case 'create':
- return $this->checkCreateAccess();
- case 'update':
- return $this->checkUpdateAccess($entity);
- default:
- return parent::access($operation, $args);
- }
- }
- ```
- ### 5. Handle Exceptions
- Implement proper error handling:
- ```php
- protected function handleException(\Exception $e) {
- watchdog_exception('my_module', $e);
- return new ResourceResponse([
- 'error' => [
- 'message' => $this->t('An error occurred while processing the request.'),
- 'code' => 500,
- ],
- ], 500);
- }
Best Practices
Always maintain backward compatibility when possible
Document your custom endpoints thoroughly
Implement proper access controls
Add comprehensive error handling
Use dependency injection instead of static service calls
Add proper request validation
Include appropriate response headers
Testing Your Custom Resource
Add PHPUnit tests to ensure your resource works as expected:
- namespace Drupal\Tests\my_module\Functional;
- use Drupal\Tests\rest\Functional\ResourceTestBase;
- class MyCustomNodeResourceTest extends ResourceTestBase {
- // Test implementation
- }
- Common Pitfalls to Avoid
Not handling all HTTP methods properly
Forgetting to update REST configuration after changes
Inadequate error handling
Missing access controls
Not validating input data
Improper response formatting
By following these steps and best practices, you can successfully override Drupal 8 core REST resources while maintaining system stability and security.