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.

Flextrine 0.6.5 released

Another released of Flextrine!  Since 0.6.1 there have been a number of changes to the Flextrine core.  The entity merging algorithm has been altered to take better advantage of Doctrine 2 merging giving us a hefty performance boost (thanks for Benjamin Eberlei at Doctrine for pointing this out), the requirement to use $_explicitType in Doctrine entities has now been removed, bootstrapping and configuration code has been extended and neatened up and there have been numerous bug fixes at all levels of the application.

My continued thanks to the community for their help in testing and using Flextrine!

Flextrine Tutorial – CRUD in a simple Flex 4 address book: Conclusion

Introduction
Setting up the server
Creating the entities
Creating the database schema
Loading the entities
Creating new entities
Deleting entities
Updating entities
Conclusion

I hope that this tutorial has given you some insight into the power of Flextrine.  In fact there are many areas of Flextrine that we didn’t touch on here including one to one and many to many associations, lazy loading, DQL, fetch joins, custom PHP functions and more – check the documentation for more details.

Both Flextrine and Doctrine 2 are currently in beta; the planned release date for both products is 1st September 2010 by which time I would hope to be able to confidently pronounce Flextrine as stable.  That’s where you come in!  If you find any issues in Flextrine please log them at http://code.google.com/p/flextrine2/issues/list and help me to make Flextrine the best Flex ORM library there is 🙂

Flextrine Tutorial – CRUD in a simple Flex 4 address book: Loading the entities

Introduction
Setting up the server
Creating the entities
Creating the database schema
Loading the entities
Creating new entities
Deleting entities
Updating entities
Conclusion

In FlashDevelop or Flash Builder create a new Flex 4 project and add the Flextrine client side library (in flextrine/src of the Flextrine download) to the classpath of your project.  Alternatively you can use the compiled flextrine/bin/flextrine.swc.  Now return to the Flextrine manager and click on GENERATE AS3 CLASSES.  You will be prompted to download a zip file – extract its contents into the src directory of your project.  You should now have AS3 versions of vo.ContactGroup and vo.Contact for use in your Flex application.

For reference, here are a few screenshot of what we will be working towards.  The tree on the left will show the groups and contacts, and the area on the right will have the group editor at the top and the contact editor below.  We will also have some buttons to create, delete and save contacts and groups.

Flextrine Contacts 1Flextrine Contacts 2

Create the Main.mxml entry class

We will begin by creating the Main.mxml entry class for our application.  To start with we will just create the basic MXML Application with a creationComplete event listener that configures Flextrine’s central class – the EntityManager.  For our simple application the only configuration that is required is to set the URL of gateway.php in the Flextrine server side component – in this case http://localhost/contacts/gateway.php.

   1: <?xml version="1.0" encoding="utf-8"?>

   2: <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"

   3:                xmlns:s="library://ns.adobe.com/flex/spark"

   4:                xmlns:mx="library://ns.adobe.com/flex/mx"

   5:                xmlns:local="*"

   6:                creationComplete="creationComplete()">

   7:

   8:     <fx:Script>

   9:         <![CDATA[

  10:         import org.davekeen.flextrine.orm.Configuration;

  11:         import org.davekeen.flextrine.orm.EntityManager;

  12:

  13:         private var em:EntityManager;

  14:

  15:         /**

  16:          * Initialize the Flextrine EntityManager, set the dataprovider of the tree and load the ContactGroups.

  17:          */

  18:         private function creationComplete():void {

  19:             // Setup the entity manager

  20:             var configuration:Configuration = new Configuration();

  21:             configuration.gateway = "http://localhost/contacts/gateway.php";

  22:

  23:             em = EntityManager.getInstance();

  24:             em.setConfiguration(configuration);

  25:         }

  26:

  27:         ]]>

  28:     </fx:Script>

  29:

  30: </s:Application>

Now we’ll add the GUI.  We’ll add a Flex Tree on the left with id tree, along with the buttons and the layout.

   1: <?xml version="1.0" encoding="utf-8"?>

   2: <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"

   3:                xmlns:s="library://ns.adobe.com/flex/spark"

   4:                xmlns:mx="library://ns.adobe.com/flex/mx"

   5:                xmlns:local="*"

   6:                creationComplete="creationComplete()">

   7:

   8:     <fx:Script>

   9:         <![CDATA[

  10:         import org.davekeen.flextrine.orm.Configuration;

  11:         import org.davekeen.flextrine.orm.EntityManager;

  12:

  13:         private var em:EntityManager;

  14:

  15:         /**

  16:          * Initialize the Flextrine EntityManager, set the dataprovider of the tree and load the ContactGroups.

  17:          */

  18:         private function creationComplete():void {

  19:             // Setup the entity manager

  20:             var configuration:Configuration = new Configuration();

  21:             configuration.gateway = "http://localhost/contacts/gateway.php";

  22:

  23:             em = EntityManager.getInstance();

  24:             em.setConfiguration(configuration);

  25:         }

  26:

  27:         ]]>

  28:     </fx:Script>

  29:

  30:     <s:HGroup width="100%" height="100%">

  31:         <!-- The groups and contacts tree -->

  32:         <s:VGroup height="100%">

  33:             <mx:Tree id="tree" width="100%" height="100%" />

  34:         </s:VGroup>

  35:

  36:         <s:VGroup width="100%" height="100%">

  37:             <!-- The editors will go here -->

  38:

  39:             <mx:Spacer height="100%" />

  40:

  41:             <mx:HRule width="100%" />

  42:

  43:             <!-- The buttons -->

  44:             <mx:ControlBar width="100%" horizontalAlign="center">

  45:                 <s:Button label="New group" />

  46:                 <s:Button label="New contact" />

  47:                 <s:Button label="Delete" />

  48:                 <s:Button label="Save" />

  49:             </mx:ControlBar>

  50:         </s:VGroup>

  51:     </s:HGroup>

  52:

  53:

  54: </s:Application>

Loading the contacts into the tree

Now its time to load some data into the tree.  Obviously at this point there isn’t any data to load so for the moment we’ll manually add some into the database so we have something to see.  Execute the following SQL against the contacts database to create some test data.  This creates two groups and three contacts, just like in the screenshots at the top of this section.

   1: INSERT INTO `contact` (`id`,`name`,`telephoneNumber`,`birthday`,`contactGroup_id`) VALUES

   2:  (1,'Arthur','01332 823636','1976-01-12',2),

   3:  (2,'Mum','07884 763623','1976-01-13',1),

   4:  (3,'Peter','0131 827 3625','1977-12-06',2);

   5:

   6: INSERT INTO `contactgroup` (`id`,`name`) VALUES

   7:  (1,'Family'),

   8:  (2,'Friends');

At this point we should talk about the concept of Flextrine’s entity repositories.  Every entity in your application has its own EntityRepository, so for our application we have one EntityRepository for ContactGroup and one for Contact.  Entity repositories perform a number of functions:

  • First and foremost entity repositories provide local storage for your entities.  Each EntityRepository has an attribute called entities which is an ArrayCollection containing the entities currently in existence in your application.
  • Secondly entity repositories make sure that there is only ever one instance of a particular entity in existence at any one time.
  • Finally entity repositories watch their entities for changes and mark them for updating when they change.

Add the following lines to the end of creationComplete() remembering to add import vo.ContactGroup to the top of the script tag.

   1: tree.dataProvider = em.getRepository(ContactGroup).entities;

   2: em.getRepository(ContactGroup).loadAll();

The first line sets the entities of the ContactGroup EntityRepository as the dataProvider of the tree.  Obviously at this point there are no entities in the ContactGroup repository, but Flextrine is very careful to respect Flex databinding throughout its lifecycle so in fact it doesn’t matter that entities is currently empty.  Any Flex component bound to the entities will automatically update themselves when the repository changes with no extra work required.

The second line calls the loadAll() method on the ContactGroup repository.  As you would expect this loads all the ContactGroups into the ContactsGroup repository and Flex databinding will take care of updating the tree once the load is complete.  By default Flextrine runs in EAGER mode, which means that when loading entities it will follow all associations and load any linked objects, so in fact loading the ContactGroups will also load all the Contacts.  Flextrine also supports LAZY loading which won’t automatically follow associations and requires you to to explicitly request unitialized entities; see Loading Associations for more details.

If you now run the application it will look like this.

Flextrine Contacts 3

We can see that the two ContactGroups are loading from the database and that Flex databinding has updated the tree automatically to reflect the loaded entities.  Unfortunately the tree doesn’t realise that it should be showing contacts as children of the contact groups, so we need to explicitly tell it so by adding a children attribute to ContactGroup.  Flextrine allows you to add logic to your entities by seperating Flextrine specific code into an ‘EntityBase’ class, and then creating an empty main entity class which you can ammend.  The idea behind this is that if you later update your entities you can replace the EntityBase without losing any functionality you added to the main entity class.

Open up vo/ContactGroup.as and add a getter function that simply returns the contacts:

   1: package vo {

   2:     import mx.collections.ArrayCollection;

   3:

   4:     [RemoteClass(alias="vo/ContactGroup")]

   5:     [Entity]

   6:     public class ContactGroup extends ContactGroupEntityBase {

   7:

   8:         public function get children():ArrayCollection {

   9:             return contacts;

  10:         }

  11:

  12:     }

  13:

  14: }

We also want the labels in the tree to show the name property of both ContactGroup and Contact so add labelField=”name” to the Tree component in Main.mxml:

   1: <mx:Tree id="tree" width="100%" height="100%" labelField="name" />

Now running the application should show the following!

contacts4

Lets see how we can create new entities.

Flextrine Tutorial – CRUD in a simple Flex 4 address book: Creating the database schema

Introduction
Setting up the server
Creating the entities
Creating the database schema
Loading the entities
Creating new entities
Deleting entities
Updating entities
Conclusion

Once we have defined the entities in the entities directory of the Flextrine server component it is very simple to create the appropriate database schema.

Creating the database schema

Browse to http://localhost/flextrinemanager (or whatever URL you pointed to the manager directory).  You should see a screen like this:

Flextrine Manager 1

Enter the URL of the Flextrine server side component (http://localhost/contacts) in the FLEXTRINE PROJECT URL input and Click to refresh.  The Flextrine manager will examine your project and update the manager to show the entities and database.  Now click on Create schema to automatically generate the appropriate tables in the database.  The manager should now look like this:

Flextrine Manager 2

Under the hood Doctrine 2 has parsed the annotations in ContactGroup and Contact and has determined the appropriate tables and columns that will be required to persist the objects.  Although you will never need to edit the schema manually, the following SQL is what was actually executed when you clicked CREATE SCHEMA.  Notice that Doctrine enforces referential integrity through MySQL constraints so that, for example, you cannot delete a ContactGroup which has any Contacts referring to it.

   1: CREATE TABLE  `contact`.`contactgroup` (

   2:   `id` int(11) NOT NULL AUTO_INCREMENT,

   3:   `name` varchar(100) NOT NULL,

   4:   PRIMARY KEY (`id`)

   5: );

   6:

   7: CREATE TABLE  `contact`.`contact` (

   8:   `id` int(11) NOT NULL AUTO_INCREMENT,

   9:   `name` varchar(80) NOT NULL,

  10:   `telephoneNumber` varchar(50) DEFAULT NULL,

  11:   `birthday` date DEFAULT NULL,

  12:   `contactGroup_id` int(11) DEFAULT NULL,

  13:   PRIMARY KEY (`id`),

  14:   KEY `contactGroup_id` (`contactGroup_id`),

  15:   CONSTRAINT `contact_ibfk_1` FOREIGN KEY (`contactGroup_id`) REFERENCES `contactgroup` (`id`)

  16: );

Now that the schema has been created you can use UPDATE SCHEMA whenever you add/remove entities or attributes within entities to update the schema without losing any data that is already in the database.  This gives you a very efficient workflow as your entities expand over the lifetime of a project.

We now have everything we need in the Flextrine server side component and in the database.  Its time to start writing some Flex code!

Flextrine Tutorial – CRUD in a simple Flex 4 address book: Introduction

Introduction
Setting up the server
Creating the entities
Creating the database schema
Loading the entities
Creating new entities
Deleting entities
Updating entities
Conclusion

UPDATED FOR FLEXTRINE 0.6.5!

After numerous requests I have finally sat myself down to write a basic tutorial for using Flextrine in a practical and simple Flex application.

What is Flextrine?

In a sentence, Flextrine is an open-source solution for reading and writing AS3 objects to and from a remote database.  Flextrine doesn’t really do anything that you couldn’t do by hand using PHP and AS3 code, but it removes most of the grunt work and standardises client-server database interactions.  All being well, database aware Flex applications coded using Flextrine are shorter, more readable and more maintainable.

Documentation for Flextrine is available in its Google Code wiki and its definitely worth having a skim through before beginning the tutorial.

What shall we build?

In this tutorial we are going to demonstrate some of Flextrine’s functionality by building a simple online contacts manager.  The application will allow us to create, edit and delete contacts, each of which simply have names and telephone numbers.  In order to demonstrate some of Flextrine’s associations we will also allow the user to put contacts into groups.

Note that the purpose of this tutorial is to demonstrate Flextrine rather than Flex, so we won’t be using any frameworks (apart from Flex itself) and where there is a choice between an elegant programming solution and just keeping it simple we’ll be going for the simpler option 🙂

Requirements

To run through this tutorial you will need the following:

  • Flex SDK 4 (free from Adobe)
  • A nice Flex IDE – I personally use the wonderful FlashDevelop, but Flash Builder 4 will do just as well
  • A web server running PHP 5.3+ and MySQL (WAMP for Windows and MAMP for OSX are good choices)
  • Download the complete source code for the tutorial and save yourself tedious typing!  This does not include the Flextrine AS3 code so you will need to add the source code or SWC to your classpath manually before compiling.

Lets begin by installing Flextrine and its dependencies.

Flextrine 0.5.3 released

As we approach the official release date I have made available another version of Flextrine.  This release adds no new functionality but upgrades various elements of the codebase to be compatible with the trunk of Doctrine 2.  If you are running against 2.0.0BETA2 this upgrade will have no effect, but if you are running against the trunk of Doctrine (via git) you require 0.5.3.

Flextrine 0.5.3 remains fully compatible with all previous versions of Doctrine 2.

Flextrine is available from www.flextrine.com