How to Override a REST Resource from Drupal Core
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.