Flextrine 0.7.3 released

The Flextrine releases are flying out hard and fast!  This release gives another batch of bug fixes, enhanced functionality in various areas, better error reporting and lots more API documentation.  Flash on the Beach is just around the corner, and I’m hoping that my presentation will bring a new batch of users into the Flextrine camp.

Pick it up at www.flextrine.com

SPOILER ALERT (only if you are coming to Flash on the Beach) – here is a sneak preview of my slides for the presentation http://prezi.com/6vrft-2h4sjy/flextrine/

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: Updating entities

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

Once an entity is in an EntityRepository (either because it was loaded from the database or it was persisted) it is known as a MANAGED entity.  This means that Flextrine will constantly watch the entity to see if anything changes, and if so will mark the entity for updating on the next flush().

Therefore updating entities is extremely simple – as long as the entity is managed there is literally nothing to do 🙂

Lets create an editor for the ContactGroups (in the same directory as Main.mxml):

ContactGroupEditor.mxml

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

   2: <s:Group 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:     

   6:     <fx:Script>

   7:         <![CDATA[

   8:         import vo.ContactGroup;

   9:         

  10:         [Bindable]

  11:         public var contactGroup:ContactGroup;

  12:         

  13:         ]]>

  14:     </fx:Script>

  15:     

  16:     <mx:Form labelWidth="150" width="100%" height="100%">

  17:         

  18:         <mx:FormHeading label="Edit group" />

  19:         

  20:         <mx:FormItem label="Name">

  21:             <s:TextInput text="@{contactGroup.name}" />

  22:         </mx:FormItem>

  23:         

  24:     </mx:Form>

  25:     

  26: </s:Group>

The component takes a contactGroup and provides a TextInput that edits its name attribute using Flex 4 two-way databinding.  In fact you need to be careful with two-way databinding on some components (e.g. DateChooser) as it can cause unnecessary updates, but it works fine for Spark’s TextInput.

Now we need to add the ContactGroupEditor into Main.mxml:

   1: ...

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

   3:             <!-- The editors -->

   4:             <local:ContactGroupEditor contactGroup="{tree.selectedItem as ContactGroup}" enabled="{tree.selectedItem is ContactGroup}" />

   5: ...

And that’s it for the group editor.  When we select a ContactGroup in the tree, the ContactGroupEditor becomes enabled, and the selected item is passed to the editor’s contactGroup attribute.  Flex updates the contactGroup’s name attribute when we change it in the editor and Flextrine automatically picks up on the change and marks the entity for updating.  On the next flush() the changes will be written to the database.

Now for the ContactEditor.

ContactEditor.mxml

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

   2: <s:Group 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:     

   6:     <fx:Script>

   7:         <![CDATA[

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

   9:         import vo.ContactGroup;

  10:         import vo.Contact;

  11:         

  12:         [Bindable]

  13:         public var contact:Contact;

  14:         

  15:         ]]>

  16:     </fx:Script>

  17:     

  18:     <mx:Form labelWidth="150" width="100%" height="100%">

  19:         

  20:         <mx:FormHeading label="Edit contact" />

  21:         

  22:         <mx:FormItem label="Name">

  23:             <s:TextInput text="@{contact.name}" />

  24:         </mx:FormItem>

  25:         

  26:         <mx:FormItem label="Telephone number">

  27:             <s:TextInput text="@{contact.telephoneNumber}" />

  28:         </mx:FormItem>

  29:         

  30:         <mx:FormItem label="Birthday">

  31:             <mx:DateChooser selectedDate="{contact.birthday}" change="contact.birthday = event.currentTarget.selectedDate" />

  32:         </mx:FormItem>

  33:         

  34:         <mx:FormItem label="Group">

  35:             <s:DropDownList dataProvider="{EntityManager.getInstance().getRepository(ContactGroup).entities}"

  36:                             selectedItem="{contact.contactGroup}"

  37:                             change="contact.setContactGroup(event.currentTarget.selectedItem);"

  38:                             labelField="name" />

  39:         </mx:FormItem>

  40:         

  41:     </mx:Form>

  42:     

  43: </s:Group>

The contact editor is marginally more complicated, but still fairly simple.  A few points:

  • Note is that as mentioned above we don’t use two-way databinding on any component apart from TextInput.
  • Although it is perfectly legal to retrieve the singleton EntityManager in the ContactEditor as we have done in the DropDownList dataProvider, in a real application we probably wouldn’t do this as it breaks encapsulation.  I’ve done it here for the sake of simplicity 🙂

Finally we need to add the editor to Main.mxml:

   1: ...

   2:  

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

   4:     <!-- The editors -->

   5:     <local:ContactGroupEditor contactGroup="{tree.selectedItem as ContactGroup}" enabled="{tree.selectedItem is ContactGroup}" />

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

   7:     <local:ContactEditor contact="{tree.selectedItem as Contact}" enabled="{tree.selectedItem is Contact}" />

   8: ...

An that’s it!  A simple but fully functioning, database aware Flex application.

And now, the thrilling conclusion.

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

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

Deleting entities is very simple.  Update the delete button MXML tag to call onDeleteClick() when clicked, and to only be enabled if there is a selection in the tree.

   1: <s:Button label="Delete" click="onDeleteClick()" enabled="{tree.selectedItem != null}" />

And implement the onDeleteClick() method:

   1: private function onDeleteClick():void {

   2:     em.remove(tree.selectedItem);

   3:     

   4:     if (tree.selectedItem is Contact)

   5:         tree.selectedItem.contactGroup.removeContact(tree.selectedItem);

   6:     

   7: }

Notice that we maintain the bi-directional association if the deleted item is a contact by removing it from its associated contactGroup.

And that’s it :)  The entity will be removed from its entity repository (updating the tree via databinding) and on the next flush() it will be removed from the database.

The final step in our little address book is to allow the user to update existing 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: Setting up the server

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

Before using Flextrine you need to do some groundwork to get your project ready.

  1. Download the latest version of Flextrine from http://code.google.com/p/flextrine2/downloads/list
  2. Install the Flextrine manager.  This is as simple as copying the manager directory from the Flextrine download into a web-accessible directory.  For the purposes of the tutorial I will assume that you have set the URL pointing at this document root as http://localhost/flextrinemanager.  Note that you will require mod_rewrite to be enabled on your webserver for the manager to function correctly.
  3. Install the Flextrine server side libraries.  These are contained in the flextrine/web/lib directory of the the Flextrine download.  All you need to do to install these is to copy flextrine/web/lib to a directory in your PHP include_path, or ammend the include_path to include the flextrine/web/lib directory.  Note that if you don’t want to change your include_path you can set it explicitly after the next step by uncommenting the $flextrineIncludePAth line in config.php of your project (see http://code.google.com/p/flextrine2/wiki/GettingStarted for more details).
  4. Install the latest version of Doctrine 2 from http://www.doctrine-project.org/projects/orm/download.  Doctrine 2 is the technology that Flextrine is based upon and required for its operation.  The easiest way to install Doctrine is to merely extract the package into flextrine/web/lib as this is already in your PHP include_path.  Alternatively you can add a new entry to your include_path pointing to Doctrine.
  5. Create an empty server-side Flextrine project.  The Flextrine download contains a blank project in flextrine/web/flextrineproject which will be your starting point.  Copy this to a new directory on your machine and make this directory web accessible.  For the purposes of this tutorial I will assume that you have set the URL pointing to this directory as http://localhost/contacts and will refer to the directory as the Flextrine server side component.
  6. Create a new MySQL database called contacts.
  7. In your Flextrine server side component open up config.php and set the database connection options in the $connectionOptions variable.

Note that next time you start a new Flextrine projects you only need to do steps 5 – 6 as steps 1 – 4 only need to be done once.

Now we are ready to use Flextrine!  The next step is to create some entities.

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

Flextrine 0.5 released!

I have released the first public version of Flextrine.  Its actually pretty feature rich, and I will be focusing mainly on bug fixes and stability as reports start to come back from the community leading up to the main release on 1st September.

Major features that have made it into 0.5:

  • Entities and the entity manager
  • Single and collection associations
  • The Flextrine Manager
  • AS3 code generation
  • Lazy loading, requireOne and requireMany
  • Full Flex databinding
  • DQL queries

Flextrine can be downloaded from Google Code at http://code.google.com/p/flextrine2/  Please try it out and log any issue you might find in Google Code.