SnippetsEmu allows you to create TextMate-style snippets in Vim which, together with Vim’s native code-completion feature, makes Vim a top choice among lightweight text editors. When I installed Snippy (as its creator, ironically, likes to call it), I had one problem: SnippetsEmu maps its functionality to the key, which is what I map code completion to. Thus, my mapping was causing Snippy not to work. As I was not about to oppose years of bash-trained muscle memory by mapping completion to a different key, I decided to bite the bullet (that hurts, by the way) and try to edit the plugin’s vim script. It turned out to be a very easy edit. Apparently the saints were smiling on me – or, at least, the patron saint of Not Having to Learn Vim Scripting.

Note that if you are using the SuperTab script, support is built into SnippetsEmu. The following is for everyone not using that script who wants to map the tab key.

Open snippetsEmu.vim and find the function s:ReturnKey. In my version, it’s on line 627. This function gets called when no snippet is found; all it does is output the tab character (or whatever key the snippets are mapped to). We want this function to output Control-P instead, since that is Vim’s native code-completion trigger. Find the line in s:ReturnKey that looks like this:

exe "return \"".substitute(g:snippetsEmu_key, '^<', "\\\\<","")."\""

This line might have been changed in your version, so just find the line that seems to do the same thing – output g:snippetsEmu_key. Replace that line with this:

return "\<c-p>"

That’s it! If that doesn’t work, all I know to do is pray. I suggest you pray to the patron saint of Damnit I Have to Learn Vim Scripting.

Through Flash’s FileReference and FileReferenceList classes, you can create a powerful file uploader that allows the user to upload multiple files with a single form element. But beware: unless the user happens to be using IE, the upload will use a new browser session to upload the files. This means that if you require that a user be authenticated before uploading something (and you better be), the upload won’t work – the request will be forwarded to the login form, or to wherever your system forwards unauthorized requests. This is a maddening bug to track down, and there is nothing you can do to make Flash use the right session. The work around is to send the session cookie in the url and, on the server side, use that to override the new (and wrong) session cookie sent by Flash. Here’s how that works in symfony, although much of the following is useful for other languages or frameworks:

First, we have to tell our Flash component what the cookie is, so it can roll it into the URL. One solution would be to pass the session cookie as an argument in FlashVars, but then the user’s session cookie is sitting unencrypted in the HTML, leaving them vulnerable to cross-site request forgery. Better to use javascript to fetch the cookie, and then put it in FlashVars. If you are using ufo.js, the first argument to UFO.create() should look like this:

{
  movie: '/flash/uploader.swf',
  id: 'uploader',
  name: 'uploader',

  flashvars: 'cookie=' + document.cookie,

  // other options ...
}

Note that if you are dealing with multilple cookies, you will want to parse the output of document.cookie and send only the desired cookie.

Next, add the cookie to the URL in your ActionScript (this is for ActionScript 2.0):

var list:Array = myFileRefList.fileList;
var item:FileReference;
var url:String = _root.uploadURL + '?cookie=' + _root.cookie;

for (var i:Number = 0; i < list.length; i++) {
  item.upload (url);
}

That does it for the client side. Now, we need to tell PHP to use our cookie instead of the one the browser sent. This does the trick:

list($cookieName, $cookieValue) = str_split('=', $_GET['cookie']);

session_name($cookieName);
session_id($cookieValue);

session_start();

If you are using symfony, things are a little more complex. We need to call session_name() and session_id() before session_start(); looking at the symfony source code, we find that session_start() is called in sfSessionStorage::initialize(). So a simple solution is to extend the sfSessionStorage class:

class mySessionStorage extends sfSessionStorage
{
  public function initialize($context, $parameters = null)
  {
    if ( /* whatever the condition is when we want to do this */ ) {
      if ($cookie = $context->getRequest()->getParameter('cookie')) {
        $name = 'symfony';
        preg_match('/^' . $name.'=(.*)$/', $cookie, $asMatch);
        $value = $asMatch[1];

        session_name($name);
        session_id($value);
      }
    }

    parent::initialize($context, $parameters);
  }
}

Finally, tell symfony to use the mySessionStorage class by editting factories.yml:

all:
  storage:
    class: mySessionStorage
    param:
      session_name: symfony

And you're done! Clear your cache, and try it out. An easy way to check if it's working is to add the following line to the end of index.php (or frontend.php):

file_put_contents('testSessionOverwrite.txt', sfContext::getInstance()->getRequest()->getActionName());

Now try uploading a file. If the action name in testSessionOverwrite.txt is the action you're uploading to, you're golden. If instead it is the name of the action that authenticates users, you have a problem somewhere, and you get to have the enjoyable experience of debugging PHP without browser output. Remember to erase the debugging line from your front controller when you get everything working.

Next time, just make the users upload their damn files one-at-a-time...

Don’t use the equality operator (==) to compare strings – use the strcmp() function, or the identity operator (===). In fact, when comparing values in PHP, use the identity operator (===) instead of the equality operator whenever possible. You may have heard that === is faster, since it incurs no type conversions, but some people have argued that it hurts code clarity. According to this theory, you should only use the identity operator when you actually need the two variables to have the same type, as when checking strpos() for the return value “false“. But the fact is that the identity operator is not only faster, it is also clearer. The identity operator says, “These two pieces of data are identical,” whereas the equality operator says, “These two pieces of data, or anything under the sun they could possibly be converted to, are equal.” Which seems like clearer code to you?

If you doubt the importance of this distinction – and I understand why you might – check out the following, rather shocking examples taken from the PHP manual:

if (            0 == 'my string'
  &&            1 != 'my string'
  &&       '+010' == '10.0'
  &&   '  131e-2' == '001.3100'
  && '000e002073' == '0e459239'
  &&       '0xab' == 0253
  &&       '0xab' != '0253'
  &&       '0xab' == '171'
){
  echo 'WTF????';
}

If you run the above code, you will see that all the above examples do indeed evaluate to true. How can that be? It’s because PHP checks every possible conversion of each argument, so it actually tries converting both strings to floats, and if those floats are equal, returns true. Those little e’s are exponent markers, the x’s indicate hexadecimal values, and a leading 0 marks an octal (unless it’s in a string, apparently). As for why the numeral zero is equal to any string … it beats the hell out of me.

In light of these facts, a developer should only ever use == when type-conversion is expected, such as when comparing a form input to a numerical value. Furthermore, we should regard == as expressing this expectation, since, by using the comparison operator, the developer has forced us to check for conversions. Thus, to keep your code clean and self-documenting, stop using ==. Use strcmp() for strings; it’s binary-safe, and expresses the type of your arguments without the need for comments. Use === for everything else.

An Undocumented “Feature”

Suppose we write the following code, whose simple purpose is to go through an XML document and replace every “foo” element with an empty “bar” element:

$dom = DOMDocument::loadXML('
  <root>
  <foo>This</foo>
  <foo />
  <foo />
  </root>'
);

$document = $dom->documentElement;
$foos = $document->getElementsByTagName('foo');

for ($i = 0; $i < $foos->length; $i++) {
  $bar = $dom->createElement('bar');
  $document->replaceChild($bar, $foos->item($i));
}

We are quite surprised when the script outputs:

<root><bar/><foo/><bar/></root>

Why did it skip the middle element? Because the DOMNodeList class has an undocumented “feature”: when the owner document of a DOMNodeList object is changed, the object is recreated. That means that, when we replace the first “foo” node, the second “foo” node becomes the new first node. Also, the length of the node list is now 2, not 3. But since $i has been incremented, the for loop misses the second node entirely, operates on the third, then exits normally.

The solution to this problem is to save a reference to each node in an array, then loop over the array:

for ($i = 0; $i < $foos->length; $i++) {
  $nodes[$i] = $foos->item($i);
}

for ($i = 0; $i < count($nodes); $i++) {
  $bar = $dom->createElement('bar');
  $document->replaceChild($bar, $nodes[$i]);
}

This code outputs what we intuitively expected from the original code:

<root><bar/><bar/><bar/></root>

Implementation: A DOMNodeIterator Class

It’s best to encapsulate this technique in a class. Here’s a simple class that does the job:

class DOMNodeIterator implements Iterator
{
  protected $nodes;

  public function __construct(DOMNodeList $nodeList)
  {
    if ($nodeList->item(0)) {
      for ($i = 0; $i < $nodeList->length; $i++) {
        $this->nodes[$i] = $nodeList->item($i);
      }
    }
  }

  public function current()
  {
    return current($this->nodes);
  }

  public function key()
  {
    return key($this->nodes);
  }

  public function next()
  {
    return  next($this->nodes);
  }

  public function rewind()
  {
    reset($this->nodes);
  }

  public function valid()
  {
    return $this->current() ? true : false;
  }
}

On the Other Hand, Orphan Nodes

Our iterator has one drawback: if we remove a node in the list via removeChild(), it will still exist in the iterator, but it will no longer be associated with our document. Unfortunately, the only way to check for this is to ascend the entire DOM tree each time we want to access a node, to make sure it is still a descendant of the root node. Rather than incur that overhead, we’ll leave it to the devloper to use the iterator with care. We can safeguard the above code by putting the call to replaceChild() inside a try block:

try {
  $document->replaceChild($bar, $foo);
} catch (DOMException $e) {
  if ($e->getMessage() !== 'Not Found Error') {
    throw $e;
  }
}

An Issue with PHP, or with DOM?

Stay tuned for my next blog entitled “Why the DOM Sucks.” Till next time…

One undeniable advantage of Ruby on Rails is its terse template syntax. The cumbersome

<?php echo $something ?>

is replaced by the elegant and readable

<%= something %>

The very good news is that you can use these same tags in PHP! Just add the following to your htaccess:

php_flag asp_tags on

Voila! Readable templates. What’s curious is that no one seems to use this option. Perhaps it is because they are referred to as “ASP-style tags.” (Can we just call them “Ruby-style tags”, instead?) On all my sites, I use the long tags for blocks of code, and the short <%= %> tags for any PHP code floating in the HTML sea. In symfony, that means the template files use one tag-style, and the rest of the code uses the other. I encourage everyone – yes, everyone – to start using Ruby-style tags in their templates. The more people use it, the more common it will be to have the “asp_tags” option on by default, so people on shared servers can join in the readable fun.

It’s important for a second reason – arbitrary conventions should be standardized. That is, any time we are faced with a set of possibilities that are all of equal value – such as what weird punctuation our programming language should use to demarcate itself – we should pick one standard way and stick with it. That way we reduce the learning curve of all languages (or whatever the things the convention pertains to). Imagine if there were one, universal syntax for putting server-side code into HTML. Imagine if there were a templating language that every designer knew – because it’s so simple – and that every server-side language supported. It would not be a universal programming language, since we should not be using the full power of a programming language from inside our templates; that’s what the controller code is for. This universal templating language (What the hell, let’s go ahead and call it UTL, because giving initials to computer-denizens makes them seem like real people) should support the following things, and probably nothing else:

  1. Variables, including objects and arrays
  2. if/else
  3. while
  4. foreach
  5. Very basic arithmetic and string operators
  6. No function or method calls

That last one may raise some eyebrows. Why would we not include functions and methods? Because we can call all those funcitons in the controller, and assign their return values to variables, which we then use in the template per number 1 above. Also, allowing function calls brings the capacity for arbitrarily complex logic into UTL, as well as coupling it more tightly with the mother language, both of which defeat the purpose of UTL.

Make the dream a reality. Start by using Ruby tags.

« Older entries § Newer entries »