1

Just a small question - but I've been asked to add 'Address Location Type' as a column in a report. At least as of our civiCRM version (4.7.13) the address seems to me to only contain the location type ID - which doesn't make much sense to users.

I wasn't able to readily find a pseudoconstant function available to handle location type id -> location type name like there are for things like State/Province and Membership Type... so I have it working with the api as below:

if (array_key_exists('civicrm_address_location_type_id', $row)) {
        if ($value = $row['civicrm_address_location_type_id']) {
          $rows[$rowNum]['civicrm_address_location_type_id'] = civicrm_api3('LocationType', 'Getvalue', array('id' => $value, 'return' => 'name'));
        }
        $entryFound = TRUE;
      }

My question is out of curiosity because I haven't run across an api call in alterDisplay like this (maybe it exists and it's fine) but... is there a better way to do this / is it bad form to get at the location type name this way?

EDIT: Here is what i've ended up with (working) based on Coleman's answer below:

        //Inside alterDisplay but outside foreach($rows) loop...

$results = civicrm_api3('LocationType', 'get', array('sequential' => 1, 'return' => array("name")));
$locationTypes = array();
  foreach ($results['values'] as $item) {
    $locationTypes[$item['id']]=$item['name'];
  };

        //now for each row it's just...

if (array_key_exists('civicrm_address_location_type_id', $row)) {
  if ($value = $row['civicrm_address_location_type_id']) {
    $rows[$rowNum]['civicrm_address_location_type_id'] = $locationTypes[$value];
  }
  $entryFound = TRUE;
}

EDIT 2: Even better version without 'sequential' or the foreach loop based on Coleman's comment below.

            //Inside alterDisplay but outside foreach($rows) loop...

    $results = civicrm_api3('LocationType', 'get', array('return' => array("name")));

            //now for each row...

    if (array_key_exists('civicrm_address_location_type_id', $row)) {
      if ($value = $row['civicrm_address_location_type_id']) {
        $rows[$rowNum]['civicrm_address_location_type_id'] = $results['values'][$value]['name'];
      }
      $entryFound = TRUE;
    }

1 Answer 1

3

This will result in one api call per row, which can add up to a lot of queries on the db.

A lighter-weight solution would be do do a single api call before the loop to look up all location types and store them in a local variable, then you can use array_search or similar for each row to get the proper value.

3
  • That makes lots of sense - thanks! I couldn't grok getting array_search exactly working, but i've edited my question with some working code with just one api call based on this answer, in case someone else finds that useful. Feb 1, 2017 at 16:24
  • 1
    That looks good. One optimization: If you take out the sequential=1 from your api call then they will already be indexed by id and you won't need the foreach ($results['values'] loop.
    – Coleman
    Feb 2, 2017 at 3:17
  • Oops looks like I am guilty of not rtfm again for basic api parameters before I tried things out and made it harder on myself :). Thank you for the kind help! I have added a further edit with a third (better) version. Feb 2, 2017 at 13:16

Your Answer

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

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