• Use Arrays in HTML Form Variables

    Nov 3 2008

    When you're dealing with processing forms, a lot of the time you have a one-to-one mapping of form fields and database columns, with perhaps an extra submit button or some fields that need special processing (eg. passwords).

    Although many frameworks like CodeIgniter make this easier, you can still easily come up with code like this:

    $this->db->insert('accounts', array(
        'first_name' => $this->input->post('first_name'),
        'last_name' => $this->input->post('last_name'),
        'email' => $this->input->post('email'),
        'address1' => $this->input->post('address1'),
        'address2' => $this->input->post('address2'),
        'city' => $this->input->post('city'),
        'state' => $this->input->post('state'),
        'zip' => $this->input->post('zip'),
        'phone' => $this->input->post('phone'),
        'fax' => $this->input->post('fax')
    ));
    

    See all that repetition? Whenever you see a group of lines that look almost the same, you know there is probably an opportunity to clean things up. Well luckily, there's a really neat one.

    You can create arrays in form fields using square brackets. That means you can name fields like account[first_name] and account[last_name] and in most server-side languages, you will end up with an 'account' array.

    In HTML, PHP and CodeIgniter, that might look something like this:

    <input type="text" name="account[first_name]"/>
    <input type="text" name="account[last_name]"/>
    <!-- etc... -->
    <input type="text" name="account[fax]"/>
    <input type="submit" name="submit"/> <!-- note the lack of 'account' -->
    
    // meanwhile, on the server...
    $account = $this->input->post('account');
    
    // VERY IMPORTANT: unset any fields that shouldn't be edited
    unset($account['id']);
    
    $this->db->insert('accounts', $account);
    

    See? Much cleaner. Yes, you do open a slight security hole potential, so be very careful when doing this on tables that have security implications, ie. user data. If you have an 'admin' column on your 'users' table, someone could maliciously add <input type="hidden" name="users[admin]" value="1"/> to your form using Firebug and grant themselves administration access. You can solve this by adding something like unset($user['admin']); to the incoming data. If you wanted to be really safe, you could have an array of the keys you want to allow and filter against that using something like PHP's array_intersect_key with array_flip:

    $user = $this->input->post('user');
    
    // only allow keys in $user to match the values in $columns
    $columns = array('first_name', 'last_name', /* etc.. */ );
    $user = array_intersect_key($user, array_flip($columns)));
    

    You can even do this with checkboxes and multiple select boxes, and alternatively leave out the key in the array to create a regular array (ie. not associative) of values:

    <label><input type="checkbox" name="choice[]" value="1"/> 1</label>
    <label><input type="checkbox" name="choice[]" value="2"/> 2</label>
    <!-- etc... -->
    
    // meanwhile, on the server...
    $choice = $this->input->post('choice');
    
    print_r($choice); // Array ( [0] => 1 [1] => 2 )
    

    This "trick" can really clean your code up. I used it recently to drastically simplify a form that had a shipping address and billing address. If the user checked a box saying "My shipping and billing are the same", I was able to simply do something like this:

    $shipping = $_POST['shipping'];
    $shipping_billing_same = $_POST['shipping_billing_same'];
    
    if ($shipping_billing_same) {
        $billing = $shipping;
    } else {
        $billing = $_POST['billing'];
    }
    

    Much nicer than that 24 form fields that were hard-coded previously.

    I've given examples here in PHP and CodeIgniter. Does anyone else want to give examples in other server-side languages and frameworks?

  • 5 Reasons Freelancers Can Succeed in a Shrinking Economy

    Oct 24 2008

    Like many people, I've been a bit obsessed about the economy lately. I'm wasn't sure whether or not to be scared, and to be honest I still don't. But I did think of some reasons freelancing might be a safe place to be.

    1. You have a diversified clientele. Your clients can be anywhere in the world, and you have many of them. And if you're lucky, you have more than enough work to fill your time. No matter how bad the economy gets, there should still be some business available.
    2. You have very little overhead. For most freelancers, all you need to work is a laptop and the Internet, both of which you'd probably have even if you weren't freelancing. You probably pay $10/month for your web site hosting, but otherwise you don't have a reason to borrow money. The gears of the credit crunch don't touch your business.
    3. You can drop your prices whenever you want. If you find less people can afford what you're charging, you'll be able to adjust accordingly. If you have a job and they decide they can't afford you, then you get laid off.
    4. The Internet is the place to be for self-employed professionals. With the considerably low cost of having the Internet, I would assume that a lot more business will happen online as more people become self-employed and work from home. The number of people you can potentially connect with online feels infinite.
    5. Businesses who don't want employees might turn to freelancers. Who knows, maybe in uncertain times, more business will want to hire freelancers on a contract basis rather than dedicate to hiring an employee they don't know if they'll be able to keep.

    For those of you who don't freelance, I'm not suggesting you quit your job and start freelancing tomorrow. You'll have to decide that for yourself. If you want to start freelancing, I would suggest is to get the ball rolling on the side while you have a job. Get that website up and get some presence on the Internet. That way you'll have something to fall back on if you lose your job.

    So things don't look too bad for us freelancers. How about you? Have you noticed the shrinking economy having a direct effect on your business or job? What do you think we can expect?

  • Keeping a Live Eye on Logs

    Oct 22 2008

    In web development, you can get really used to getting good error messages. If you're coding in PHP, you come to rely on the web server telling you if a variable is undefined or a file is missing.

    Likewise, when you're debugging, sometimes the easiest sanity check is to output some text. You'll find me using echo "wtf?"; die; quite often when I'm trying to figure out why a block of code isn't being executed.

    But sometimes, even these rudimentary methods of developing aren't available to you. Maybe error messages are turned off on the web server you're stuck debugging. Or maybe you have a lot of Ajax requests flying around and are tired of peeking at the result of each request.

    Log files to the rescue. Nearly every framework and server has logging functionality. Apache usually logs every request, so you can see when images, static files, and other requests are made. CodeIgniter has several levels of logging, including DEBUG, ERROR and INFO. Whatever framework you use, or if you're using one you built yourself, you'll probably find some way of writing log messages to a file.

    And if you have a log file that's being updated, you have a way of watching things happen in real time. I'm not talking about opening up the log file every now and then and looking back through it, I'm talking about watching it being updated as it happens.

    Let's say you have a web server running Linux and are trying to debug something using CodeIgniter. You SSH into the web server, find the log file, and tail -f it. tail is a command which will dump the end of a file out for you. If you add the -f parameter, it will "follow" the file, printing out any new lines as they are added to the log file.

    $ cd thefutureoftheweb.com/system/logs
    $ tail -f log-2008-10-23.php
    

    If you're working locally on Windows, make sure you have Cygwin installed. (Cygwin gives you a Linux-style console in Windows so you can do awesome stuff like this.) If so, you should have or be able to use tail in the exact same way. Mac and Linux users should have tail installed already.

    Back at my old job, we used to keep console windows open using tail to watch the live web servers, especially after an update. This way we could see errors appearing to users live and could investigate and solve problems that would otherwise a) get buried in the logs, or b) go completely unnoticed.

    It can really help to get in the groove of having one or two terminal windows open tailing the logs of the servers you're currently working on. And then if you get the urge to write echo "wtf?"; die; you can instead write log_message('info', 'wtf?'); (or equivalent in your framework of choice).

    For further information, check out:

    Happy tailing!

  • Using PHP's empty() Instead of isset() and count()

    Oct 20 2008

    I often work with data arrays in PHP as a way to pass information around or store information in sessions. When you work with these, you can't always assume that all properties are defined. I had some conditional logic code in PHP that was only supposed to execute if an array contained any values:

    $data = array(
       'text' => array( 'hello', 'world' ),
       'numbers' => array( 43, 2, 55 )
    );
    
    if (count($data['text'])) {
       // do something with $data['text']
    }
    

    But then I was in a situation where $data['text'] may or may not be defined. So I was going to update my if statement like so:

    if (isset($data['text']) && count($data['text'])) {
       // do something
    }
    

    But that looks kind of messy. I don't really like isset() but it is a necessary evil to avoid "Undefined" errors. Or is it?

    if (!empty($data['text'])) {
       // do something
    }
    

    empty() to the rescue - it returns true if $data['text'] is undefined, or if it is an empty array, or if it is false or null or 0. So !empty() is what I'm really trying to determine, and it works great.

    For more info, see: empty() at PHP.net.

  • Testing Web Pages with Lynx

    Oct 19 2008

    If you're not familiar, Lynx is the most basic web browser, found on Unix and Linux servers. There are no photos, just pure text, links and forms.

    You're probably wondering why you would ever think about supporting a browser that's based in a console window. Does anyone actually browse the web from a bash shell?

    Basically, here's the benefit: if you know it works in Lynx, you know it works everywhere. Lynx doesn't have JavaScript or CSS available, and there are no images. It doesn't get more limited than that.

    And actually, a lot of the traffic to your site is viewing things in this HTML-only form. I'm talking about search-engine spiders, bots, and people stuck using text-only devices such as screen readers.

    So run through your site with Lynx now and then. You will be able to see at a glance if there is enough hidden or alternate text on the page to be useful to search engines and the blind. You'll also be able to ensure that forms and functionality are available to absolutely everyone, even people browsing under Bash!

    Update: I just discovered Seebot, a web app which lets you browse the web the same text-only way Lynx (and bots) do.

<< older posts newer posts >>