NOTICE:
This content is in the "archives" of Gadgetopia. It has been moved to this subdomain as it is no longer considered relevant to the site. It is being hosted here for a indeterminate period of time. Its existence at this URL is not guaranteed, and it may be removed at any time. If you would like to refer to this content in the future, you are encouraged to save it to your local file system.

Adding User-Defined Fields in Movable Type

Originally published by "dbarker" on 2003-10-08 17:15:00Z

I’ve complained off and on about the lack of user-defined fields in Movable Type. Today was finally the day I got off my high-horse and messed with some code.

Here is a method to add a new field to the MT database. The field can store whatever you like, can be queryed on and sorted by (via Brad Choate’s marvelous SQL plugin), and has its own template tag.

Here are some handy uses for this field.

I’ll show you how to add just one, but you can repeat the process to add as many as you like. I’ve named my field “User1,” but you can call yours whatever you need, just modify the examples accordingly.

I’ve tested this, and it seems to work fine, but no warranties are given nor implied. Additionally, this isn’t supported by anyone, and it will preclude running any upgrades from Six Apart. Finally, this is MySQL-centric. I imagine you could get it to work with other data storage systems, but I haven’t tried.

(Warning – this hack isn’t for the faint of heart. You’re going to have to add columns to your database, and rummage around in Perl code. If you don’t know a subroutine from a submarine, maybe you should skip this one.)

(Another warning – this was written for and tested on MT 2.x. No idea how this would work on 3.x.)

Step One: Add the Field to the Database Add a new field to the “mt_entry” table in your MySQL database. I made mine a text datatype, just so I could put anything in it without running afoul of length limitations and such.

If you want to order on it numerically, you can make it a numeric datatype, but you’ll need to take steps to ensure users only enter numbers in the field.

For the purposes of this instruction, I called mine “entry_user1.” You can call it whatever you like, but it has to start with “entry_”. (Remember, if you call it something else, you’ll need to modify all the code samples on this page to match your field name.)

I don’t know if the position of the field in the table matters, but I put mine on the end. (The issue being that if MT gets all the fields, and expects them in a certain order, you’re hosed.)

Step Two: Add the Column to the Data Map Find this file:

lib/MT/Entry.pm

Somewhere around line 17, you’ll find an array defintion called “columns.” It’ll look like this:

columns => [ ‘id’, ‘blog_id’, ‘status’, ‘author_id’, ‘allow_comments’, ‘title’, ‘excerpt’, ‘text’, ‘text_more’, ‘convert_breaks’, ‘to_ping_urls’, ‘pinged_urls’, ‘allow_pings’, ‘keywords’, ‘tangent_cache’,

Add your new field (minus the “entry_” prefix) to end of this, so the last line looks like this:

'tangent_cache','user1',

Step Three: Add a New Textbox to the Editor Find this file:

tmpl/cms/edit_entry.tmpl

Add this code somewhere in the main editing interface table. I put mine starting at line 433, but my line numbers are a bit off from my last hack, so your mileage may vary.

User-Defined Value 1

<><tmpl_if name="AGENT_MOZILLA”> cols=”” class="width500” name="user1” rows="5” wrap="virtual”><tmpl_var name="USER1”></tmpl_var><tmpl_if></tmpl_if></tmpl_if>

This puts a new textbox in the editing interface, and links the field to it. If you want your field to run of some other form element – a drop-down, a checkbox, a radio button, etc. – modify the HTML accordingly.

Step Four: Add the Template Handlers Find this file:

lib/MT/Template/Context.pm

Look for a subroutine called “init_default_handlers.” It starts around line 70. It has a bunch of lines in it that start:

$ctx->register_handler…

Add this line:

$ctx->register_handler(EntryUser1 => \&_hdlr_entry_user1);

This tells MT what to do when it runs into the template tag “MTEntryUser1.” We’re telling to run the subroutine “_hdlr_entry_user1.”

Now you just need to add this subroutine to the file. Find a spot in the file that isn’t in the brackets of any other subroutine (the very end of the file will do), and add this:

sub hdlr_entry_user1 { my $e = $[0]->stash('entry’) or return $_[0]->_no_entry_error('MTEntryUser1’); defined $e->user1 ? $e->user1 : ‘'; }

You’re all done. You now have a new field in MT. You can access the contents of the field in templates with the tag…

``

You can also use Brad’s plugin to query it:

This would give you all the entries where something had been entered in the field.

Here are a couple of handy uses for this:

Explicit Filenames I have MT generate filenames based on the entry title. But what if that filename conflicts with something else, or I just want it to have another name for some reason?

I have a user-defined field called “entry_filename” where I can enter an explicit name for MT to use. If there’s nothing in the field, it forms the filename as usual. (See Mark Pilgrim’s article for how he set this up – he did it using a plug-in to store the filename, but the basic theory is the same.)

Key/Value Data Brad has a great key/value plugin that you can use to store arbitrary data. However, you have to re-use a current field, like the Excerpt or Keywords fields, to use it. You can tack them on underneath data in an existing field, but for some users, this is just too abstract to understand (“You mean that stuff won’t appear in my article? By it will appear over there? Even though I typed it right…there?”).

Add a new field called “entry_keyvalue” and use it to store this data away from everywhere else. This is much easier for the user to get. Access it this way:

``

Arbitrary Ordering Want to control how your entries are ordered on index pages? Just add a field for “entry_sequence” and use Brad’s SQL plugin to get the entries, ordering using this field (“…ORDER BY entry_sequence”). You can number your entries from 1 to a million and they’ll appear in that order on the index page.

(Remember what I said before, however, you need to take steps to make sure users don’t enter non-numeric values in this field. A client-side JavaScript form validation script will do in a pinch.)

If you use this hack, please let me know. I’d be interested in how it works for you, how I can improve this instruction, and what you’re using it for.

Comment by "john" on 2003-10-08 13:29:00Z
Outstanding Deane -- Next time I need this functionality I'll give it a try.
Comment by "Deane" on 2003-10-08 17:22:00Z
For my next trick, I want MT to use different "edit_entry" templates for each blog, so that you can customize the editing interface -- label the fields differently, have different form elements, etc. For instance, you could have a blog for an event calendar, and have fields for "recorrance," "start time," "end time," etc. Instead of the user having to remember want info gets hacked into what field, you could present them with a customized editor.
Comment by "Mean Dean" on 2003-11-12 09:51:00Z
Why didn't I see this post earlier? I could kiss you on the lips for this one. I've been thinking, if I could just add 2 fields, I could take the "web links" portion of blogs4God and move it entirely into MovableType.
Comment by "Mean Dean" on 2003-11-13 12:29:00Z
It's official, you've been blogged: [http://www.healyourchurchwebsite.com/archives/001073.shtml](http://www.healyourchurchwebsite.com/archives/001073.shtml)
Comment by "Deane" on 2004-01-05 17:07:00Z
I just did an install with no less than six user-defined fields: one for key/value information, and five for whatever. It seems to work perfectly.
Comment by "Hans" on 2004-07-29 06:44:00Z
Thanks for the great hack! It is very well described and even feaseable for a "faint of heart" as me. An addition: If you want to use the public search module built in MovableType (I use 2.661) you just need to extend a single line in /lib/MT/App/Search.pm Around line 440 you'll find the subroutine sub *search*hit Just add your new field like this: @text*elements = ($entry->title, $entry->text, $entry->text*more, $entry->keywords, $entry->user1); and you are done.
Comment by "zeebeest" on 2004-10-17 06:56:00Z
Hi, this hack doesn't seem to work with version 3.11. Was anyone of you able to do the same thing in v3.11?
Comment by "sasco" on 2004-10-31 18:12:00Z
The main problem I'm having in MT v.3.* is that the template file no longer uses tables, instead it uses CSS for everything. I'm sure this is still a feasable hack but it's going to take someone a lot smarter than me to figure it out.
Comment by "zeebeest" on 2004-11-02 16:09:00Z
Ah I figured it out! I added a post on how to add an extra field (including changing some other back-end display options and taking into account your new field in the export function) on my site (see Category MovableType) in Dutch. I'm planning on translating the post to English as well, but in the mean time: If anyone needs any help on this in any other language then just let me know (not here, but on my own site...)!
Comment by "Fabio" on 2004-12-08 16:37:00Z
Hi :) just used that and some other stuff i developed to build some avatar stuff on my site's comments system :)) thanks! if you want to know what i did contact me on morroida at gmail :)
Comment by "mattiz" on 2005-03-07 16:34:00Z
You are a hero! This works excellent and very easy to do.
Comment by "PeteoFun" on 2005-04-27 11:00:00Z
This hack is great, and makes MT more of an all purpose CMS. I wish it didn't prevent upgrading MT's version though.
Comment by "Craig" on 2005-06-06 14:38:00Z
Thanks for these instructions. I implemented them with 2.66 but soon enough it got to be a pain to upload my saved tmpl files all the time. I think I will settle for Brad Choate's KeyValue plugin, even if it is a little less 'elegant' because I don't need to "upgrade" every upgrade. This is a personal choice but for people who would rather not bother tweaking code everytime, it is worthy of consideration.
Comment by "Ben" on 2005-07-21 13:10:00Z
Hi, Thanks for the tip. Unfortunately, I am looking for native support of this feature since I am running under the BerkleyDB, not MySql. But, thanks again for sharing this with me. I'll bookmark it and maybe I will switch to MySql in the near future so this will work.
Comment by "Dave" on 2005-08-31 10:01:00Z
Hey thanks for this -- got the bank end working fine -- but when i try to build the site, i get Undefined subroutine &MT::Template::Context::*hdlr*entry_location called at lib/MT/Builder.pm line 159. any ideas? line 59 is : my $out = $h->($ctx, \%args, $cond); thanks!
Comment by "Dave" on 2005-08-31 10:41:00Z
Found the problem! Is was the space between sub and *hdlr*entry_user1 { sub *hdlr*entry_user1 { should be sub*hdlr*entry_user1 { thanks!
Comment by "Dave" on 2005-08-31 12:01:00Z
Ok, I'm stuck now! It's all working in the backend I've got nice fat tags in my individual template like But nothing appears! Any ideas?
Comment by "Dave" on 2005-09-01 09:09:00Z
fixed it -- stoopid typo in context.pm -- sorry!
Comment by "Kevin" on 2006-01-23 07:02:00Z
Hi, thanks for the tip! I have a question I'm hoping someone can answer. I added a new field that holds an integer, and everything worked great. So I tried adding a second field the exact same way as the first (only difference is that it holds a varchar(40) data type in the mysql db). However, whenever I reference my other tag, I get the following error: "Building results failed: Error in tag: Error in tag: You used an 'MTEntryBoxShot' tag outside of the context of an entry; perhaps you mistakenly placed it outside of an 'MTEntries' container?" Again, I followed the instructions exactly the same in both cases, but for some reason, the second on I added wants to be inside an tag. Any ideas?
Comment by "Kevin" on 2006-01-23 10:16:00Z
Nevermind, I figured out my problem :) Thanks again for such a well written tutorial, this was a life-saver for me on a project I'm working on right now.
Comment by "Cameron" on 2006-07-14 17:07:00Z
designing something that needs another field in 3.2, but unfortunately I get an error 500 when I try this method. Darn!
Comment by "Tobias Beruf" on 2006-09-14 11:50:00Z
But you have to pay for it so i can use the time for you.
Comment by "Inda" on 2006-10-25 15:34:00Z
Hi, people!! Great new site about gay sex! The youngest, freshest and hardest porn for FREE! Updates Everyday! [gay twins kissing](http://www.hotgayguy.info/gaytwinskissing.html) Best porno pics and video !!! All category, millions movies and photos !!!