YASB – Yet Another Symfony Blog

May 21, 2008

Initial commit of sfToboAds plugin now available

Filed under: General, PHP — Krof Drakula @ 9:35 pm

We’ve just released the initial version of sfToboAds, a Symfony plugin allowing for integration with ToboAds, an advertising network offering contextual text and graphic advertising to the masses (banners are contextual!). The initial release is pending PEAR packaging before being offered as a compressed download, for now, it’s available via the subversion repository on the following URL:

http://toboads-plugins.googlecode.com/svn/trunk/symfony_plugin

This is part of our wider package of plugins for different platforms and is fully LGPL licensed. A solid release with updated documentation will be available soon.

February 27, 2008

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

Filed under: General, PHP, Tips and tricks — Krof Drakula @ 4:37 pm

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:

@cmd /c d:\Projects\symfony-1.1\data\bin\symfony.bat %*

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

February 19, 2008

Tuesday weirdness: a Symfony on Symbian phones

Filed under: Exotic, General, PHP — Krof Drakula @ 6:59 pm

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.

July 23, 2007

More gotchas from the Symfony world

Filed under: General, PHP, Tips and tricks — Krof Drakula @ 5:00 pm

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->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):

// lang php
$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->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->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. ;)

June 22, 2007

A PHP gotcha within Symfony

Filed under: General, PHP, Tips and tricks — Krof Drakula @ 10:45 am

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.

June 13, 2007

Followup: Creating rich GUIs with Javascript in Symfony

Filed under: Browsers, Javascript, PHP — Krof Drakula @ 11:08 am

Well, I’ve written up a short summary of ideas relating to handling Javascript files in relation to requests, not it’s time to evaluate them.

First thing I’ve noticed with the different ways of injecting Javascript into the response is the order by which the files are loaded, the problem being dependency. If you’re using a library such as jQuery (or any other for that matter), the order by which the JS files are loaded is crucial. I usually force jQuery to use the noConflict mode by calling jQuery.noConflict() in a separate file (to keep the original library file intact in case of upgrades and updates) and loading it after jQuery. That’s done in the general view.yml file on the app-level configuration.

But when I try to add an action-specific JS to the mix, things start getting hairy – when you call $this->getResponse()->addJavascript(), it adds Javascripts to the beginning of the list of JS files, before the view.yml gets a chance to add its own. In this case, you’re limited to adding JS files via a module-level view.yml file by specifying the view to which you want to append the JS.

This is different when handling components – imagine having, say, a countdown timer written in Javascript. If you’d like to include it in several places but don’t want to handle the dependencies, then there’s a foolproof way of handling those – simply include the dependencies using $this->getResponse()->addJavascript(). This time, the components get rendered AFTER the main view, so including JS files this time adds them to the end of the list, after the main view’s files have been added.

The good thing about the latter is that you never have to worry about changing any view.yml files after including the component anywhere in your main views. That lends itself to building self-contained, no-fuss plugins using components, which, in the context of this article, could be HTML widgets, like calendars, calculators, AJAX comment boxes, shoutboxes, etc.

Anyways, hope this insight helps. Now for some midday coffee.

May 11, 2007

Easier I18n XLIFF message generation

Filed under: General, PHP, Tips and tricks — Krof Drakula @ 1:43 pm

If you’re like me and you don’t trust yourself to catch all of the breadcrumbs you leave behind you, you tend to rely on an arsenal of tools to keep you in check. This is especially true with XLIFF and Symfony.

There’s an i18n generation script that scans your actions, YAMLs and templates for the use of the __() function. The scanner routine is pretty robust and only adds missing entries, but leaves others intact. A great tool if you’re translating applications.

But there’s a problem: when you try to write your own validators and have I18n enabled in your application, the sfRequest::setError() expects 2 parameters: the name of the request parameter and the value of the error, the problem here being that ::setError() expects the second parameter to be the source language for translation, which in turn means that you don’t need to use __() to wrap your error message, so that it works directly with your validation YAML files.

That’s very smart, because you don’t have to translate your YAML validation files, since it already wraps it in __(). But not good, if you want to generate your own XLIFF files and not use the __() function (since the current implementation only scans for occurences of that function).

The problem was elegantly solved by fatg, who proposed testing the script for the detection of *__() functions – and it works. So, if you’re using any function which ends with __, the init-i18n script WILL detect it and add it to the XLIFF.

But how exactly does that solve anything? Well, instead of writing something like:

// lang php
$this->getRequest()->setError("my_parameter", "my_error");

…you write:

// lang php
$this->getRequest()->setError("my_parameter", i18n__("my_error"));

Okay, so the script now detects "my_error" as being an XLIFF source, but the application will fail with a fatal error in this case. That part is easily solved by adding

// lang php
function i18n__($message) { return $message; }

to apps/[myapp]/config/config.php, which creates the i18n__() function within the myapp application.

Although this isn’t the ideal solution (it would be nice if Symfony auto-generated the XLIFF by itself when using the __() function), it’s way better than duplicating the source keys inside comments like:

// lang php
// __("this is a source string");

Not only is it a pain to edit, it bloats the code significantly.

Anyways, hats off to fatg. Nice work.

May 9, 2007

Solved: How to get I18n working on reverse-engineered tables

Filed under: Database, PHP, Propel — Krof Drakula @ 12:24 pm

We’ve all been there – Symfony and I18n do play well together – it’s got XLIFF for interface translation which works almost out-of-the-box, it’s got localization features for things like numbers, currencies and many others. It also has internationalization features that work with database tables.

Unfortunately, all is well until you stray from the guidelines presented in the Symfony book. The norm in Symfony is to write the database definition withing the schema.yml file. That’s okay… it’s compact, concise and verbose enough to be understood within the context of Symfony nomenclature. But when you’re dealing with 25+ tables that need accompanying I18n tables, things could get messy, nomenclature or not.

(more…)

February 28, 2007

Progress update

Filed under: PHP — Krof Drakula @ 3:11 pm

I know, I know, I’m getting lazy. Or rather, that’s what it would seem. Lately I’ve had projects coming in on all sides, which extended my field to include developing Flash applications, which is a pain in the. Also, Friday is the big premiere I’ve been bragging about the last couple of weeks.

As far as things here are concerned, I’ve decided to write up a better image manipulation package for Symfony as a plugin, based on the Wideimage project. Yes, it’s yet another open source project I’m involved in, but there are several advantages to incorporating this package into a plugin for various reasons:

  • it handles all GD2-supported image types, other formats can be added by extending the image loader
  • supports all GD2 filters
  • simplifies common tasks for images (resize, blur, sharpen, writing pixels, etc.)
  • supports chaining operations
  • fully extendable on all levels
  • implements an unsharp filter, which enables you to generate sharper thumbnails

For a simple example of just how it works on the user level, have a look at this. Also, have a look at the included demos and unit tests. Yes, the whole package is thoroughly tested.

What this enables you to do is handle image uploads or manipulate images already on the server, for example, adding watermarks or generating grids of cropped images.

More to come after the show. ;)

January 25, 2007

Getting advanced with objects

Filed under: PHP, Tips and tricks — Krof Drakula @ 10:05 am

Just a quick note – if you’re into strict systems specification and architecture, you’re no doubt no stranger to object-oriented patterns and interfaces. In case you were ever tempted to use interfaces in your application, Symfony has a simple way of declaring an instance and having it autoload into the program stack: just declare your interface in a file, named as the interface itself, plus the suffix interface.php. Simple, no?

UPDATE: Per ruzz’s request, I’m posting a quick example:

(more…)

Older Posts »

Powered by WordPress