Upcoming Events
NYC CiviCRM Meetup - September 7th
September 7th, 2010
This next NYC meetup will feature a case study or 2, a look at what's new in (more...)
Configuring, Customizing and Extending CiviCRM - New York
September 16th, 2010
This comprehensive two-day hands on training course is targeted at (more...)
CiviCRM User and Administrator Training - New York
September 16th, 2010
A comprehensive two day hands on training course covering the configuration, (more...)
CiviCRM Code and Test Sprint - New York
September 18th, 2010
This code and test sprint is targeted at experienced developers who want to (more...)
CiviCRM Toronto Meetup
September 21st, 2010
Come meet others from the Toronto Area who are interested in, using or (more...)
CiviCRM Philly Meetup – September 2010
September 23rd, 2010
Come meet others from the Philadelphia Area who are interested in, using or (more...)
CiviCRM Seminar - Dublin
September 28th, 2010
NfP Services are hosting a free seminar at The IBOA, Stephen St Upper, Dublin 8 (more...)
London developer and implementer training
September 30th, 2010
This comprehensive two-day hands on training course is targeted at implementers, (more...)
London user and administrator training
September 30th, 2010
A comprehensive two day hands on training course covering the configuration, (more...)
Berlin user and administrator training
October 6th, 2010
A comprehensive one day hands on training course covering the configuration, (more...)
Berlin developer and implementer training
October 7th, 2010
This comprehensive one-day hands on training course is targeted at implementers, (more...)
Benelux meetup in Brussels: Connect, communicate and activate your supporters and constituents
October 11th, 2010
Come meet others who are interested in, using or developing for CiviCRM. For (more...)
CiviCRM Toronto Meetup
October 19th, 2010
Come meet others from the Toronto Area who are interested in, using or (more...)
CiviCRM Toronto Meetup
November 16th, 2010
Come meet others from the Toronto Area who are interested in, using or (more...)
Setting and Getting Custom Field Values in CiviCRM Hooks
- Not Just a Contact Database
-
These optional components give you more power to connect and engage your supporters.

civiCONTRIBUTE
Online fundraising and donor management.

civiEVENT
Online event registration and participant tracking.

civiMEMBER
Online signup and membership management.

civiMAIL
Personalized email blasts and newsletters.

civiREPORT
Report generation and template management.
Cross-posted at The Nerdy Adventures of Wes.
CiviCRM isn't always the most predictable codebase. Recently I needed to get and set some custom field values in a hook I was writing. The hook's job was to calculate some custom field values and create some contact references when a contribution was created or updated. As always, dlobo was a huge help (he's the CiviCRM guru, find him in #civicrm on Freenode). Here's what I did to set a couple of custom fields in my _pre hook:
$custom_fields = array('foo' => 'custom_1', 'bar' => 'custom_2');
function modulename_civicrm_pre ($op, objectName, $objectId, &$objectRef) {
if ($objectName != 'Contribution' || ($op != 'edit' && $op != 'create')) {
return;
}
$contribution_id = $objectId;
require_once 'CRM/Core/BAO/CustomValueTable.php';
$my_foo = 'blah';
$my_bar = 'baz';
$set_params = array('entityID' => $contribution_id,
$custom_fields['foo'] => $my_foo, $custom_fields['bar'] => $my_bar);
CRM_Core_BAO_CustomValueTable::setValues($set_params);
}
And here's an example for retrieving some custom field values from the contact object in the same hook:
$custom_fields = array('contact_foo' => 'custom_3', 'contact_bar' => 'custom_4');
function modulename_civicrm_pre ($op, objectName, $objectId, &$objectRef) {
if ($objectName != 'Contribution' || ($op != 'edit' && $op != 'create')) {
return;
}
// set the field names to 1 that we want to get back
$get_params = array('entityID' => $objectRef['contact_id'],
$custom_fields['contact_foo'] => 1, $custom_fields['contact_bar'] => 1);
require_once 'CRM/Core/BAO/CustomValueTable.php';
$values = CRM_Core_BAO_CustomValueTable::getValues($get_params);
$my_cfoo = $values[$custom_fields['contact_foo']];
$my_cbar = $values[$custom_fields['contact_bar']];
}
So it's not ideal that you have to hard-code the custom field IDs; there should be a way to look them up (maybe there is). But it's not the worst thing in the world unless you're in the habit of destroying and recreating your custom fields from time to time. Probably you're not on a production system.







Comments
The code in my original post has a bug in it
The code in my original post has a bug that makes it only work for updating existing objects. For new objects, it will fail because there is no object yet in a pre hook. You should use a post hook instead for this.
Note that the $objectRef is a reference to the BAO instance in a post hook, rather than an array.
Also note that for non-read-only fields, CiviCRM will clobber your hook changes after you make them in a post hook because post fires before the form changes are applied. You probably want a postProcess hook in that case.
added function to get custom field ID
given the field label and an optional group title:
http://issues.civicrm.org/jira/browse/CRM-5805
this will be part of 3.1.2
looking up custom fields
I am in the habit of destroying and recreating my custom fields. :-) Therefore I wrote a function that looks up the custom table name and field names, so that I can use them in the 'real' SQL statements. The function relies on the label for the custom field group and the fields. So as long as the labels stay the same, the code works.
Here is my function, which could be improved on:
function getCustomTableFieldNames(){
//*** Start of section to get table and column names ***/
# Change the next 3 variables to match the labels of the custom field group.
$custom_field_group_label = "Extended Date Information";
$custom_field_birthdate_sunset_label = "Birth Date Before Sunset";
$custom_field_deathdate_sunset_label = "Death Date Before Sunset" ;
/* rest of the function */
$return_custom_birth_sunset = '';
$return_custom_death_sunset = '';
$error_msg = '';
// figure out the table names and field names for custom fields.
$tablename_query = "SELECT civicrm_custom_group.table_name as tablename from civicrm_custom_group
where title = '$custom_field_group_label' and extends = 'Individual' ";
$extended_date_table = '';
$table_dao =& CRM_Core_DAO::executeQuery( $tablename_query );
if ( $table_dao->fetch( ) ) {
$extended_date_table = $table_dao->tablename;
}else{
$error_msg = "Cannot find table for custom field group '$custom_field_group_label'";
$return_values = array( $error_msg, $return_custom_birth_sunset , $return_custom_death_sunset );
return $return_values;
}
$table_dao->free( );
if( $extended_date_table == ''){
$error_msg = "extended_date_table variable is empty";
$return_values = array( $error_msg, $return_custom_birth_sunset , $return_custom_death_sunset );
return $return_values;
}
$date_fields_query = " SELECT civicrm_custom_field.column_name as column_name, civicrm_custom_field.label as label
FROM civicrm_custom_group left join civicrm_custom_field
on civicrm_custom_group.id = civicrm_custom_field.custom_group_id
where civicrm_custom_group.title = '$custom_field_group_label'
and civicrm_custom_group.extends = 'Individual'
and ( civicrm_custom_field.label = '$custom_field_birthdate_sunset_label' or
civicrm_custom_field.label = '$custom_field_deathdate_sunset_label' ) ";
//print "";
$fieldnames_dao =& CRM_Core_DAO::executeQuery( $date_fields_query );
while ( $fieldnames_dao->fetch( ) ) {
$tmp_label = $fieldnames_dao->label;
if($tmp_label == $custom_field_birthdate_sunset_label){
$extended_birth_date = $fieldnames_dao->column_name;
}else if($tmp_label == $custom_field_deathdate_sunset_label ){
$extended_death_date = $fieldnames_dao->column_name;
}
}
if($extended_birth_date == "" || $extended_death_date == ""){
$error_msg = "Cannot find custom field names for before sunset flags for date of birth or date of death";
$return_values = array( $error_msg, $return_custom_birth_sunset , $return_custom_death_sunset );
return $return_values;
}
$fieldnames_dao->free( );
//*** end of section to get table and column names ***/
$return_values = array( $error_msg, $extended_date_table, $extended_birth_date , $extended_death_date );
return $return_values;
}
lookup shoud be in the core
what is the license? public domain and can be recopyrighted ? academic free ?
custom fields
The code I pasted in my previous comment is GPL. Actually I would prefer to see more control given when creating a custom field group. Perhaps the option to do this could be collapsed for "begining" users and expanded for "advanced" users.
The problem I see even with the lookup routine that I wrote: If a end-user changes the label, then my code for custom hooks, reports, etc will break. If I had control over the actual table name and field name in the database, then the end-user could change the labels without worry.
Also for multi-lingual setups, I cannot rely on the label being a known value.