Get custom field ID in Apex
Yes it’s Dreamforce. No I’m not there. No nobody is going to read this blog. Yes it contains a ghetto hack. With that said, lets proceed with the madness.
It was a dark and stormy night. There I was working on this visualforce component, which needed to have a button that would take a user to a new record. That record had to have some information pre-populated so I used the classic URL hack of putting in field IDs and their values into the URL to pass them along (You know how you can pass in something like ?what_id=0036000001nOfOh on the end of a new task url and the what_id field will be populated? Well you can do it with custom fields too by passing in the ID of the field, which isn’t the devleoper name, but a separate ID much like the ID of any other sObject). The problem I then realized that since this code was for a package that could be installed in any org, those Id’s would change, and would have to be fixed for every install of the package in every org. Some poor schmuck would have to go find the IDs of the fields and update the custom button code in every single org.
Sure I could make it a little less painful by using a custom label or setting to read the value from so the person fixing it wouldn’t have to mess with code, but that still sucks. So knowing that you needed the the custom fields Id to do the pre-populate hack, I set out looking for a way to retrieve the ID programatically through apex. As it turns out, this isn’t exactly easy. Because Salesforce hates the URL pre-populate hack (hey we wouldn’t use it if we had a better alternative) and there isn’t much else you can do with the field’s ID, they don’t make it available. It’s not in any describe information anywhere…. except in the tooling API describe calls.
For those unaware the tooling api is a new-ish api Salesforce released to allow you to do more system admin kind of things through programatically. Create objects, fields, check the status of batch jobs and code coverage test results, etc. Mostly intended to allow you to build other cool applications that integrate with Salesforce even more, and maybe even some kind of cool alternative admin interface. But we are going to slap it around and make it give us the field ID we need.
So anywho, first thing’s first, if we intend to call out to an API, any API, we are going to need a remote site exception. So add your own instance URL as an exception if you havn’t already. You know the drill, security->remote site settings-> copy your org url up until right after the .com. Save that. Now time for some code.
Stick this in some utilities class somewhere, and give it a shot. Pass in the name of a field, and you should get back the field ID. Make sure it’s a custom field though, since that is the table that is being queried.
Now I’ll go ahead and say that this method isn’t exactly the cleanest thing in the world. There is a lot of serializing and deserializing going on, and I’m not really wild about it. However in the spirit of keeping this call light weight and easy to use (no additional classes for the JSON deserializing are required) it’s a trade off that I am okay with. This way you can easy add fields to your query if you want, and they’ll just show up in the resulting object. Also the semi-complex nature of the returned JSON makes trying to create the proper Apex class for deserializing a bit more annoying since you can’t have nested inner classes (without the whole thing having it’s own file, which I hate because it feels like it clutters up my org with single use class files). ANYWAY point being is that you get back a nice data object that has the fields as it’s keys and their corresponding values. Because the way the tooling API works doesn’t seem to let you filter by sObject type when querying for custom fields, you’ll have to do that part yourself. The fullname field does have the name of the object, but you can’t run a query filter on it, and I figured I’d leave that part an an exercise for the reader. Simply iterate over the resulting list, evaluate the fullname field to see if it contains the name of the object you want, and then read the field ID.
So now with the field ID gettable, you can put it into your URL hacks from your visualforce pages. Simply call the method, use the resulting ID’s to build your URL. Honestly I’d recommend storing the ID’s in a custom setting or something so you don’t have to be waiting on an HTTP request to run and all this JSON to parse every time you want to construct the URL, but that’s just me. Anyway, hope you guys like this and find it useful. Till next time.
(Also, I’d love to see a more efficient, less serializing, deserializing version of my function if you think you can make it better).