Installing Symfony 1.1 SVN and Symfony 1.0 PEAR packages side-by-side: A Windows Vista How-To (and XP, too)

February 27th, 2008

As a tie-in to this excellent how-to for installing both versions of Symfony, I’ve decided to extend the method to apply to Vista as well.

EDIT: Symlinks don’t work this way because of the working directory being in C:\PHP where the symlink is located. See below for modified instructions.

First, check out the SVN branch for 1.1 to a directory of your choosing - this can be located anywhere on any storage volume. When the checkout’s done, open a command prompt and navigate into your PHP directory where symfony.bat is already located. In my case, this is C:\PHP and my checkout is D:\Projects\symfony-1.1. As Vista comes with an NTFS file system capable of UNIX-like (not quite, but close enough) symlinks (thanks to camason on #symfony for pointing that out to me), you can create a symlink to Symfony 1.1’s batch file using mklink (you’ll need a command prompt with elevated privileges for this to work):

C:\PHP> mklink symfony-1.1.bat d:\Projects\symfony-1.1\data\bin\symfony.bat

This creates a symbol link to the symfony.bat executable - now I can (assuming I have PATH set to C:\PHP) run symfony-1.1 at the command prompt from anywhere and can use the new branch with the same ease of use as the original article.

Unfortunately, due to symlinks executing with the working directory being in C:\PHP, you’ll get Symfony v. 1.0.x instead. To overcome this, delete the symlink and create a symfony-1.1.bat with the following contents (including fix from neonard0):

@cmd /c d:\Projects\symfony-1.1\data\bin\symfony.bat %1 %2 %3 %4 %5 %6 %7 %8 %9

That will fix the working directory problem and correctly execute Symfony 1.1.

Tuesday weirdness: a Symfony on Symbian phones

February 19th, 2008

A while back, I’ve stumbled upon an interesting, yet exotic, project - PAMP. It promises to bring the full Apache/MySQL/PHP stack to the Symbian phone. So, on a whim, I decided to try it out.

After following the installation instructions (installing on a Nokia N95 with the installation for memory cards) and starting up the PAMP stack, I’ve connected to the home LAN network and navigated my computer’s browser to the phone’s LAN IP. Lo and behold - the almighty “It works!” sign showed up. Even phpinfo() says it’s got most of the bundled extensions enabled (including GD2 and mbstring!).

So, on another whim, I decided to stress test the bugger and see if it runs Symfony. To spare you the excitement - it doesn’t run. Copying the files via USB messes up the file casing, so I had to re-copy the whole shebang using the phone’s sync software (which I’m still doing).

One thing to add though - while copying, I’ve noticed some files will not copy and I’m guessing the culprit is the lenght of the absolute path and name of the file. The first one in question is located inside $sf_data_dir/sfPropelCrud/ somewhere (the damn thing won’t show me which), there are probably more (I’m still copying files by hand). While I’m not using the generator in the test application, it seems there will have to be some workaround to get it working on a this phone (but the question really is - is Symfony really meant to run on phones?).

More to follow.

Edit:

It seems that using the phone software’s bundled File Manager solves the file casing issue. I still haven’t managed to copy all the files, but those that can’t be copied I’m sure won’t get used anyways (some generator skeletons and such).

Edit nr.2:

Well, all things said and done, it seems PHP segfaults before symfony has even a chance of running anything, but no way of seeing what error is produced, exactly. I haven’t been able to find any Apache logs written anywhere. And no, no Symfony logs to speak of as of now (it segfaults before that point). It could be something to do with UTF-8 encoding - I’ve tried opening a file on the phone with the default file manager and all the YAML files were messed up. I’m not even sure which encoding the phone is using. It’d be a shame if it was limited to ISO-8859-2 or such.

Tired of setting up your presentation/testing environment?

February 6th, 2008

Yeah, I’ve been away a while, had no time to update this blog, but still have been active on freenode’s #symfony channel.

Just a quick tip for anyone interested or looking for a better solution than XAMP - it’s called The Uniform Server. It unzips into a convenient folder anywhere on your computer and sits there until invoked. It’s portable (USB key server, anyone?), self-contained and can be secured and managed via the control panel after you get the server up and running.

It took me just 10 seconds to unzip and start the server (including opening the command prompt and typing Start_server.bat). That’s the fastest Apache/PHP5/MySQL setup I’ve ever done. Maybe not very newbie friendly, but for anyone used to working with LAMP, it should be a breeze.

Apple, Safari, Windows and a whole lot of confusion

November 27th, 2007

Before I start off, this isn’t a Mac vs. PC bash article. Nor is it a comparison between the two. I disclaim any statements about the superiority of each platform, since this will not be an article discussion these topics. That said, let’s move on to the topic of relevant interest.

As any self-respecting web developer, I try to cover as much ground as possible when it comes to the population of browsers that inhabit our Internet. It’s a pain in the ass, but we have to do it. Much of it is alleviated by the numerous JS and CSS libraries that I use to leverage the complexity of being cross-browser compatible (jQuery, Blueprint CSS, YUI CSS, just to mention a few). Still, it’s a daunting task.

Recently, Apple announced that it would be bringing the Safari browser to Windows and I thought “Gee whiz, it’d be great not to have to buy a Mac just to see IF my site works on a Mac.” I downloaded a copy, had it installed in less than a minute and was pretty impressed by the painlessness of the process. Nice job, Jobs (pun intended). My only gripe was the page loading time - everytime I’d start it up, it would take anywhere from 10-20 seconds to load up the first page, subsequent loads were quicker. I surfed a few pages thinking that it was good that it had its own typography rendering engine (nice to see how fonts look on Mac natively - very important for making accessible designs). Also, it seemed kind of… different. The pages I was looking at seemed more vibrant in colour. Then it hit me - of course, Macs have a gamma of 1.8 whereas Windows has 2.2. It must be using that preset to render colours within the browser. Neato, I thought, since most sites looked better.

What I was thrown off the chair for was testing a design I threw up with the help of a friend of mine. Nothing special, just a few background images and some JPEGs. Nothing special. Everything looked perfect on Linux and Windows (the two targets I test for primarily), worked on Opera, Firefox, IE6 + 7, Konqueror and a few other minor browser that I just felt like testing in. Finally I thought, “okay, moment of truth!” Fired up Safari on Windows and lo and behold, HTML colour space was different than the image colour space, be it PNG, JPEG or GIF (I even tried removing colour profiles from the images, to no avail). In plain terms, #00aa00 (HTML) != #00aa00 (image). All the backgrounds were now fractured at the seems and the page seemed like it was thrown together at gun point.

Now, I ask, what is the point of having your own colour space calibration if you don’t apply it consistently? While I don’t have a minimal test case for when this happens, I presume I just wasn’t paying attention at the other sites to notice a similar effect. Or I may be missing the point.

But the point is, I wasn’t expecting an image colour space misalignment problem, more of CSS and JS-related problems. I guess until Apple sorts this colour space problem in the Windows version of Safari, it’s widely unusable for anything but functional and layout testing purposes. It seems browsing the web on Windows is best left to non-Apple browsers. That, or depending on your colour blindness to counter the colour problem present.

Reaching deep into the I18n core

October 17th, 2007

When creating truly internationalized content, you need to think of a few things - first, what country your are in, and secondly, what the locale is in that country. Why should you care? User input.

While Symfony does have handy features via sfI18N, it doesn’t expose some of the methods needed to correctly parse strings. While string parsing isn’t meant to be the scope of this post, I’ll explain how to get your hands on the number formatting information to enable your application to correctly parse input strings and/or display them in templates (although, I might remind you of the Number helper and its application within the view layer, to aviod logic duplication when that’s already been taken care of).

When you want to get number format information, you simply create an instance of sfCultureInfo, like so:

$culture_info = new sfCultureInfo(sfContext::getInstance()->getUser()->getCulture());
$number_format_info = $culture_info->getNumberFormat();
$negative_sign = $number_format->getNegativeSign();
$decimal_sign = $number_format->getDecimalSeparator();

This gives you the chance to write your own number parser according to the expected format and/or use locale-specific settings for different purposes for user-friendly input, not just sfI18N::getTimestampForCulture().

IE fixed, Opera is next

October 3rd, 2007

I’ve never liked Opera that much - have been trying to use it since version 7, but never got around to actually keep myself using it. I actually prefer IE7 over Opera 9 any given day of the week. Now, it seems, there’s yet another reason why I dislike Opera even more, but will have to keep an eye on it after all, even more so, after I discovered a nasty “feature.”

It all boils down to semantics, really. Opera prides itself on being the fastest browser on the planet. Well, from a user’s standpoint, I’d agree, pages do load smoothly in Opera, rendering is a shitload faster than Firefox (especially when it comes down to sliders, for example) and IE. Yes, I admit, it seems to work faster than other browsers. But there’s a price to pay - it doesn’t block scripts when they try accessing CSS properties when listening for the DOMContentLoaded event.

Why should that matter? Case in point: when you want to enable a user interface which uses unobtrusive scripting, the event fires BEFORE any external stylesheets get loaded. As a consequence, all hell breaks loose when you try styling elements. Say, for example, you want to position some div element to the left of some other, like so:

<div>This is a box</div>
<div>This is its right neighbour</div>

// lang js
jQuery(document).ready(function() {
  jQuery("div:last").css({
    position: "absolute",
    top: jQuery("div:first").css("top"),
    left: jQuery("div:first").css("width")
  });
});

In this case, IE, Firefox and Konqueror (and, by induction, Safari) will load CSS first, then apply the CSS properties. Opera does not and fires the DOMContentLoaded event on a bare DOM. It helps when you use inline styling (jQuery then gets the correct styles), but what’s the point of using CSS if you declare everything inline anyways?

Opera sucks. From a developer’s point of view. And no, it’s not jQuery’s fault. It’s Opera’s implementation and interpretation of the aforementioned event.

Oh, and if you’re looking for a solution, there’s no way around using the onLoad. I know, you’re thinking “but the content flashes if you use onLoad!” You are correct. But Opera already flashes unstyled content before loading the external CSS (at least in my tests with an empty cache), so this shouldn’t bother you. It will bother the crowd (all 2% of them), but hey, at least the GUI works!

UPDATE: It seems the only consistent implementation of DOMContentLoaded within other browser is waiting for all elements (including scripts and CSS) to load before actually firing the event (up to Gecko 1.9+, Trident-based browsers don’t implement this event and must be simulated). The rationale behind this is that scripts loaded in the head might use styled elements after the CSS is applied, so that, for example, boxes are aligned or moved according to other elements’ positions and/or sizes. Even copying calculated styles from one element to the other.

Opera goes the other way around - it defined the event as the moment is stops parsing the bare HTML, leaving it up to the programmer to figure out cases when any of the files loads in a different order or if at all. It does improve responsiveness, showing the content before the actual styles are applied, but the downside is flashing unstyled content and gripes about checking applied styles first before trying to actually do anything with dynamically modifying interfaces.

Yet another grievous error on IE’s part (updated: float problem)

September 26th, 2007

AJAX can be really useful sometimes. We all agree on that. We’ve pretty much solved the cross-browser divide when it comes to the XHR object by using libraries, but one thing still remains - what about the GUI?

I know this might seem like just another post about using AJAX and fancy GUI updates, but let me point out that it isn’t. It’s about a major error I’ve found in IE7 (and possibly 6) that kinda blows your whole client-side dynamic updates. I’m talking about rendering errors regarding lists in IE. The dynamically rendered ones.

A test case involves an unordered list (possibly ordered, too), which is empty by default (on page load) and gets populated after the AJAX request fires. What my script did was it took a JSON response and appended li elements to the list. You’d think something as simple as this would pose no problem to the new and improved Trident, but it does. The list expands as though the list items are there, but they’re transparent. If you want to see the contents, you have to drag a selection over the text (and even then renders only the letters that were actually selected), but they dissapear upon re-rendering.

The first solution I could come up with is to apply a CSS transformation to the text after adding li elements. Which is a major pain in the ass. I just did a quick .fadeOut(1).fadeIn(1) to force change in opacity:

jQuery("ul.error").fadeOut(1).fadeIn(1);

That way, no blinking would be noticed by the user since the animation would be faster than a screen redraw, thus eliminating the problem.

Haven’t done a baseline test on this one, but it shows just how grimey stuff gets when you’re not developing straight onto IE7 in the first place, then porting to others.

Long live Trident. You bastard.

UPDATE: I’ve managed to identify the culprit causing this disastrous behaviour - it has to do with floated elements and clearing elements. Also known as the Peekaboo bug. While this solution might not be appropriate for you, it worked for me in the given situation.

Basically, this problem manifests itself when you try to use floats, then a clearing element after them to ensure they are fully contained within a parent container div. The problem is solved by assigning the following style to the clearing element:

<div>&nbsp;</div>

The only problem here I can see is that it breaks pixel accuracy - while you can assign padding and margin of 0, you cannot style it with height:0 or font-size:0. And also, adds to the semantics of the page, which I personally dislike. Sure, you can class the style in the above example, but you still need to put a non-breaking space in there.

This was supposed to be fixed in IE7, as the link says. Guess not. (Tested on IE 7.0.5730.11, update version 0, Windows XP SP2 fully patched.)

More gotchas from the Symfony world

July 23rd, 2007

Well, it seems there’s a few other things that aren’t as they seem in Symfony - if they’re expected or not, they are things I’ve noticed and needed a few minutes (or in a another case) or just over two hours to figure out.

All of them have to do with Symfony’s output escaper using PHPView. The first one is concerned with custom ResultSet objects that you pass into the template using a simple $this-&gt;anything assignation within an action or a component. Say you’re got a simple SQL query within a component or action that you want returned as a ResultSet (using Creole):

$SQL = "
  SELECT *
  FROM app_user
  WHERE insertion_time > DATE_DIFF(CURDATE, INTERVAL ? DAY)
";
$stmt = Propel::getConnection()->prepareStatement($SQL);
$this->results = $stmt->executeQuery(
  array(7), ResultSet::FETCH_ASSOC
);

You’d expect to have $results contain a ResultSet object that you can iterate over using a while($results-&gt;next()) {}, but you’re in for a surprise - it doesn’t work.

If you look closely at the variable within the template printed out using print_r(), you can see that the object is wrapped within an sfOutputEscaper (or variant of) object that intercepts certain functions. This is what seems to happen when using a ResultSet object - the wrapper escaper object overloads the methods and prevents ResultSet’s methods from being invoked.

The solution? Place $results = $results-&gt;getRawValue() somewhere before the while loop and everything works fine.

I’ll probably enter a ticket for this one, after I grab something to eat. ;)

RobotReplay, a usability testing tool

July 14th, 2007

If you’ve ever asked yourself just why your web site or web app doesn’t perform as well as you’ve thought it would, since you’ve given a lot thought into the design of the page and user interface, then you might ask yourself - are you the proper person to be judging the design?

In comes usability testing. It’s giving the end user a chance to work with your product (in our case, a web page or application) and having a system measure the user interaction - how long it takes them to locate a certain function, where they have the most difficulty identifying a certain feature, finding information, etc. There’s already great software that does exactly this (Morae, for example), but the problem here is that you still need a lab to conduct such experiments.

Read the rest of this entry »

A PHP gotcha within Symfony

June 22nd, 2007

There’s an interesting aspect about using functions within partials, which I’ve written about before - the existence of functions and the dangers of redeclaring them.

The problem here is using partial-specific functions within partials. We’ve had an instance where we needed a function to solve a recursive problem when displaying data within the partial (a complex tree structure).

The quick’n'dirty solution was to declare the function within the partial, which solves the problem. There was no PHP fatal error right up until functional testing. The reason why this error wasn’t spotted before was because the partial was used only once (if it was ever used within a view), thus never realising itself.

When running functional tests, sfTestBrowser instantiates an instance of the sfContext class and runs the application within a single runtime, which means that all registered global functions exist at all times. And because the partial is used by many views, the second the test encountered the second view that used the aforementioned partial, the test died with a PHP fatal error.

As mentioned in the article from before, the solution is to never declare any functions within template PHP files. Any functions that you need (even if it’s used by a single template file) should be declared within a helper and included appropriately. This way, Symfony guarantees the helper will be included exactly once, avoiding the fatal error that would otherwise crash the application.