WordCamp 2012

Wow, it’s been almost two weeks since Vancouver WordCamp 2012, the awesome one-day conference on all things WordPress. As last year, the event was divided into Design and Development tracks. And again as last year, I went back and forth between the two. Let’s face it, the line between design and development can pretty thin.

Wow, it’s been almost two weeks since Vancouver WordCamp 2012, the awesome one-day conference on all things WordPress. As last year, the event was divided into Design and Development tracks. And again as last year, I went back and forth between the two. Let’s face it, the line between design and development can pretty thin.

Calm and Simple Code With Purpose

Jeremy Felt from 10up.com gave the audience some pointers on calm, effective and mindful coding. Rushed code means bugs, and you may think you’ll go back and fix them later but there’s always another deadline! Better to do it right the first time. Invest the time to perfect your craft. Dig into the Codex*, read the code, understand how things work and why they work the way they do.

As well, developers need to know what tools are available, when to use them, and when not to. Libraries like jQuery are already there, no need to add it in your plugins! Use caching when you must.**

Finally, we need to be mindful of our audience: developers in our team, or even ourselves six months down the line. Document your code, make it readable, whether you’re solo or part of a team. And if you’re working solo, get involved in community projects!***

*And don’t complain if it’s crap. You’re totally free to improve things!

**Memo to myself: read up on the WordPress Transient API, because I have absolutely no experience in it.

***I totally need to do that.

Documentation

John James Jacoby of Automattic came to talk about PHPDoc, a PHP documentation standard similar to JavaDoc. Documentation standards like that are about not wasting time and brainpower. It’s about (his words) not being an asshole, and not taking time away from other people or even your future self. Because you’ll be able to quickly get to what a particular bit of code is doing and why.*

JJJ also repeated Jeremy’s advice to get on the Codex and improve it if you’ve got something to say. It’s a great place to learn, because wordpress.org has lots of caretakers.

*The why is important. It’s easy to describe what is happening but why is the more interesting question.

S2Members—a membership plugin for WP

Rayhan Abdulmughnee of the Small Business Centre spoke about a S2Members. It was fairly narrow in its focus, which was a bit of a disappointment. Then again, I knew what I was getting into. The main reason I attended this presentation instead of one on a command-line-interface for WordPress, was that I was possibly about to start a WP project heavily dealing with user roles, and I thought this might give me some good ideas. I’m not sure if it did. That project ended up not happening, which was also a bit disappointing; I’ve never dealt with WordPress user management except in the most basic sense. Drupal, sure, I know it forward and back, but I would have liked a chance to dig into it on the WordPress side. Someday soon, I’m sure.

JQuery mistakes and how to avoid them

Back to the development track after lunch, to learn all about jQuery from Automattic’s Andy Peatling. This was an very intense presentation, dishing out all sorts of jQuery tips and tricks which I won’t list here (and honestly, some of which went over my head).

Caching in WordPress: Invalidation schemes

Oh, but the fun doesn’t stop there! Zack Tollman was up to tell us all about caching in WP, and schemes to refresh that cache when it gets obsolete. Cache versioning, transients, and again a lot of this was totally new to me.

How to make your WordPress site mobile-friendly

David Zille started out by giving some general tips on what a mobile theme needs: fast loading, visibility of the important elements, ease of navigation, and accessibility. Then he laid out various schemes to make your site mobile friendly:

  • a third-party service
  • a responsive theme
  • a separate mobile theme

Responsive themes (which I already have some experience in) use CSS and JavaScript behind the scenes, but the downside is that you’re serving your entire content to a phone. Plus, they can be difficult to maintain and build from scratch.

Separate mobile themes (which may come with plugins) avoid most of these pitfalls, but probably have issues of their own. It all comes down to your budget, skill sets, etc…

Food for thought, definitely.

The WordPress community

Vancouver’s own Christine Rondeau wrapped up the day to tell us about the WordPress community. And it’s real: it’s in the meetups and in the forums and the blogs and on IRC, and in events like this one. You participate to learn, to get referrals, make friends and say thanks. You know, Christine’s talk was another kick in the pants for me to get more involved. More than just going to meetups (which I do), I need to actually contribute something. There’s a theme I’ve been hacking away at on and off (based on my current blog theme, actually) I need to polish it up and submit it.

Oh, and I won a Code Poet t-shirt!

There was an afterparty, but I already had plans to ogle hot athletes in underwear at Celebrities, so I had to give that a miss.

Programmatically attaching image files to nodes in Drupal 7

I found the answer on Stackoverflow.

Simple, right? And this works fine if you’re attaching a brand new image.

I found the answer on Stackoverflow

I found the answer on Stackoverflow.

Simple, right? And this works fine if you’re attaching a brand new image. However, if you’re updating an image you’ll find that the styles don’t update after calling node_save(), and the image will not show up correctly on your site. You need one extra step: call image_path_flush() to regenerate that image’s styles before calling node_save().

//if the image is being updated, flush all its styles
image_path_flush($node->field_image['und'][0]->uri);

Freelance Camp 2012

I attended my second Freelance Camp this weekend. I won’t try to summarise the excellent talks, because I’m still digesting all the nuggets of wisdom and working to put them in practice. I will say that I met some amazing folks who are doing amazing things, and I feel more energised than ever about my freelancing career.

I attended my second Freelance Camp this weekend. I won’t try to summarise the excellent talks, because I’m still digesting all the nuggets of wisdom and pondering all the great tools I learned about and working to put it all in practice. I will say that I met some amazing folks who are doing amazing things, and I feel more energised than ever about my freelancing career.

And of course, since I pretty much never come down to New West except for FLC, I snapped a few photos around the quay.

The world's largest tin soldier

Three Bridges

And a cute photo of a sparrow I took the day before. Such a pretty little thing!

Sparrow in the morning

Ubercart 3: Programmatically submitting an order from Canada

I’ve been working on a project that, among other things, involves purchasing a particular item with one click: the order is created, payment information is added (how it’s stored is not important here) and the order is submitted, all automatically.

I’ve been working on a project that, among other things, involves purchasing a particular item with one click: the order is created, payment information is added (how it’s stored is not important here) and the order is submitted, all automatically. After a bit of flailing about on my own, I found this post on the Ubercart forums explaining how it’s done, and it totally saved my bacon. In short:

  1. add item to cart using uc_cart_add_item()
  2. populate and submit form ‘uc_cart_checkout_form’
  3. if things are okay, populate and submit form ‘uc_cart_checkout_review_form’ (which actually submits the order)

However, it’s not quite complete. 3 things are missing, in fact, which took me a bit of experimentation to figure out:

1) You need to enter the credit card info in the form_state array, not just in $_POST

The post says to do this:

// Define the credit card information in the $_POST directly.
  // See uc_payment_method_credit($op = 'cart-process') for why this is necessary.
 

$_POST['cc_number']    = 'XXXXXXXXXXXXXXXX';
  $_POST['cc_exp_month'] = 'XX';
  $_POST['cc_exp_year']  = 'XXXX';
  $_POST['cc_cvv']       = 'XXX';

But that didn’t work for me. It looks like you also need to enter it in the form_state, like so

$uc_cart_checkout_form_state['values']['panes']['payment']['details']['cc_number'] = 'XXXXXXXXXXXXXXXX';
	$uc_cart_checkout_form_state['values']['panes']['payment']['details']['cc_exp_month'] = 'XX';
	$uc_cart_checkout_form_state['values']['panes']['payment']['details']['cc_exp_year'] = 'XXXX';
	$uc_cart_checkout_form_state['values']['panes']['payment']['details']['cc_cvv'] = 'XXX';

2) Entering an address not in the store default country

(This post title says “Canada” because the default default store country is the US and that’s what I was testing with.)

Here’s the problem: if you try to enter a Canadian province in the $uc_cart_checkout_form_state['values']['panes']['billing']['billing_zone'] field, the ‘uc_cart_checkout_form’ form submission will fail with the following error message:

An illegal choice has been detected. Please contact the site administrator

Why? Because when the form is built, the allowed Zone values are based on the selected country. If all you can select are US States but you enter “BC” anyway, Drupal will not accept it, and that’s what the error message means.

Here’s the solution: the billing / shipping address panes are built based on the order country, and by default uc_order_new() creates an order with the billing and shipping countries set to the store default. So, all you need to do is set that field to a different value:

//after $order = uc_order_new()
$order->billing_country = 124; // Canada, or same value entered in $uc_cart_checkout_form_state['values']['panes']['billing']['billing_country']
//do the same for shipping country

This will populate the dropdown with Canadian provinces, and allow you to enter a province in $uc_cart_checkout_form_state['values']['panes']['billing']['billing_zone']

3) If you’re not starting from the cart, you need to change the redirection checks

The code checks if drupal_form_submit('uc_cart_checkout_form', $uc_cart_checkout_form_state) finished correctly like this:

if ($uc_cart_checkout_form_state['redirect'] == 'cart/checkout/review') {
    // We're good to move forward!!

And similarly for drupal_form_submit('uc_cart_checkout_review_form', $uc_cart_checkout_review_form_state)

Function uc_cart_checkout_form_submit($form, &$form_state) (defined in uc_cart/uc_cart.pages.inc) sets the form_state redirect:

function uc_cart_checkout_form_submit($form, &$form_state) {
  if ($form_state['checkout_valid'] === FALSE) {
    $url = $form_state['storage']['base_path'] . '/checkout';
  }
  else {
    $url = $form_state['storage']['base_path'] . '/checkout/review';
    $_SESSION['uc_checkout'][$form_state['storage']['order']->order_id]['do_review'] = TRUE;
  }

  unset($form_state['checkout_valid']);

  $form_state['redirect'] = $url;
}

If you’re starting from the cart, then $form_state['storage']['base_path'] will be equal to ‘cart’. But if your goal is a 1-click purchase, chances are you’ll be starting on a completely different page, and the redirect will be different as well. So you’ve got a couple of options:

  • Change $form_state['storage']['base_path'] somehow (is that possible?)
  • If you know the path of the page you started on, use it in the check:
    if ($uc_cart_checkout_form_state['redirect'] == 'yourpath/checkout/review') {
        // We're good to move forward!!
    
  • Be a little more flexible, and only check the last part:
    if (strpos($uc_cart_checkout_form_state['redirect'],'checkout/review') !== FALSE) {
        // We're good to move forward!!
    

Northern Voice 2012, Part 4: And The Rest

Last but not least, a bunch of talks that didn’t easily fit together:

Last but not least, a bunch of talks that didn’t easily fit together:

On Friday Martha Rans of Artists Legal Outreach gave us a brief overview of copyright law in Canada, the why and the how. I learned a few interesting things, such as that you can copyright lighting techniques in photography. Subjects like the Eiffel Tower can’t be copyrighted, but composition and lighting can—in Martha’s words, copyright is not about ideas, it’s about expression of ideas.

And there’s the basics, which still bear repeating: the Web is not public domain. You don’t get to use stuff without attribution or permission. And money is not the issue. Most artists and creators would be perfectly happy with a “This is great! Can I use it if I attribute to you / link back / whatever?” Likewise, creators need to make it easy for people to do this. A “If you like my work, get in touch with me!” message on your blog may prevent people from just lifting your stuff.

This was followed by Jon Newton talking about the defamation case against his old site, p2pnet.net, about which more here. It wasn’t a long talk; Newton isn’t a public speaker, and the merits of the decision were so blindingly self-evident that there wasn’t much point to a Q&A period.

Next, Photocamp! John Biehler gave a little demonstration of light painting (well, not an actual demonstration, though he did have the gizmo in question with him).

Ariane Colebrander gave us some tips on accessories: not lenses or tripods or such, but the bags and packs that you lug it all around in.

Morten Rand-Hendriksen taught us (1) how to shake hands like the Vikings of old, and (2) a few techniques to efficiently blog your photos and publicize them on social networks. He demoed a cool plugin (whose name I forget) that allows you to post your photos on Facebook at the same time as you’re posting them to your blog. Choose the featured image for your post, and it’ll show in the preview in your timeline. You can tag your friends or other pages. Probably lots of other nifty features. This wasn’t directly useful to me since I post my photos on Flickr. Still, a little more SEO wouldn’t hurt…

Syx Langemann gave us a brief tutorial on portrait photography: how to watch out for visual noise, how to use lighting, and most of all that you should respect your subject. “We owe it to the person in front of the camera to create a beautiful & powerful photo.” The story of his great-uncle was especially moving and memorable.

And I don’t remember if it was Morten or Syx who gave us the addresses of a couple of photography blogs. Nevertheless, here they are:

Vivian Meier, a stupendously talented photographer who never showed her work to anyone and only became famous after her death.

yowayowa camera, the blog of a Japanese girl who does “levitation” photography. It’s strange, a little eerie, and absolutely brilliant.

Kemp Edmonds talked to us about lifelong learning. This is about the point that my laptop died, but fortunately I jotted down a few notes on my phone. Very incomplete, but better than nothing, especially since the link I have to his presentation doesn’t seem to work.

Anyway: the key to self-directed lifelong learning is in 6 steps:

  1. Decide what you wat to learn (it has to be something you’ll be passionate about)
  2. Discover your tools: podcasts, videos, lynda.com, Google Scholar, TED, were some of the ideas thrown out by the audience. I loved that Kemp actively encouraged audience participation; in fact, near the beginning of his talk he said something something about looking forward to learning from us. Great attitude!
  3. Find, filter and evaluate all those tools
  4. Who will you learn from? (My notes here mention “the hierarchy of contagiousness”)
  5. Select your method of experimentation. For example, to be a better photographer, post to Flickr and solicit feedback. For me, that would be blogging to hone my voice, and develop themes and plugins to share
  6. Who will you teach? Everybody knows one of the best ways to learn is to teach!

Quote of the day: “You don’t have to know everything, you just have to know that you don’t know everything.”

So, there you go, that was Northern Voice 2012. The quality of speakers was top-notch, I had a great time and learned a lot! Can’t wait for next year!

Northern Voice 2012, Part 3: Voices, Brands and Authenticity

Steffani Cameron dealt with writer’s block for six years ending when a head injury forced her to write to keep her brain active. She was here to tell us about Ripping the Bandaid Off and other tips to find your voice.

Steffani Cameron dealt with writer’s block for six years ending when a head injury forced her to write to keep her brain active. She was here to tell us about Ripping the Bandaid Off and other tips to find your voice. One tool to get your brain started in the morning is writing about what you’re having for breakfast. Or, the “ideas box” where you store your ideas and revisit them when you have the time.

But really, there’s no magic formula. You don’t just sit down and get good, you need to write something every day. But what you shouldn’t do is publish something every day! Be relevant, be researched, be interesting.

It’s a constant struggle, but if you want to get personal, you rip that fucking bandaid off and you keep ripping and digging. Hey, that’s what Shane said too, so you know it’s good advice!

Quote of the day: “The hardest thing in life is to be yourself.”

Getting personal can be hard for other reasons, as Georgia Gaden Jones explains Are you for real? Struggling with blogger authenticity in a time of personal brands and monetization. Georgia is not a blogger herself, though she is an avid reader of blogs and interested in the blogging experience from an academic standpoint. In most academic circles, using your personal voice is frowned upon, though it seems blogging is more and more being seen as inherently collaborative and empowering, especially in feminist academia. As well, until recently, employers were twitchy about bloggers, due to all the (potential) airing companies’ dirty laundry and hanging out with the nerds in IT.

As for authenticity, the real key is independence. Readers have to know that a blogger is speaking for themselves and not their department or manager, or sponsors. According to one focus group Georgia mentioned, the suspicion of commercialisation and selling out is a big worry. Are you upfront about the freebies you receive? Are your product reviews honest or are you being nice for fear of not getting more free stuff? Are you doing product product placement when you shouldn’t be?

More generally, there’s the question of how your personal voice fits with your personal “brand”. A brand needs consistency to be authentic, but people are not consistent. People are messy and self-contradictory sometimes. On the one hand, you don’t want to reveal every single sordid detail of your life. But on the other hand, you can’t lie by omission. And on the third hand, what if your brand has taken control of your blogging life? Georgia mentioned a rep from Mom Central Canada, an outfit that seems to match “mom bloggers” with products to hawk. The catch is that blogger’s brand has to fit with the product’s brand. And once you’re matched, you must apparently “ensure your brand does not conflict with ads on your blog”. Which raises the question: are bloggers just “brands” now, to be matched with other brands? And another question: who really controls the content on your blog, you or your sponsors?

Where’s the authenticity then? Or can we think of authenticity as a commodity, a quality you need for (commercial) success? By creating careful descriptions of a flawed individual that still fits with commercial values?

Troubling questions, for sure, and Georgia is right to be concerned. This isn’t the first time we’ve addressed them at Northern Voice, though. Just last year Morten Rand-Hendriksen discussed his Code of Ethics, which is very journalism-focused—with its emphasis on trustworthiness, separating opinion from fact, and being mindful of your sources—but really applies to any kind of content creation. And let’s be clear, making money—even making a living—from blogging is not necessarily a bad thing, as long as you’re upfront about it.

Quote of the day #2 (I couldn’t find anywhere else to put it): Blogging is not just an extension of yourself, but a construction of yourself, through your connections and your interests.

Northern Voice 2012, Part 2: In Brightest Day, In Blackest Night

Part 2 of my NV12 recaps: productivity, voice, and comics

Mike Vardy‘s talk on Saturday dealt with Better Blogging Productivity. He offered some commonsense tips such as:

  • Be realistic (or in his words, “get real!”): get clear about what you can and can’t do in the windows of time available to you. If you only have a little bit of time, do simple things like catch up on email or collect ideas. Save the really creative work for when you can focus on it
  • Build a schedule. In Mike’s words, blog proficiently not prolifically. Start small, get used to a blogging routine, and build up from there.
  • Avoid distractions (as opposed to disruptions). Distractions are messages, email notifications, anything nonurgent and avoidable.

Commonsense, sure, but this is stuff I definitely need to work on. I don’t have a blogging routine, and as often as not I’ll check my email when that little red circle appears over the icon. Hey, at least I turned off the sound notifications!

Then Mike offered a number of tools to help with this productivity: tasks managers like 30/30, email filters like AwayFind, forced discipline apps like Freedom (on the Mac).

But the kicker to me was when he said, “discipline is not enough. You need willpower.” Mike told the audience that he wears a Green Lantern ring when blogging as a physical focus. Green Lanterns, as everyone knows, are powered by will. And who is Green Lantern’s arch-nemesis, he asked? “Sinestro,” I replied from the front row. And what does Sinestro run on? “Fear,” I replied again, thus outing myself as a big nerd. Bottom line, then: fear impedes willpower.

And you know what? I totally get it. My take on the discipline vs. willpower dichotomy is that the former is going through the motions, tools and habits that you need to internalise until they’re second nature. Willpower, on the other hand, is the clarity of hearing that little voice pushing you to create and excel. Fears, doubts and insecurities definitely get in the way of hearing that voice.

(Incidentally, Mike and I chatted over lunch for a bit, and I learned about the Green Lantern animated series. I watched the entire first season the day after the conference, and I’m here to tell you it’s awesome. I didn’t think I’d be crazy about the CGI animation, but the technology’s come a long way, and the story, characters and action are all fantastic. Any series that stars Atrocitus, Mogo and Saint Walker is tops in my book.)

After lunch, Shane Birley‘s keynote The Evolution of the Blogger’s Voice took us on a whirlwind sci-fi trip through his blogging history. There was no real plot, just a collection of vignettes from 1998 to the present day: his time in Victoria, meeting Allyson, getting laid off from Cayenta, starting Left Right Minds, and the million other projects he’s currently got going.

Some of his posts (especially the early ones) were about looking for vindication, feeling grumpy, feeling tied down, and looking for his voice. And then his voice came, though sometimes it didn’t feel that way. The moral is: you already have a voice, you just have to find it. It may not be through plain text blogs. Try podcasts, vlogs? Keep digging, and you’ll find it.

And here’s what I’m taking from this talk. I’m not sure if this was really Shane’s point, but here goes, my interpretation:

The thing is, discipline will keep your world ordered, and willpower will keep you putting one foot in front of the other, but you need to see where you’re going, or at least hope that the tied-down-ness and the grumpiness will pass, and you will find your voice one day. All will be well.

My personal view is that Fear has many opposites, not just Willpower. Another is Hope. That’s in the comics too, by the way. Blue Lanterns (powered by hope) by themselves are apparently the weakest of the emotional spectrum (I guess reflecting the fact that hope alone is passive and kind of useless). But team them up with a Green Lantern and they boost each other’s power so as to be nigh-unstoppable. Hope and Willpower together are the greatest force in the universe.

Northern Voice 2012, Part 1: The Future And How To Get There

Northern Voice, the blogging and social media conference which I’ve been attending for two years running, happened again. This time in June instead of May, and at SFU Woodward’s instead of UBC. It’s a great venue, and suited me better, commute-wise.

I had an amazing time again this year, and of course I’m going to recap the hell out of it. Some of the talks complemented each other nicely, so I’ve decided to cover them together. Let’s start with the two morning keynotes:

Reilly Yeo of Open Media kicked the conference off on Friday with her keynote Using the Internet to Save the Internet. From Slacktivism to Interactivism. Open Media has led a number of campaigns, including Stopthemeter.ca, fighting the push by telecom companies to implement metered net use. That petition got over 500,000 signatures, made national news, and the decision-makers responded. More recently, their campaign to stop Bill C-30, the online spying bill made more national news, exposed yet again the raving paranoia of the Harper government in general and Safety Minister Vic Toews in particular. Again, the government blinked.

The moral of these stories? Online petitions do work! Online activism can make a difference! The term “slacktivism” is easy to throw around; and signing online petitions is just about the least you can do to call yourself an activist, but there’s a lot more going on than that. First, half a million “slacktivists” can’t be dismissed so easily.

Second, don’t knock petitions. Darren Barefoot said so way back in Northern Voice 2010: there are many ways to do good online, simple and complex, and it’s important to have a low barrier of entry to do-gooding.

Third, they (well, some, at least) are not just putting in a token ten seconds of effort, they’re getting informed, getting connected with like-minded people, and coming up with hilarious memes. The decision-making process is suddenly a little more human, a little closer to home. Netizens move away from passive consumption of lolcats and Justin Bieber, and towards responsible, mindful involvement.

Not that there’s anything wrong with lolcats, of course. Lolcats are awesome. But lols mixed with politics? Well, that’s best of all.

Second moral, BTW: the Harper government, for all its majority, isn’t quite the juggernaut it would like to be.

So maybe, Yeo argues, “slacktivism” isn’t the right term after all. She suggests “interactivism”: a new kind of activism, highly connected and savvy, with massive potential, and open to anyone.

But what is interactivism saving the internet for, though? Let’s ask Blaine Cook. In his Saturday keynote, The Wild Future (not to be confused with The Future is Wild, which I have on DVD and is totally awesome), Cook argues for the preservation of a “wild” internet, a net free to evolve organically, where difference is a good thing, multiple cultures can arise, coexist and enrich each other.

Let’s talk about Babel for a moment. Cook introduced it as a metaphor for the frustration we feel that we can’t accomplish the things we want, because we can’t work on things together. That’s one interpretation I’ve never heard before! And it’s true, we get more done when we work together. But when we work as one, we get the same things done, over and over. We put up the same towers, over and over. But one size does not fit all.

Case in point: UBC’s Buchanan Building is a fine example of Brutalist architecture, apparently modeled on a building in San Diego. The windows in that building relied on being set deep enough that direct sunlight wasn’t a problem. Problem is, they transplanted the exact same design 2,000 km north, where the sun is much lower in the sky, and apparently the building is an oven.

Brutalism’s been around for a long time. Many cities have a few examples, as office buildings or low-income housing, like the UK housing estates. Some worked, some became slums and got torn down. The lesson is: attempting to design urban utopias with a single, narrow vision leads to monocultures. “Machines for living in” don’t inspire community or organic cultural growth.

Seguing into the online world, Blaine drew a parallel between, on one hand, Brutalist architecture and on the other, the iPhone and social networks like Facebook. The iPhone, you say? (or at least, I said) This pretty, pretty thing with all the wonderful software, how is it anything like those giant ugly-ass buildings? Well, it’s controlled from the top down by a single corporation, and has built-in pesticides to limit the diversity of its software ecosystem. By contrast, the Android system is a much wilder place. Facebook likewise is pretty bland, omnipresent, and controlled by a corporation who calls the shots on your privacy.

Mind you, Facebook did have Cow Clicker, so it wasn’t all bad.

And let’s face it, sometimes you want the bland and the safe. It’s a push-and-pull thing, I guess. Humans settle, we make the wild places not-wild. For comfort, for support, for community. That’s not a bad thing. Not everybody can be a pioneer. But we need to be able to fork cultures, we need the space to create new spaces and ways to express ourselves, and this is something the Web enables like nothing else. As long as it’s not bled dry by big telecoms, strangled or spied on by a paranoid government, censored by churches, or turned into bland consumer networks by greedy corporations.

That is our wild future. The future of collaborative writing using Git, of open source software like Drupal, Firefox and Linux, of a hundred phone OS’s and Pinterest clones, of freely shared knowledge thanks to Wikipedia and others.

The world is so malleable, and we get to find the answers together by building them.

db_query() and the IN() operator

A little while ago I was porting a Drupal 6 module to Drupal 7, which meant changing over a lot of queries. The new database API had oodles of new features and somewhat different rules, and I wanted to do things by the book.

Haven’t done a Drupal post in a while!

A little while ago I was porting a Drupal 6 module to Drupal 7, which meant changing over a lot of queries. The new database API had oodles of new features and somewhat different rules, and I wanted to do things by the book. Now, I thought I could leave the simpler queries to be static (ie: using db_query()) instead of dynamic (using db_select()) since db_select() apparently creates a lot of overhead… but a few just wouldn’t work. They were the ones using the IN() operator.

Here’s what my original code looked like:

$res = db_query('SELECT field FROM {table} WHERE cond_field in(@values)',array('@values' => implode(',',$array_of_ints));

My first stab in Drupal 7 was simply to replace the ‘@’ with a ‘:’

$res = db_query('SELECT field FROM {table} WHERE cond_field in(:values)',array(':values' => implode(',',$array_of_ints));

Didn’t work. There was no error, but the query didn’t return any rows. However, it did work when I plunked the imploded array right in the query string, like so:

$res = db_query('SELECT field FROM {table} WHERE cond_field in(' . implode(',',$array_of_ints) . ')');

Not pretty. Not clean. There had to be a better way, but what was the problem? And then it hit me: in Drupal 7 you don’t need to add single quotes around placeholders in the query, even if they represent strings, the API does all that for you if the value isn’t a number. So what was happening was that the value of the IN() clause was taken as one big string, which just happened to consist of comma-separated numbers.

What to do about it? I had to use a dynamic query:

$res = db_select('table')
  ->fields('table',array('field'))
  ->condition('cond_field',$array_of_ints,'IN')
  ->execute();

So there you go. It’s more involved, for sure, and note that the condition takes an array instead of a string, but it works. And it was a good introduction to dynamic queries, which used to scare me a little but now totally don’t. I’ve done far more complicated ones, with merges and subqueries and all sorts of crap, and db_select() can handle it all.

Magento: Adding custom attributes to orders, Part II

In hindsight I probably should have tested the method I blogged about recently, just to make sure it works.

Because it doesn’t.

In hindsight I probably should have tested the method I blogged about recently, just to make sure it works.

Because it doesn’t.

Oh, the EAV attribute is created all right. But it’s useless, because as I learned since then, orders do not read from the EAV tables since Magento 1.4 (released end of 2010, maybe). They use a flat table ({sales_flat_order}) along with a bunch of other flat tables (order items, quotes, invoices…).

What to do? There are a couple of options. I could add a field to that flat table. Easy to do with an install script, something like:

$installer->run("ALTER TABLE ADD my_custom_field VARCHAR(500);");

Problem is, according to one poster on Stack Overflow, that’s probably not upgrade safe. Plan B would be to create a separate table, keyed on Order ID. Easy enough to do, and my first plan was to write the to the custom as the info is copied from the quote to the order, in Mage_Sales_Model_Convert_Quote::toOrder().

But that doesn’t look possible, because the Order ID isn’t set yet. Seems crazy, I know, but I tried to read

$order->getIncrementId() //I know that one's set
$order->getId() //Nope
$order->getOrderId() //Not that either
$order->getEntityId() //Because the order table's primary key field is entity_id

So I could use increment_id (not exactly sure what that field is good for, except for displaying to customers)… but then I decided to just key the custom table on quote_id. No need to worry about writing to the order, I just extend the order model like so:

class Npd_Myextension_Model_Sales_Order extends Mage_Sales_Model_Order
{
    public function getCustomField() {
    	$quote = Mage::getSingleton('sales/quote');
	$quote->load($this->getQuoteId());
   	return $quote->getCustomField();
    }
}

Which works, because orders always keep a reference to their source quote. Likewise, invoices keep a reference to their source order.

So there you go, and I’m making progress. Progress against a massive headwind, mind you. Again, I whine: why the hell is Magento making things so hard for developers?

PS: about the order ID, am I just kind of dim, or is it actually not set at that point? If it is, what getter function should my code be using? The fact that I’m even asking “what getter function should I be using?” shows either Magento or myself needs serious help…