Answers.Body: <p>This will result in one api call per row, which can add up to a lot of queries on the db.</p>
  
  <p>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 <code>array_search</code> or similar for each row to get the proper value.</p>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-02-01T16:24:42.820Z
Answers.Text: 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.
Answers.UserDisplayName: Eli Lisseck
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-02-02T03:17:15.017Z
Answers.Text: 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.
Answers.UserDisplayName: Coleman
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-02-02T13:16:12.943Z
Answers.Text: 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.
Answers.UserDisplayName: Eli Lisseck
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-02-01T03:53:40.063Z
Answers.LastActivityDate: 2017-02-01T03:53:40.063Z
Answers.UserDisplayName: Coleman
Body: <p>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.</p>
  
  <p>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:</p>
  
  <pre><code>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' =&gt; $value, 'return' =&gt; 'name'));
          }
          $entryFound = TRUE;
        }
  </code></pre>
  
  <p>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?</p>
  
  <p><strong>EDIT:</strong> Here is what i've ended up with (working) based on Coleman's answer below:</p>
  
  <pre><code>        //Inside alterDisplay but outside foreach($rows) loop...
  
  $results = civicrm_api3('LocationType', 'get', array('sequential' =&gt; 1, 'return' =&gt; 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;
  }
  </code></pre>
  
  <p><strong>EDIT 2:</strong> Even better version without 'sequential' or the foreach loop based on Coleman's comment below.</p>
  
  <pre><code>            //Inside alterDisplay but outside foreach($rows) loop...
  
      $results = civicrm_api3('LocationType', 'get', array('return' =&gt; 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;
      }
  </code></pre>
  
Tags: <civireport><custom-reports>
Title: Is calling the api in a report template 'bad form'?
ThreadText: # Is calling the api in a report template 'bad form'?
  
  (Asked by: username_0 on 2017-01-31)
  
  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 username_1'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 username_1'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;
      }
  
  ```
  
  **Tags:** civireport, custom-reports
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2017-02-01. Score: 3 | Accepted answer
  
  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.
  
  > **Comments:**
  > **username_0**: 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.  
  > **username_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.  
  > **username_0**: 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.  
  
  ---
  
  