Order Custom Field Not Showing in Drupal Commerce API
Problem/Motivation
When using the Commerce API module in Drupal, custom fields added to orders are not visible in the API response, despite being properly configured in the order entity. This documentation explains the issue and provides a solution for exposing custom order fields through the Commerce API.
Impact
- Custom order fields are not accessible via the JSON:API endpoints
- Unable to read custom field values through the API
- Affects integration with external systems that need access to custom order data
Steps to Reproduce
- Add a custom field to the order entity (e.g., a text field named "Field note")
- Add an item to the cart
- Access the checkout endpoint via URL:
/jsonapi/checkout/{checkout-uuid}
- Observe that the custom field is not present in the JSON response
Root Cause
The issue stems from the Commerce API module's FieldAccess
service, which controls which fields are exposed through the API. By default, this service restricts access to custom fields for security reasons.
Solution
1. Create a Service Provider
Create a custom service provider to override the default FieldAccess
service implementation.
File: modules/custom/my_module/src/MyModuleServiceProvider.php
<?php
namespace Drupal\my_module;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Drupal\Core\DependencyInjection\ServiceProviderBase;
use Drupal\Core\DependencyInjection\ServiceProviderInterface;
class MyModuleServiceProvider extends ServiceProviderBase implements ServiceProviderInterface {
public function alter(ContainerBuilder $container) {
$definition = $container->getDefinition('commerce_api.field_access');
$definition->setClass('Drupal\my_module\FieldAccess');
}
}
2. Extend the FieldAccess Class
Create a custom FieldAccess
class that extends the original one and adds your custom fields to the allowed list.
File: modules/custom/my_module/src/FieldAccess.php
<?php
namespace Drupal\my_module;
use Drupal\commerce_api\FieldAccess as OriginalFieldAccess;
class FieldAccess extends OriginalFieldAccess {
/**
* {@inheritdoc}
*/
protected function getAllowedViewFieldNames(string $entity_type_id): array {
$field_names = parent::getAllowedViewFieldNames($entity_type_id);
if ($entity_type_id === 'commerce_order') {
$field_names = array_merge($field_names, [
'field_custom_field_1',
'field_custom_field_2',
'field_custom_field_3',
]);
}
return $field_names;
}
}
Implementation Notes
- Replace
my_module
with your actual custom module name - Update the list of field names in
getAllowedViewFieldNames()
to match your custom field machine names - Clear the Drupal cache after implementing these changes
Related Issues
Additional Information
- This solution maintains the security of the Commerce API module while allowing specific custom fields to be exposed
- Remember to only expose fields that are safe for API consumers to access