7.x field.api.php hook_field_access($op, $field, $entity_type, $entity, $account)

Determine whether the user has access to a given field.

This hook is invoked from field_access() to let modules block access to operations on fields. If no module returns FALSE, the operation is allowed.


$op: The operation to be performed. Possible values: 'edit', 'view'.

$field: The field on which the operation is to be performed.

$entity_type: The type of $entity; for example, 'node' or 'user'.

$entity: (optional) The entity for the operation.

$account: (optional) The account to check; if not given use currently logged in user.

Return value

TRUE if the operation is allowed, and FALSE if the operation is denied.

Related topics

1 function implements hook_field_access()

Note: this list is generated by pattern matching, so it may include some functions that are not actually implementations of this hook.

field_test_field_access in modules/field/tests/field_test.field.inc
Implements hook_field_access().


modules/field/field.api.php, line 2751
Hooks provided by the Field module.


function hook_field_access($op, $field, $entity_type, $entity, $account) {
  if ($field['field_name'] == 'field_of_interest' && $op == 'edit') {
    return user_access('edit field of interest', $account);
  return TRUE;


james.williams’s picture

Interestingly, this can also affect the access on the admin UI for editing the field setting. The setting for the default value of the field will be affected by this hook. I found a previously set default value for the field was lost once I had implemented the hook like this and then saved the field configuration form again as an admin:

function MYMODULE_field_access($op, $field, $entity_type, $entity, $account) {
  if ($op == 'edit' && $field['field_name'] == 'field_subscription_status') {
    // This stops users editing their subscription fields, even including
    // admins.
    return FALSE;

The code should stop even admins from editing the 'field_subscription_status' field on content/users. But this will also stop admins being able to choose a default value when configuring this field. To get around this, check the $entity parameter, since it is NULL when configuring the field, but will not be when editing (or creating) content or users. So instead, add a check for !empty($entity) to avoid interfering with the fields admin UI:

function MYMODULE_field_access($op, $field, $entity_type, $entity, $account) {
  if ($op == 'edit' && !empty($entity) && $field['field_name'] == 'field_subscription_status') {
    // This stops users editing their subscription fields, even including
    // admins.
    return FALSE;
Mile23’s picture

That's because you need to assemble a permission and call user_access().

So you'd say something like:

$permission = $op . ' field_subscription_status';
return user_access($permission, $account);

This gives you automatic access if you're user 1, and of course you'll need to add the edit permission to the administrator role if you need to. That's the whole point of implementing permissions on fields. :-)

Also, implement hook_permission() to declare the permissions you want user_access() to check against.

Upchuk’s picture

With this approach you check whether the entity is empty making sure the admin UI for configuring the field when it is being created is not tampered with. But what about configuring an already existing field? Prevents access in this case?



spiderman’s picture

Having been bit by some confusion I had interpreting the comment above re !empty($entity), I thought I'd share a complete working function as an example of how to do this:

function rnao_dollars_field_access($op, $field, $entity_type, $entity, $account) {
  if ($field['field_name'] == 'field_rnao_dollars_continuous') { # Field we care about?
    if (empty($entity)) { # No entity passed, so check user_access
      return user_access('edit own commerce_coupon entities of bundle rnao_dollars', $account);
    } else {              # Entity is being edited, so do a more thorough access check.
      return rnao_dollars_continuous_access($account, $entity);
  } // Else it's not our field, so do nothing.

When I had the logic wrong, my hook was applying to *all* fields inadvertently, and thus causing very strange behaviour on my site :)

jackbravo’s picture

What is the substitute for this in Drupal 8? Is it hook_entity_field_access?

anthonys’s picture