Flextrine 0.9 released

I am very proud to announce the release of Flextrine 0.9.  This is a major release with changes across the board; much of the codebase has been improved, optimized and cleaned up, and a host of new features have been added.  Flextrine has also moved from Google Code to Github, and the documentation has been completely updated for the new version and is available on the Github wiki.  Some of the new features are listed below:

  • The ability to run multiple Flextrine applications within a single install – Flextrine will ship with a micro-framework to facilitate this along with a command line tool to create new projects.
  • Flextrine Manager functions, including entity generation, will become available through the command line (implemented through the Doctrine console tool) to aid in build processes.  The Flextrine Manager has been removed.
  • Configuration files are YAML instead of PHP.
  • Support for XML, YAML as well as annotations in entities (this was done mainly to enable the use of the awesome ORM Designer) .
  • Massive performance boosts when updating large objects graphs.
  • Lazily loaded collection associations can be configured to load on demand, throwing ItemPendingErrors to allow Flex components to react to the updates automatically.
  • Lazily loaded entities can be configured to load on demand.
  • Improved DQL querying from Flex including support for named parameters and hydration modes including scalar queries.
  • Bi-directional associations are now auto-managed by Flextrine, so there is no longer a need to set both sides of the relationship.
  • An EntityManager::rollback() method that undoes any changes made to the repository.
  • Class table and single table inheritance.
  • By default repositories hold weak references so that unused entities are eligible for garbage collection after Configuration::entityTimeToLive has elapsed (configurable globally or per repository).
  • The option to run Flextrine in PULL mode; this queues up changes but doesn’t apply them to the repositories until a successful return from em.flush() (experimental!)
  • PagedCollections which load query results as the user scrolls (experimental!)
  • Integrated support for access control to entities using Zend_Acl (experimental!)
  • Heaps of bug fixes!

Flextrine v0.9 is available from www.flextrine.com

Work on Flextrine resumes!

After a few months break I have started work on Flextrine once again.  During the break I have been working a lot with Doctrine 2 in pure PHP, and have learnt a lot of things to do with both the internals of Doctrine and its practical application in a real world application.  Now that Doctrine 2 has its first stable release its time to start applying some of these lessons to Flextrine.

Here are a few of the things that will be in the upcoming release of Flextrine:

  • The ability to run multiple Flextrine applications within a single install – Flextrine will ship with a micro-framework to facilitate this along with a command line tool to create new projects.
  • Flextrine Manager functions, including entity generation, will become available through the command line (implemented through the Doctrine console tool) to aid in build processes.  The Flextrine Manager will probably be removed.
  • Configuration files will be YAML instead of PHP.
  • Support for XML, YAML as well as annotations in entities (this was done mainly to enable the use of the awesome ORM Designer) .
  • Integrated support for access control to entities using Zend_Acl.
  • Massive performance boosts when updating large objects graphs.
  • Lazily loaded collection associations can be configured to load on demand, throwing ItemPendingErrors to allow Flex components to react to the updates automatically.
  • Lazily loaded entities can also be configured to load on demand.
  • Improved DQL querying from Flex including support for named parameters.
  • Bi-directional associations are now auto-managed by Flextrine, so there is no longer a need to set both sides of the relationship.
  • An EntityManager::rollback() method that undoes any changes made to the repository.
  • Class table inheritance.
  • By default repositories hold weak references so that unused entities are eligible for garbage collection after Configuration::entityTimeToLive has elapsed (configurable globally or per repository).
  • The option to run Flextrine in PULL mode; this queues up changes but doesn’t apply them to the repositories until a successful return from em.flush() (experimental!)
  • PagedCollections which load query results as the user scrolls (experimental!)
  • Heaps of bug fixes!

Flextrine 0.9 is currently planned for release towards the end of February.

Flextrine 0.7 released – now with ZendAMF!

After much soul searching I eventually decided to put in the time to convert Flextrine from using AMFPHP to ZendAMF.  There were a few reasons I decided to make this move, but eventually it boiled down to the fact that quite a few people had asked me to do so.  In retrospect it was certainly the right thing to do – ZendAMF has the green light from Adobe, its licence is LGPL instead of GPL and the cleaner code base means that the changes Flextrine requires can be implemented as overridden classes instead of having to modify the ZendAMF core.  This particularly is great news because it means that you can use Flextrine directly with the standard Zend framework installation, whereas previously you could only use the version of AMFPHP bundled with Flextrine.

Functionally speaking things remain exactly the same, and we continue to approach our stable release alongside Doctrine 2.

The new version of Flextrine can be downloaded from www.flextrine.com.  Note that if you are upgrading from a previous version of Flextrine you will need to regenerate your AS3 entities.

Transforming ArrayCollection data using a map function to keep your view seperated in an MVC app

Last night I was working on a project which involved me having to display large amounts of data in a Flex list.  However, this data needed to be transformed before being displayed.  Let me explain with a simplified example.

The problem

Suppose we need to display a huge list of Result objects, where a Result object contains a score property (lets say it is a Number).  If we just need to display the number then we provide the ArrayCollection of Results as the dataProvider to the list and set the dataField to ‘score’ and everything is nice and easy.  Now suppose that we need to do some kind of calculation on score – for example, we need to divide it by 2 before displaying it.  Again, this is no problem; we use the labelFunction in the list and add a callback function in the MXML file that divides the score by two before returning it:

   1: private function labelFunction(item:Object):String {

   2:     var result:Result = item as Result;

   3:     return result.score / 2;

   4: }

This is all fine.

Now lets suppose that we need to transform the score in a more complicated way – imagine that we are writing some kind of multiuser application and we need to divide the score by the number of users currently logged on to the application before displaying it in the list.  At this point I should point out that I tend to use PureMVC so I will explain this using PureMVC terminology, but its equally applicable to all other MVC frameworks (Mate, Swiz, Robotlegs, etc).

Lets assume that the number of users logged on is in our Model tier; we then have a couple of options on how to go about this:

Inject the number of users into the view from our mediator and continue to use labelFunction.

       1: public var userCount:Number;

       2:

       3: private function labelFunction(item:Object):String {

       4:     var result:Result = item as Result;

       5:     return results.score / userCount;

       6: }

This is an ok solution – it doesn’t break MVC encapsulation and it works fine.  However, the drawbacks are that we need to monitor when userCount changes and each time re-inject it into the view (and tell the list to update itself).  But the main problem with this is that it gives our view knowledge of something that it shouldn’t know about.

Extend Result to do the calculation itself

We can add a getter to Result that does the calculation which means we can get rid of labelFunction in the view and just set dataField to the getter (e.g. dataField=”transformedScore”).  But this just moves the problem elsewhere; now the Result object will need to know the number of users; we’d either have to inject it in via a static variable, or give the Result object knowledge of the MVC framework.  This solution is in fact much worse than our first effort.

Pre-build the ArrayCollection with transformed scores

In this method we iterate through the Results, doing our calculation on score each time and building up a new dataprovider.  This is fine from an MVC perspective; the view gets its data fully formed in the format it requires, and since the mediator is building the list there is no problem with it querying the model tier.  However, this is a bad solution for other reasons; say that you have 5000 Result objects; the mediator will need to iterate through the entire list before passing the new collection to the view, incurring a nasty performance hit.  Furthermore we will need to rebuild this list entirely if the score or the number of logged in users change.

The solution

Here, at last, is my solution to the problem.  Like all good solutions it is disarmingly simple 🙂

   1: package org.davekeen.collections {

   2:     import mx.collections.IList;

   3:     import mx.collections.ListCollectionView;

   4:

   5:     public class MappedListCollectionView extends ListCollectionView {

   6:

   7:         public var mapFunction:Function;

   8:

   9:         public function MappedListCollectionView(list:IList = null) {

  10:             super(list);

  11:         }

  12:

  13:         override public function getItemAt(index:int, prefetch:int = 0):Object {

  14:             if (mapFunction == null) {

  15:                 return super.getItemAt(index, prefetch);

  16:             } else {

  17:                 return mapFunction(super.getItemAt(index, prefetch));

  18:             }

  19:         }

  20:

  21:     }

  22:

  23: }

MappedListCollectionView extends the normal ListCollectionView (which is the superclass of ArrayCollection) adding a single property – mapFunction – which transforms an item of the array collection into another item.  So now we can do the following in the mediator:

   1: var mappedListCollectionView:MappedListCollectionView = new MappedListCollectionView(resultsArrayCollection);

   2:

   3: mappedListCollectionView.mapFunction = function(item:Object):String {

   4:     var userCount:Number = getUserCountFromModel();

   5:

   6:     var result:Result = item as Result;

   7:     return result.score / userCount;

   8: }

   9:

  10: myView.myList.dataProvider = mappedListCollectionView;

I think this is an excellent solution – it maintains encapsulation within the view, it follows Flex standards (in that its syntax is the same as filterFunction), it will work with Flex binding and COLLECTION_CHANGE events and best of all it is high performance as mapFunction is only called for the rows that are actually on the screen.

One thing to bear in mind when using this solution is that Flex databinding will only be triggered when elements of the array collection itself change, so if userCount changes you will need to manually dispatch a COLLECTION_CHANGE event on the array collection.

Hope you find this as useful as I do!

Announcement of Flextrine 2

Flextrine Bar

I am most proud to announce the development and upcoming release of Flextrine – an open source project I am developing that simplifies and encapsulates ORM with Flex and PHP.  Very simply, Flextrine maps AS3 objects to database tables giving you the ability to save and load objects to a remote database without having to worry about any server coding.  It supports all usual associations, local caching, indexing, Flex databinding and many other things, as well as having a nifty web interface for generating schemas and stubs.

Flextrine is planned for release on 1st September to match the release of its parent project Doctrine 2.

Check out http://code.google.com/p/flextrine2/ for more details.

Using addItemAt and removeItemAt on a DataGrid dataprovider

According to the notes buried deep within the Flex documentation:

If you use the ICollectionView interface to sort or filter a collection, do not use the IList interface to manipulate the data, because the results are indeterminate.

This means that if you are using an ArrayCollection as the dataprovider of a sortable component (e.g. a DataGrid), sort the columns and then try and use addItemAt() or removeItemAt() elsewhere in your application you will be entering a world of pain; the wrong items will be added/deleted in the datagrid, rows might get duplicated in strange way, etc.

The reason for this is that sorting the datagrid is changing the ListCollectionView of the original ArrayCollection which affects subsequent index based operations.

Luckily there is a simple solution; give the component its own personal ListCollectionView:

   1: dataGrid.dataProvider = new ListCollectionView(arrayCollection);

This preserves IList integrity on the original collection which means that databinding should work as expected.

How to stop SWFs caching in the browser once and for all

As Flash and Flex developers know all too well, browsers have a habit of caching SWFs so that when you put up a new version it doesn’t always show up on client machines.  There are two classic ways to get around this – either by manually clearing your cache (and telling your clients to do the same) or by appending a random number to the end of the filename as a parameter which is then ignored by the application but fools the browser into thinking that the file has changed.  The first method is unreliable and the second method causes the SWF to reload every time you visit the page (even if it hasn’t changed) which munches up your bandwidth and your time.

As it turns out, there is a third and far superior way!  With a tiny bit of PHP in your embed code you can make browsers refresh the SWF only when it has changed.  Note that this uses the SWFObject library, but would work equally well with any embedding method.

   1: swfobject.embedSWF("MySWF.swf?version=<?php echo filemtime('MySWF.swf'); ?>", "myDiv", "100%", "100%", "10.0.0");

It works by using the file modification timestamp of the swf as the version number with the result that browsers will refresh their cached copy if and only if you replace the swf with a new version.  Simple and extremely useful!

Watch and learn – Data binding in Flex

My apologies to those of you who are watching my blog for updates – I’ve been working flat out on a number of exciting projects over the last few months including a plugin-based XML editor written in Flex which will be released as open source software in the coming weeks.

In the meantime I wanted to point everyone’s attention to this brilliant lecture which explains Flex data binding at the compiler level and finally tells us what [Bindable] really does, why we need to use ArrayCollection instead of Array and all the other internals of Flex architecture which the official docs gloss over.

http://www.onflex.org/ted/2008/08/diving-in-data-binding-waters-with.php