A CodeIgniter view does not run in the global scope

In a regular PHP file, you can grab the value of a variable from the global scope using the keyword GLOBAL. So for example if you want to use a variable inside your function, you can do something like this…

<?php
$TODAY = date('Y-m-d');
function getEvents()
{
    GLOBAL $TODAY;
    if ($TODAY > '2012-02-14')
    {
        //...
    }    
}
?>

I’m not saying you SHOULD write code this way, but there are times when this sort of option is cleaner than passing another parameter to your function, or faster than rewriting the existing code.

I tried to do this in a CodeIgniter view, which looks and behaves very much like a regular PHP file. But it wasn’t working. My variables (such as $TODAY, above) weren’t available inside my function, even after I used the GLOBAL keyword to grab them from the outer scope.

My mistake was thinking “… from the outer scope.” GLOBAL doesn’t pull variables from “outer” scopes, it only pulls variables from the top-level, global scope.

As it turns out, a CodeIgniter view doesn’t run in the global scope. It gets swallowed by the CodeIgniter engine. It is evaluated and run from within a CodeIgniter scope, which in turn runs within the global scope. (I haven’t actually traced how many layers there are between a view and the global scope — there could be more.)

The only option in this case is to pass the variable to the function as a parameter.

The scope of a CodeIgniter view file is not obvious, nor could I find it mentioned in the documentation. Hopefully this post will save someone else the trouble of tracing why the GLOBAL keyword doesn’t seem to be working in CodeIgniter.

And if you have dug even deeper than me and can draw a scope diagram for CodeIgniter, let me know!

Posted in Web programming | Tagged , , , , | Leave a comment

A sensible naming scheme for backup files

It’s important to back up a database regularly. But how do balance being thorough with being reasonable? If you save a full backup, every day, indefinitely, you will need more and more storage space. And really, do you care if you have to go back to the Tuesday backup from a year and a half ago, rather than the Thursday backup? No.

What you want is a lot of recent backups, and a few older backups, saved regularly.

My strategy is this:

  1. Make a backup every day
  2. Make a copy.
  3. Give the two copies the following names: “Wednesday.sql” and “February.sql” (or whatever the current day and month are). Always overwrite any file with the same name.

What results is a manageable list of only 19 backup files. I have 7 backups that are less than a week old, and I have a backup every month going back one year.

So far, the only backup I’ve ever needed was the most recent one. But I feel good that I’m making backups and keeping some history, without bloating my server with near-duplicates of files I will never read.

Posted in Uncategorized | Leave a comment

UTF-8 not working? Look for htmlentities.

I converted all my sites to UTF-8 and it was relatively painless. However, on one of my sites, I kept seeing legal UTF-8 characters turning into gibberish. It happened after entering UTF-8, submitting a form and then redisplaying the values in an edit box.

I know that all my pages are using UTF-8, and also that my database stores the text as UTF-8.

The thing that I overlooked is that, because I’m writing text to an input box, I’m using PHP’s htmlentities function to handle special characters, and the default character set used by that function is ISO-8859-1. I had to change my PHP command from

echo htmlentities($field);

to

echo htmlentities($field, ENT_COMPAT, 'UTF-8');

Once I verified that worked, I searched my whole codebase for htmlentities and made sure they were all using ‘UTF-8′

Posted in Character encoding, Debugging, Web programming | Leave a comment

HTML5 Application Cache always caches your home page

I built a mobile site for a client. One of the neat features is the ability to customize a secondary view of the home page.

When I went to add a cache manifest to the site (so that images, styles, and static pages could be viewed offline) I found that the application cache wouldn’t let go of the stored home page with its custom view, in spite of my having listed it in the online whitelist section of my cache manifest.

I think that this comment from the spec describes it:

“… in practice the page that referenced the manifest is automatically cached.”

It doesn’t explain why that is the case, but apparently it is. That tells me two things:

  1. Any customizations to the home page should be handled via AJAX, or better yet, be handled on a page other than the home page, and
  2. The manifest attribute of the HTML tag should probably only be included on the home page (or any other likely landing pages) — and not on every page of the site, as I had built it originally.
Posted in Uncategorized | Leave a comment

Print Avery labels using CSS and HTML

A client for whom I provide web services asked me if I could help her print barcode labels from their data.

Now, I’ve created Avery labels using Office, Illustrator, even Photoshop — but never using web technologies. You just don’t have a lot of control printing from your browser using CSS.

Or do you…? After all, we’ve always been able to specify real-world measurements such as “in” and “cm” using CSS.

I bought Avery 5160 labels because they seemed big enough to allow me to be a little sloppy while still providing many stickers per page.

A quick test proved that I could specify the page margins, label sizes, and gutter widths in inches. And both Firefox and IE allowed me to set the print margins to 0, leaving control of the layout to my CSS. Here’s what the print preview looks like from Firefox:

It’s not perfect, but it’s good enough.

Printing multiple pages turned out to be trickier. First, to prevent pages from breaking halfway across my labels, I inserted an empty div with the style rule “page-break-after” set to “always”.

Also, I had used the HTML body to set the margins. But the top of “page 2″ doesn’t know anything about the HTML body’s top margin. There is some documentation on “paged media” but it felt like uncharted territory. Rather than fight it, I decided to let the browser — rather than the CSS — set the top margin. I had to convey that in some friendly instructions on my client’s launch page:

Before printing labels, use your browser’s print preview options to set the top print margin to 1/2 inch and all other print margins to 0 (zero).

Try printing a test page on plain paper first. Hold it up to the light behind a sheet of labels to make sure the bar codes line up with the stickers.

It worked great in Firefox and Internet Explorer — good enough for my client.

Once the concept was proven, I built a controller page that lets my client print a test sheet, blocks of real data, individual data points, and even “blank” labels to push the data past previously peeled stickers so that nothing is wasted.

Here’s a one-page example of the HTML and CSS used to create Avery 5160 labels. (HTML corrected thanks to Halty.)

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>HTML & CSS Avery Labels (5160) by MM at Boulder Information Services</title>
    <link href="labels.css" rel="stylesheet" type="text/css" >
    <style>
    body {
        width: 8.5in;
        margin: 0in .1875in;
        }
    .label{
        /* Avery 5160 labels -- CSS and HTML by MM at Boulder Information Services */
        width: 2.025in; /* plus .6 inches from padding */
        height: .875in; /* plus .125 inches from padding */
        padding: .125in .3in 0;
        margin-right: .125in; /* the gutter */

        float: left;

        text-align: center;
        overflow: hidden;

        outline: 1px dotted; /* outline doesn't occupy space like border does */
        }
    .page-break  {
        clear: left;
        display:block;
        page-break-after:always;
        }
    </style>

</head>
<body>

<div class="label"><img src="http://boulderinformationservices.files.wordpress.com/2011/08/barcode_sample.png" /><br>Human readable</div>
<div class="label"><img src="http://boulderinformationservices.files.wordpress.com/2011/08/barcode_sample.png" /><br>Human readable</div>
<div class="label"><img src="http://boulderinformationservices.files.wordpress.com/2011/08/barcode_sample.png" /><br>Human readable</div>
<div class="label"><img src="http://boulderinformationservices.files.wordpress.com/2011/08/barcode_sample.png" /><br>Human readable</div>
<div class="label">(Repeat 30 times)</div>
<div class="page-break"></div>

</body>
</html>
Posted in Uncategorized | 5 Comments

A visual checksum for your PHP output

Refactoring the code on my billing system, I was promoting a method to its parent object. If I did it right, the output from the code wouldn’t be any different before and after the refactor.

Unfortunately, the output page was a large table of numbers, and it was difficult to detect a small change at a glance. If only there were some way to have the page spit out a checksum, I could quickly tell whether the refactor resulted in identical output.

SHA-1 is an encryption algorithm. It takes a string of any length as an input and returns a string of 20 hexadecimal characters. It’s easy to reduce a big HTML table full of numbers to a small string.

It was still a little difficult to tell the difference between, for example, the next two lines

a847a906c9955734217c348eaa5b3b38abab0bdf
15b8fdd026c607e0b51b2d5e51103a77bf103354

So I decided to take advantage of the fact that here was a nice long string of hex decimals. I grabbed the first 6 and the last 6 digits to create a colored box with a colored border. Now I could quickly glance at a big blob of color and tell whether anything had changed.

This difference is much easier to see:

15b8fdd026c607e0b51b2d5e51103a77bf103354
a847a906c9955734217c348eaa5b3b38abab0bdf

Here is the PHP function:

function getVisualChecksum($out)
{
 // from boulderinformationservices.wordpress.com
 $checksum = sha1($out);
 $checksumColor1 = substr($checksum, 0, 6);
 $checksumColor2 = substr($checksum, -6, 6);
 return sprintf(
  '<span style="background-color: #%s; border: 4px solid #%s">%s</span>',
  $checksumColor1,
  $checksumColor2,
  $checksum
 );
}
Posted in Debugging, Refactoring, Web programming | Leave a comment

Share Eclipse snippets among workspaces, or even different computers

I use Eclipse as my editor of choice. I also use multiple Workspaces (see File > Switch Workspace). I also use Snippets for common code templates.

I created some useful snippets in one workspace that I wanted to be able to use in another. Eclipse doesn’t provide an easy way to share snippets across workspaces. Using Eclipse, you would have to copy the snippet, switch workspaces (which requires restarting the program), and then paste it… for each snippet you want to reuse. And that’s awful.

Phase 1: Copy the XML nodes

One way to copy a bunch of snippets across workspaces is to merge the various snippet XML files into a master file. Your snippets are stored in

C:\Users\YOURNAME\AppData\Roaming\Eclipse\workspace-YOUR_WS_NAME\.metadata\.plugins\org.eclipse.wst.common.snippets\user.xml

I was able to use WinMerge to compare my new snippets file with my older one. It was easy to use WinMerge’s Copy Left command to push just the new lines into my older file, and then save the merged master. Restarting Eclipse with the new master file confirmed that I successfully copied the snippets.

But wait a minute…. My snippets files are in sync, but there is nothing to prevent them from drifting out of sync again.

Hard links to the rescue.

Phase 2: Make a hard link

A hard link is a pointer. It looks like a file, but it doesn’t have any contents, it has a reference to another file, somewhere else on the file system. I can create a hard link called “user.xml” in each of my workspaces that points to a single, XML master file.

I saved my merged master XML file to a location outside of the Eclipse folder tree. Then I backed up my individual user.xml files by renaming them. Then I created the hard links.

To create a hard link,

  1. Open a command prompt.  You may have to open the command prompt as an administrator (on Windows 7, right-click the link to command prompt and choose “Run as administrator”).
  2. Change directories into your workspace/(etc.)/org.eclipse.wst.common.snippets/ folder.
  3. Make the link like so:
mklink /H user.xml "C:\path\to\your\master\user.xml"

… and repeat steps 2 and 3 for each of your workspaces. Easy!

To carry the idea a step further, I decided to put my real master XML file in a folder that is shared via LiveMesh (you could do the same thing with Dropbox or a network drive). That way, I can sync my snippets between my laptop and my desktop computer.

Posted in Uncategorized | Leave a comment