Mind: blown (or: How to use Drupal’s post teasers properly)

This past week I was lucky enough to take Drupal module development course taught by Gord Christmas. Gord showed the class a lot of really cool stuff, and helped solidify my understanding of some heretofor-considered black Drupal magic (it’s now white magic) - and also demonstrated what rapid prototyping can accomplish in a classroom setting.

But the coolest thing by far that happened was a little aside he travelled down in response to a (slightly snide) comment by yours truly: I said something like “Pshaw. Teasers? Who even uses those things anyway?”

And then Gord said “Well, actually…” And then he totally blew my mind.

I had always thought that teasers were an outmoded display method, a legacy from the old Drupal 5 days. I’d always considered them sort of old-fashioned – nobody ever uses the “river of news” front-page display anymore, and teasers seemed to belong to a quaint era before Views offered its lovely “truncate to X words and add elipses” option.

How wrong I was.

“Only use fields if you have tabular data to display. Otherwise, use Full Node.” The idea here is that you configure teasers in Display settings, and then set up your templates to be aware if it’s a teaser or not, so you can theme it (the full node’s view mode lets you exclude links and whatnot typically shown on full posts, so this might not even be necessary for most things). Then you use Node view in your Views, and what pops out is consistent, every time.

Mind? Blown.

Using teasers for fun and profit

  • In any list-type view, instead of adding fields each time you set up a similar view, use Node View and set the Build Mode to teaser.
  • Actually configure teasers in your content-type settings – because they’re separately configurable you can show/hide, change display format, and outright exclude totally different things from teasers as from full node. Teaser length is configurable per content-type if you download a little module for 6. It’s rolled into 7.
  • Create per-content-type node.tpl.php files. In each templates, test for teaser mode existence and output accordingly (because chances are different types will have different layout needs.)
  • In your css, theme *once*, instead of adding CSS classes to your views and tacking on different view-types to .views-row and .views-field-xxx-xxx…

And voila. The payoff is consistent Views displays and no fiddling with fields, consistent single-point-of-configuration, very consistent look across views, much less CSS and easier theming, and a bit of database/caching ease, too.

The trade-off is “extras” – throwing an extra field into a single view will have the same overhead as it did before, you’ll have to add all the fields, and theme for it, etc, etc. But most of the ways we use views is to display lists, and for the most part the only time we change how things look in those lists is for different content-types – and then they appear that way all over the site. We rarely add “just one extra field” unless we’re doing something very View-y like complex relationships using different views-hooked-module-field-output. Because we can still leverage the power of filters, arguments, and relationships, however, those use-cases shrink to something fairly small. And it’s the same amount of work to deal with those anyway.

Now, I haven’t tried this myself. I’m sure as shooting going to try it for the next site I develop. I’ll let you know how it goes – it sounds like a bit more work up front, but thinking about it for half a second reveals that it might actually save tonnes of time, and cut down my swear-words-per-hour rate to something close to manageable.

What are your thoughts? Does this look totally mind-blowing, or more trouble than it’s worth (you know where I stand! =) ?

UPDATE: Was recently reading some performancy-things, and found this entry: avoid calls to node_load. They explicitly recommend using fields in views. Hmm. Mind still blown, but wondering… :) If it’s a small performance trade-off then with caching and whatnot it shouldn’t make a huge difference, but it will depend on the size of the site and your priorities. Benchmark away.

Stop wasting my time! (or: a primer on using Drupal properly)

I think I can safely say that I speak for 95.6% of all frustrated Drupal professional out there when I tell new developers this:

STOP creating custom modules and proprietary solutions.

Just… stop it. For every proprietary project that goes and duplicates 96% of the work another proprietary project already created, there’s an open-source developer like me crying into her beer because of the horrible waste of human capital and interoperability this represents.

This isn’t just a Drupal problem, it’s an open-source problem, but I see it here because this is my world.

The problem? Programmers.

Don’t get me wrong: I work with programmers. I love programmers! But programmers love to program. That’s what they do. When you hire a programmer, nine times out of ten they do not carefully research possible solutions, find one that pretty-much-fits, implement it, and customize it using the tools the solution itself provides. That’s not what they trained to do in their university Computer Science classes! Nooo. They were trained to program. So they whip out their favourite text editor, they get up to their elbows in API, and they start writing code.

And then I get to spend a not-insignificant number of billable hours, after they’ve gone on their merry way, ripping out all that lovely hand-written custom module logic, exporting custom database tables, and re-implementing everything in basic out-of-the-box Drupal just so that a customer’s site can be upgraded and properly maintained.

I hate doing this. I really, really do.

One developer friend I work with joked “The client looked at the site and said ‘It looks exactly the same…’ and I was like ‘YES! ISN’T THAT AWESOME?’” The difference was invisible, but crucial: the first version (which she was hired to ‘maintain’) was hideously insecure and totally un-upgradable; the second version was done properly, and could be maintained going forward using standard Drupal tools and best-practices.

Unfortunately, clients do not care what goes on under the hood, they just want it to work, so this puts the new developer they hire to fix whatever goes wrong in a huge bind. Clients don’t really understand the fundamental difference between solutions — they just see line-items on an invoice, and they don’t get the open-source mentality of security-by-lots-of-eyes, or contributing-work-back-to-the-community. They just understand functionality. If it works, they pay.

This just encourages programmers who should really know better, and screws the people who have to clean up after them.

But all is not lost: clients are willing to listen. They don’t want to have to go back and re-do everything when they get hacked, or when they try to upgrade versions and find they can’t. But if we don’t educate them, they will naturally blame the software, not the developer. We can’t expect them to magically understand the amount of work that needs to go on just to make their site look and function identically to their old site because their programmer loved to program. They just get a bill, and blame Drupal.

Drupal doesn’t need this.

Now, sometimes, I realize, it’s necessary to implement proprietary stuff. Sometimes you’re working with weird, antiquated and cantankerous systems that just need a good smacking-down in the form of a custom module. Oh, yes, I have met those. But this is rare. I have seen so many custom implementations of modules already well-maintained on Drupal.org that I want to cry. My first question is always “Can you write a rule for that?” “Did you create an action?” “TRIGGERS!” “This is a CCK field, right?”

I once helped rip out an entire web store done with its own database tables; we were able to re-implement the whole thing using just CCK, Views and Ubercart. And I will never get those hours of my life back.

A more egregious example is this: one site I worked on had a lovely custom-LDAP module set up, to add users from the company’s LDAP directory and give them pre-defined Drupal roles. WAIT A MINUTE. THAT SOUNDS FAMILIAR.

Well, of course it does: there’s already an LDAP module! And it works out of the box. It’s not perfect (it needs some work on provisioning, for example, because of the way PHP pages results) but it is a Drupal-community-maintained module. If the developer had the time to create a whole new custom module, writing thousands (yes) of lines of code to do exactly the same thing as the LDAP module, why couldn’t she or he have just implemented the LDAP module and helped fix it up where it didn’t fit their needs — and contribute it back?

Well, he or she probably didn’t know about it, because they probably just cracked open a text editor and started coding.

In all cases where this happens, the open-source community loses the chance to have a great programmer working on a module or project that can use some TLC (not to talk smack about any particular module — all Drupal modules need TLC, all the time, and they all need people willing to test and patch, always! Because this is software we’re talking about.)

So, all new Drupal developers? DO NOT REINVENT THE WHEEL.

Feel free to add some sparkles, feel free to maybe put on a nice hub-cap or two, but stop making things that already almost exist. Search! Use some of those analytical skills to assess existing solutions! And, if you do create something and it seems useful, stop keeping it to yourself: this is a community, and we need your contributions. Try to generalize it, and then give it back. Use your amazing developer skills to do it the Drupal way.

The community will thank you, and so will I – the fewer sites I have to fix, the better.

How to handle taxonomies – CCK Fields or default?

I’ve recently come to the conclusion that it’s far better to add vocabularies via CCK than it is to use the default Taxonomy setting.

Why? Oh, so many reasons. Here are three:

  1. Content display
  2. Tokens
  3. Views

1. Content Display

Main Drawback of Drupal’s Taxonomy: You can’t separate out a specific vocabulary for special theming. You also can’t choose to display only one vocabulary, and have another be hidden.

The default Drupal implementation of taxonomies are all-or-nothing. If you have several vocabularies assigned to a content type – like, say, a site vocab and an audience vocab, and a free-tagging vocab, then Drupal just treats them as “terms” and prints them all in a block at the bottom of your post (for the programmers in the audience: they’re all lumped into the $node['vocabularies'] variable).

With CCK Content Types in place of the default taxonomy, though, you can set what shows up on the field’s “Display” settings page, and can choose to hide vocabularies there. You can also theme them separately on the theme layer.

2. Tokens

Main Drawback of Drupal’s Taxonomy: You can’t separate out a specific vocabulary for use in tokens.

The default Drupal implementation of taxonomies is also all-or-nothing in tokens. For example: if you’re using Pathauto and want to create “Category” paths, you can only tokenize the term that happens to come first in the first vocabulary assigned to your node. What?!

Using separate CCK fields, on the other hand, lets you choose the vocabulary you want to use – it’s available as a token, and since they are separate, well, there you go.

3. Views

Main Drawback of Drupal’s Taxonomy: Again, mainly by virtue of being separated out, CCK taxonomies allow you to use separate vocabs in views. This allows you to sort much better when displaying fields.

Main Drawbacks of using CCK Fields: Well, this is great for View fields, however it’s not so great for View arguments, because they’re specially written to leverage Drupal’s main site taxonomy… as are a lot of things.

OK, so can we do both?

YES! Views “Arguments” implementation is written to mesh really well with Taxonomies, allowing you to, for example, take the page terms as a default argument into a block (by specifying “Provide Default Argument”) and filtering on them. If you are using CCK Fields, of course, this becomes a problem. Unless…

Workarounds: Always always always select “Save terms to core taxonomy tables” when adding a CCK Taxonomy Field. You have to have the core Drupal Taxonomies set up in advance anyway – CCK Fields can just be used as a better way to leverage them. So make sure you’re still saving all those terms onto your nodes as if they were using core Taxonomy terms. That way you can have the best of both worlds. Really.