We have two different user permission groups: Finance team who can see the Contributions tab, and Personnel, who can't. We wanted to hide some custom field tabs for both groups, and mimicked the documentation on the civicrm_tabs hook, simply using

unset ($tabs[12]);

However, the index 12 corresponds to different tabs for the two types of users, because the count changes depending on whether or not the Contributions tab is visible.

How do we hide tabs in a manner independent of the user group and the other tabs they see?

  • Just as a matter of interest, are you also limiting their ability to export? We're in a similar position, and I'm just wondering how other people are doing it... Commented Jul 3, 2015 at 11:13
  • I'm not sure what you mean by "ability to export", but no, we haven't done anything to limit exporting of anything...just used basic CiviCRM Access Control to distinguish between financial people with access to CiviContribute, vs other people.
    – Norris
    Commented Jul 3, 2015 at 17:29

2 Answers 2


The $tabs variable passed into the tabs hook is an array of arrays, with unique identifying values in the "id" column of each entry. I found a function to scan all elements of the array to check the "id" column for a given value. This returns the correct $tabs index to use with the unset() function.

function searchForId($id, $array) {
  foreach ($array as $key => $val) {
    if ($val['id'] === $id) {
      return $key;
  return null;

Example usage:

$duestab = searchForId('custom_15', $tabs); //tab holding dues
unset( $tabs[$duestab] );

If my server used PHP 5.5 or greater, I could have skipped the searchForId function and used a one-liner:

$duestab = array_search('custom_15', array_column($tabs, 'id'));
unset( $tabs[$duestab] );

There is a specific hook to modify the tabs on the Contact Summary. I suggest you use this hook in an extension to make the tabs do what you need them to do? So you could also remove the Contributions tab. Example:

function threepeas_civicrm_tabs(&$tabs, $contactID) {
  $threepeasConfig = CRM_Threepeas_Config::singleton();
   * first check if contact_subtype is country
  if (_threepeasContactIsCountry($contactID) == TRUE) {
    $activeCountryTabs = array('contact_documents', 'rel', 'case', 'activity', 'participant');
    foreach ($tabs as $tabKey => $tab) {
      $projectWeight = $tab['weight']++;
      if (!in_array($tab['id'], $activeCountryTabs)) {
  • Yes, that tabs hook is the one we're using. Your example is a nice option...though it seems to be based on the contact you're viewing, which is different than limiting permissions based on who's viewing the contact. I suppose you could write the hook to check the viewer permissions, but it seems easier to just use the built in ACL system.
    – Norris
    Commented Jul 4, 2015 at 22:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.