I'm trying to customise the top-left quicksearch box so that it recognises some of our internal codes without selecting a specific option in the dropdown.

I used to adapt xavier's great Quick Contact Autocomplete extension, but this uses the crmAutocomplete action which I think went away in 4.5.

Is there a particular recommended way of doing this in 4.5+?

  • What are your internal codes? Custom fields? External identifier core field? Or... ?
    – Coleman
    Commented Jul 17, 2015 at 14:30
  • External identifier, plus a custom field that's always in a specific format. I taught xavier's extension to recognise the format and fall back to a regular search if not - just trying to replicate that really. Just wanted to save our admin team a couple of clicks on each search. Commented Jul 17, 2015 at 14:34

3 Answers 3


For customizing the list of options, see this question.

To override the quicksearch behavior, you could try hook_civicrm_apiWrappers to modify the output of the contact.getquick api.


I found it quite hard to replace the customization done with hook_civicrm_contactListQuery (CiviCRM <= 4.4) with the new hook_civicrm_apiWrappers (CiviCRM >= 4.5).

So I am sharing my results here.

My goal is to have a way to search quickly either by contact name, or by a custom field that stores a member identifier (different from internal identifier and external identifier).

My old code looked like this :

function myext_civicrm_contactListQuery( &$query, $name, $context, $id ) {
  if ($context == 'navigation') {
    // if not name / email search, just keep the standard behavior
    if (!isset($_GET['tableName']) || $_GET['tableName'] != 'cc') return;

    // if the search is a number, try to look for the custom member id
    if (is_numeric($name)) {
      $query = "SELECT cc.id as id, CONCAT_WS( ' :: ', CONCAT(sort_name, ' (', im.num_ro_de_membre_37, ')') ) as data, sort_name
                FROM civicrm_contact cc
                LEFT JOIN civicrm_value_r_sum_de_membre_6 im ON ( cc.id = im.entity_id ) 
                WHERE im.num_ro_de_membre_37 = '$name'
                AND cc.is_deleted = 0
                LIMIT 5";

    } elseif (strlen($name) < 2) {
      $query = "";


And now :

function myext_civicrm_apiWrappers(&$wrappers, $apiRequest) {
  if ($apiRequest['entity'] == 'Contact' && $apiRequest['action'] == 'getquick') {

    // search by member id if the search is a numeric value
    if (is_numeric($apiRequest['params']['name'])) {
      $wrappers[] = new CRM_Myext_APIWrapper();

// i need to do this because there is no function civicrm_api3_contact_getlist
function emulate_civicrm_api3_contact_getList($params) {

  // not loaded by default
  include_once "api/v3/Generic/Getlist.php";
  include_once "api/v3/utils.php";

  $apiRequest = array(
    'entity' => 'Contact',
    'action' => 'getlist',
    'params' => $params,
  $res = civicrm_api3_generic_getList($apiRequest);

  // reformat the output to look like getquick
  foreach ($res['values'] as $idx => $value) {
    $res['values'][$idx]['data'] = $value['extra']['sort_name'] . " ({$value['extra']['custom_37']})";

  return $res;

And a new APIWrapper class in a dir CRM/Myext/APIWrapper.php :

class CRM_Myext_APIWrapper implements API_Wrapper {

  public function fromApiInput($apiRequest) {

    // change api call - getquick is deprecated and doesn't work with custom field
    $apiRequest['entity'] = 'Contact';
    $apiRequest['action'] = 'getlist';
    $apiRequest['function'] = 'emulate_civicrm_api3_contact_getList';

    // change name param to field custom_37 and remove useless params
    $apiRequest['params']['params']['custom_37'] = $apiRequest['params']['name'];

    // restrict return data (getlist doesn't use return param)
    $apiRequest['params']['extra'] = array('sort_name','custom_37');

    return $apiRequest;


Based on @samuelsov answer and samples I've developed an extension that could customize the quicksearch fields

More info here: https://civicrm.org/extensions/quicksearch

  • 1
    The extension is in Core since CiviCRM 5.8.
    – samuelsov
    Commented Apr 6, 2021 at 16:16

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.