Fix for FirstCustomFieldValue not returning value if global custom field specified by name

I couldn’t find the answer in the RT list archives. If someone has a
better solution (or if there isn’t a problem and I’m just using the API
incorrectly) I’d be interested in being corrected.

Problem: RT 3.0.7_01 issue. $Ticket->FirstCustomFieldValue(x), where x
is the integer id of a custom field or its textual name, should return
the value of the custom field. If the custom field is a global one
rather than queue specific then it only works if the integer id of the
custom field (i.e. the value in the ‘id’ column of the CustomFields
table) is specified. It seems like it should work using the id or name
of the custom field whether it is a global or queue specific custom

Cause: This is because FirstCustomFieldValue makes a call to
CustomFieldValues which then either loads the custom fields by id (works
fine) or by using the id of the queue that the ticket is in
($Ticket->QueueObj->Id). A queue ID is an integer > 1. A queue id of 0
signals a global value so passing in the ticket’s queue id means that a
global custom field value can’t be retrieved if one wants to specify the
custom field by name.


  • Copy $RT_HOME/lib/RT/ to

  • Cut out everything except the FirstCustomFieldValue and
    CustomFieldValues subroutines.

  • Modify both to pass an additional parameter ($isGlobalCustomField).
    If that parameter is passed, then have CustomFieldValues make its call
    for the custom field values as:

    $cf->LoadByNameAndQueue(Name => $field, Queue => 0);

otherwise go with the RT default which only works if the custom field is
queue specific:

$cf->LoadByNameAndQueue(Name => $field, Queue =>

  • Restarting Apache then means that having the following in a Mason

    <%$Ticket->FirstCustomFieldValue(“Foo”, 1)%>

    Will invoke the new code and display the value of global custom field

    Having the Mason code as the usual RT call:


    so other RT pages will continue to work as they always have: This
    change (as far as I can see) doesn’t break any existing code.

    The code for is given below. Even if this change
    turns out to be unnecessary it illustrates how trivial it is to
    easily change/extend RT given the thought that went into the
    *, *, * conventions and directory

Gurdon Merchant Jr.
Invisible IT

use strict;
no warnings qw(redefine);

sub FirstCustomFieldValue {
my $self = shift;
my $field = shift;
my $isGlobalCustomField = shift; # Set to true if requesting a
global custom field by name.

my $values = $self->CustomFieldValues($field, $isGlobalCustomField);
if ($values->First) {
    return $values->First->Content;
} else {
    return undef;


sub CustomFieldValues {
my $self = shift;
my $field = shift;
my $isGlobalCustomField = shift; # Set to true if requesting a
global custom field by name.

my $cf = RT::CustomField->new($self->CurrentUser);

if ($field =~ /^\d+$/) {
} else {
    if ($isGlobalCustomField) {
       $cf->LoadByNameAndQueue(Name => $field, Queue => 0);
    } else {
       $cf->LoadByNameAndQueue(Name => $field, Queue =>

my $cf_values = RT::TicketCustomFieldValues->new( $self->CurrentUser

# @values is a CustomFieldValues object;
return ($cf_values);