Adobe Flex – Presentation & Cookbook
Here is a little thing that I made up for people using Flex/Flash and amfphp a little cheat sheet to use as a reference.
I have two different versions of this:
- Is use without any framework and without a services-config.xml file in the compiler.
- Second version is for use with the Cairngorm Framework.
These example are snippets from my Flash Remoting presentation and Snippr Air application. Source files will be provided at the end.
Table Of Contents:
- Installation Setup
- Service Proxy for managing calls
- Value Objects
- Model Locator
- Getting Data
- Sending Data
- Removing Data
- Views
- Source
Amfphp Installation Setup
Server folder structure:
Snippets MySQL Table:
1: CREATE TABLE `snippets` (
2: `snippet_id` int(11) NOT NULL auto_increment,
3: `snippet_title` varchar(255) NOT NULL,
4: `snippet_code` text NOT NULL,
5: `snippet_type` varchar(3) default 'as',
6: `snippet_created` timestamp NULL default NULL,
7: `snippet_user` varchar(200) NOT NULL,
8: PRIMARY KEY (`snippet_id`)
9: ) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=latin1
Service Proxy
Here is how you create a Service Proxy file that handles all of your calls, this makes all calls to and from amfphp really easy.
Use in SnipprService.as
1: package com.jonniespratley.snippr.services
2: {
3: import com.jonniespratley.snippr.model.ModelLocator;
4: import com.jonniespratley.snippr.vo.SnippetVO;
5:
6: import flash.net.NetConnection;
7: import flash.net.Responder;
8:
9: import mx.collections.ArrayCollection;
10: import mx.controls.Alert;
11:
12: /**
13: * This file is for use without! using the services-config.xml file
14: * @author Jonnie
15: *
16: */
17: public class SnipprService
18: {
19: private static var _service:NetConnection;
20: private var model:ModelLocator = ModelLocator.getInstance();
21:
22: //Here we are creating a new connection to our amfphp service, when this is instantiated, it connects to our service
23: public function SnipprService()
24: {
25: _service = new NetConnection();
26: _service.connect( "http://YOURSERVER.COM/amfphp/gateway.php" );
27: }
28:
29:
30: /* ***************************************
31: *** Service Calls
32: *****************************************/
33:
34: //Here we are calling the getSnippets on our server (amfphp) and setting the result and fault handlers
35: public function getSnippets():void
36: {
37: _service.call( "snippr.SnipprService.getSnippets", new Responder( snippetResultHandler, snipprFaultHandler ) );
38: }
39:
40: //We take one argument here, and that is a snippet, because our server (amfphp) is expecting a snippetVO
41: public function saveSnippet( snippet:SnippetVO ):void
42: {
43: _service.call( "snippr.SnipprService.saveSnippet", new Responder( snippetSavedHandler, snipprFaultHandler ), snippet );
44: }
45:
46: //We take one argument here, and that is the id of the snippet we are wanting to remove
47: public function removeSnippet( snippet_id:uint ):void
48: {
49: _service.call( "snippr.SnipprService.removeSnippet", new Responder( snippetRemoveHandler, snipprFaultHandler ), snippet_id );
50: }
51:
52:
53: /* ***************************************
54: *** Result and Fault Handlers
55: *****************************************/
56:
57: //Here we are handling the result coming back as an array of snippets, then we add our snippets to our model
58: private function snippetResultHandler( data:Array ):void
59: {
60: model.snippetCollection = initVO( data );
61: }
62:
63: //Helper for the result
64: private function initVO( resultArray:Array ):ArrayCollection
65: {
66: var tempArray:ArrayCollection = new ArrayCollection();
67:
68: for ( var s:String in resultArray )
69: {
70: tempArray.addItem( new SnippetVO( resultArray[s] ) );
71:
72: }
73: return tempArray;
74: }
75:
76: //Here we are handling the result and adding it to the value of serviceResponse in our model
77: private function snippetSavedHandler( data:Object ):void
78: {
79: ModelLocator.getInstance().serviceResponse = data.toString();
80: }
81:
82: /*
83: Here we are handling the result that is being returned, which will be the id of the removed snippet, and
84: removing it from our model, at the snippet index
85: */
86: private function snippetRemoveHandler( data:Object ):void
87: {
88: getSnippets();
89: }
90:
91: //Here we are alerting the user that there was an error connection to our server
92: private function snipprFaultHandler( fault:Object ):void
93: {
94:
95: Alert.show( "There was an error connecting to the server.", "Snippr Service Error" );
96: }
97: }
98: }
Use in SnipprService.php:
1: <?php
2: /** *******************************************************************
3: * Copyright (c) 2008 Jonnie Spratley. All Rights Reserved.
4: *
5: * THE SOFTWARE IS PROVIDED "AS" IS, WITHOUT WARRANTY OF ANY KIND,
6: * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
7: * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
8: * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
9: * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
10: * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
11: * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12: *
13: * @author Jonnie Spratley
14: * @contact jonniespratley@gmail.com
15: * @internal
16: ******************************************************************* */
17:
18: class SnipprService
19: {
20: //Specify our output temp directory
21: var $output_dir = "screenshots";
22: //Specify our output url
23: var $server_url = "http://snippr.jonniespratley.com/";
24: //Specify our table name
25: private $table = "snippets";
26:
27: public function SnipprService()
28: {
29: mysql_connect("localhost", "spratley_guest", "guest");
30: mysql_select_db("spratley_snippr") ;
31: }
32:
33:
34: private function mapRecordSet( $recordset )
35: {
36: require_once( "../vo/SnippetVO.php" );
37: $list = array();
38:
39: while( $data = mysql_fetch_array( $recordset ) )
40: {
41: $vo = new SnippetVO();
42: $vo->mapObject( $data );
43: array_push( $list, $vo );
44: }
45: return $list;
46: }
47:
48:
49: public function getSnippets()
50: {
51: //We must specify our vo, because we need to map correctly
52: require_once( "../vo/SnippetVO.php" );
53:
54: $sql = mysql_query( "SELECT * FROM ". $this->table. "" );
55:
56: $result = array();
57:
58: while( $snip = mysql_fetch_array( $sql ) )
59: {
60: //Create a new snippet vo
61: $snippet = new SnippetVO();
62: $snippet->snippet_id = $snip[snippet_id];
63: $snippet->snippet_title = $snip[snippet_title];
64: $snippet->snippet_code = $snip[snippet_code];
65: $snippet->snippet_type = $snip[snippet_type];
66: $snippet->snippet_created = $snip[snippet_created];
67: $snippet->snippet_user = $snip[snippet_user];
68: //Result is a snippet
69: $result[] = $snippet;
70: }
71: //Print out the result
72: return $result;
73: }
74:
75: //This is used for returning the created or updated snippet for flex
76: public function getOne( $id )
77: {
78: $rs = mysql_query( "SELECT * FROM ".$this->table." WHERE snippet_id = ".$id );
79: //Map the recordset to our vo
80: $list = $this->mapRecordSet( $rs );
81: //Return our vo
82: return $list[ 0 ];
83: }
84:
85: //Creates a new snippet
86: public function saveSnippet( $snippet )
87: {
88: require_once( "../vo/SnippetVO.php" );
89: //Check to see if the snippet has an id of 0
90: if ( $snippet[snippet_id] == 0 )
91: {
92: $query = "INSERT INTO ".$this->table."
93: ( snippet_title,
94: snippet_code,
95: snippet_type,
96: snippet_created,
97: snippet_user )
98: VALUES (
99: '".mysql_real_escape_string($snippet[snippet_title])."',
100: '".mysql_real_escape_string($snippet[snippet_code])."',
101: '".mysql_real_escape_string($snippet[snippet_type])."',
102: '".mysql_real_escape_string($snippet[snippet_created])."',
103: '".mysql_real_escape_string($snippet[snippet_user])."')";
104: if( !mysql_query( $query ) )
105: {
106: return false;
107: }
108: return $this->getOne( mysql_insert_id() );
109:
110: } else {
111: $id = $snippet[snippet_id];
112:
113: $query = "UPDATE ".$this->table." SET
114: snippet_title = '".mysql_real_escape_string($snippet[snippet_title])."',
115: snippet_code = '".mysql_real_escape_string($snippet[snippet_code])."',
116: snippet_type = '".mysql_real_escape_string($snippet[snippet_type])."',
117: snippet_created = '".mysql_real_escape_string($snippet[snippet_created])."',
118: snippet_user = '".mysql_real_escape_string($snippet[snippet_user])."'
119:
120: WHERE snippet_id =". $id;
121:
122: if( !mysql_query( $query ) )
123: {
124: return false;
125: }
126: //Return the created snippet
127: return $this->getOne( $id );
128: }
129: }
130:
131: public function removeSnippet($id)
132: {
133: $sql = mysql_query( "DELETE FROM ".$this->table." WHERE snippet_id = ".$id );
134:
135: if( !$sql )
136: {
137: // trigger_error("Unable to delete Snippets", E_USER_ERROR);
138: return "There was an error removing this snippet";
139: }
140: else return $id;
141: }
142:
143: /** *******************************************************************************
144: Save image from the given bytearray and return the path of the saved image
145: ***********************************************************************************/
146: public function takeScreenshot( $byteArray, $filename, $compressed = false )
147: {
148: if( !file_exists( $this->output_dir ) || !is_writeable( $this->output_dir ) )
149: trigger_error ( "Please create a directory first with write access", E_USER_ERROR );
150:
151: $data = $byteArray->data;
152:
153: if( $compressed )
154: {
155: if( function_exists( gzuncompress ) )
156: {
157: $data = gzuncompress( $data );
158: } else {
159: trigger_error ( "GZip method does not exists, please send uncompressed data", E_USER_ERROR );
160: }
161: }
162: //Put the File in the Directory, and Rename it, what the User wanted the Name to be.
163: file_put_contents( $this->output_dir . "/$filename", $data );
164:
165: return $this->server_url . $this->output_dir . "/$filename";
166: }
167: }
168: ?>
The Model Locator
Here is our ModelLocator.as file that will hold all of our data.
1: /** *******************************************************************
2: * Snippr AIR
3: * Copyright (c) 2008 Jonnie Spratley. All Rights Reserved.
4: *
5: * THE SOFTWARE IS PROVIDED "AS" IS, WITHOUT WARRANTY OF ANY KIND,
6: * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
7: * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
8: * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
9: * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
10: * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
11: * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12: *
13: * @author Jonnie Spratley
14: * @contact jonniespratley@gmail.com
15: * @internal
16: ******************************************************************* */
17: package com.jonniespratley.snippr.model
18: {
19: import com.adobe.cairngorm.model.IModelLocator;
20: import com.jonniespratley.snippr.vo.SnippetVO;
21:
22: import mx.collections.ArrayCollection;
23:
24: /**
25: * The Model Locator pattern is a singleton and was created purely
26: * to be used with Flex/Air application development. In this case,
27: * a singleton is a design pattern that allows for only one
28: * instance of the Model Locator to be present within your a
29: * application's memory. Any data that you think is required to live
30: * in the application's state should be stored inside the Model Locator.
31: * The Model Locator creates a central area where all the states
32: * can be held in your Flex/Air application. This allows the view
33: * components to bind to the model or state of the application
34: * and keep everything up to date.
35: *
36: */
37:
38: [Bindable]
39: public final class ModelLocator implements IModelLocator
40: {
41: /**
42: * Defines the Singleton instance of the Application ModelLocator
43: */
44: private static var instance:ModelLocator;
45:
46: public function ModelLocator()
47: {
48: if( instance != null ) throw new Error( "Error: Singletons can only be instantiated via getInstance() method!" );
49:
50: ModelLocator.instance = this;
51: }
52:
53: /**
54: * Returns the Singleton instance of the Application ModelLocator
55: */
56: public static function getInstance():ModelLocator
57: {
58: if( instance == null ) instance = new ModelLocator();
59:
60: return instance;
61: }
62:
63: // *********** Public Variables that our views are going to bind to **************
64:
65: /* Snippet Collection for all lists/datagrids */
66: public var snippetCollection:ArrayCollection;
67:
68: /* The selected snippet */
69: public var selectedSnippet:SnippetVO;
70:
71: public var serviceResponse:String = "";
72:
73: // ***************** Public Static Variables for Work View States *************
74: public var workflowState:uint = 0;
75: public static const LOGIN_SCREEN:uint = 0;
76: public static const WELCOME_SCREEN:uint = 1;
77: }
78: }
Value Objects
Code for both server and client are provided as follows.
Use in SnippetVO.as
1: package com.jonniespratley.snippr.vo
2: {
3: [RemoteClass(alias="vo.SnippetVO")]
4:
5: /**
6: * VOs are used to create a layer of business objects that can be
7: * transferred between tiers, instead of using records, results sets, and datasets.
8: */
9: [Bindable]
10: public class SnippetVO
11: {
12: public var snippet_id:int;
13: public var snippet_title:String;
14: public var snippet_code:String;
15: public var snippet_type:String;
16: public var snippet_created:String;
17: public var snippet_user:String;
18:
19: /**
20: * Helper function for building the data.
21: * @param source
22: */
23: public function SnippetVO( source:Object = null )
24: {
25: if ( source != null )
26: {
27: for ( var item:String in source )
28: {
29: try
30: {
31: this[item] = source[item];
32: }
33: catch ( error:Error )
34: {
35: throw new Error( "SnippetVO: " + error );
36: }
37: }
38: }
39: }
40: }
41: }
Use in SnippetVO.php
1: <?php
2: /** *******************************************************************
3: * @author Jonnie Spratley
4: * @contact jonniespratley@gmail.com
5: * @internal
6: ******************************************************************* */
7: class SnippetVO
8: {
9: //AMFPHP only
10: var $_explicitType="com.jonniespratley.snippr.vo.SnippetVO";
11:
12: public $snippet_id;
13: public $snippet_title;
14: public $snippet_code;
15: public $snippet_type;
16: public $snippet_created;
17: public $snippet_user;
18:
19: public function SnippetVO(){}
20:
21: //Maps the data to the specific table names
22: public function mapObject( $data )
23: {
24: $this->snippet_id = $data[snippet_id];
25: $this->snippet_title = $data[snippet_title];
26: $this->snippet_code = $data[snippet_code];
27: $this->snippet_type = $data[snippet_type];
28: $this->snippet_created = $data[snippet_created];
29: $this->snippet_user = $data[snippet_user];
30: }
31: }
32: ?>
Getting Data
Code for both server and client are provided as follows.
1: //Here we are calling the getSnippets on our server (amfphp) and setting the result and fault handlers
2: public function getSnippets():void
3: {
4: var _service:NetConnection = new NetConnection();
5: _service.connect( "http://localhost/Snippr/amfphp/gateway.php" );
6: _service.call( "snippr.SnipprService.getSnippets",
7: new Responder( snippetResultHandler, snipprFaultHandler ) );
8: }
1: public function getSnippets()
2: {
3: //We must specify our vo, because we need to map correctly
4: require_once( "../vo/SnippetVO.php" );
5:
6: $sql = mysql_query( "SELECT * FROM ". $this->table. "" );
7:
8: $result = array();
9:
10: while( $snip = mysql_fetch_array( $sql ) )
11: {
12: //Create a new snippet vo
13: $snippet = new SnippetVO();
14: $snippet->snippet_id = $snip[snippet_id];
15: $snippet->snippet_title = $snip[snippet_title];
16: $snippet->snippet_code = $snip[snippet_code];
17: $snippet->snippet_type = $snip[snippet_type];
18: $snippet->snippet_created = $snip[snippet_created];
19: $snippet->snippet_user = $snip[snippet_user];
20: //Result is a snippet
21: $result[] = $snippet;
22: }
23: //Print out the result
24: return $result;
25: }
To Save Data
Code for both server and client are provided as follows.
Use in SnippetForm.mxml
1: /*
2: The saveSnippet function that gets called when there is no errors in our form
3: This is one function that is going to handle both creating a new snippet, and
4: updating an existing one. Our server side php script says that if the snippetVO[snippet_id]
5: is equal to 0, then go ahead and insert it as a new snippet. But if the snippetVO[snippet_id]
6: is not set to 0, then update that snippet where the recieved id is equal to the id we are updating.
7: */
8: private function saveSnippet():void
9: {
10: /* If the selectedSnippet is empty create a new snippet */
11: if ( model.selectedSnippet == null )
12: {
13: var createS:SnippetVO = new SnippetVO();
14: createS.snippet_id = 0;
15: createS.snippet_title = txt_title.text;
16: createS.snippet_code = txt_code.text;
17: createS.snippet_user = txt_author.text;
18: createS.snippet_type = txt_type.text;
19:
20: /* Service proxy */
21: service.saveSnippet( createS );
22:
23: } else {
24: /* Set the snippet id to the value of the selected snippet_id */
25: var updateS:SnippetVO = new SnippetVO();
26: updateS.snippet_id = model.selectedSnippet.snippet_id;
27: updateS.snippet_title = txt_title.text;
28: updateS.snippet_code = txt_code.text;
29: updateS.snippet_user = txt_author.text;
30: updateS.snippet_type = txt_type.text;
31:
32: service.saveSnippet( updateS );
33:
34: }
35: /* Do nothing */
36: }
Use in SnippetSerivce.php
1: //Saves a snippet if the id == 0, otherwise it updates it
2: public function saveSnippet( $snippet )
3: {
4: require_once( "../vo/SnippetVO.php" );
5:
6: //Check to see if the snippet has an $snippet[snippet_id] == 0 from Flex
7: if ( $snippet[snippet_id] == 0 )
8: {
9: $query = "INSERT INTO ".$this->table."
10: ( snippet_title,
11: snippet_code,
12: snippet_type,
13: snippet_created,
14: snippet_user )
15: VALUES (
16: '".mysql_real_escape_string($snippet[snippet_title])."',
17: '".mysql_real_escape_string($snippet[snippet_code])."',
18: '".mysql_real_escape_string($snippet[snippet_type])."',
19: '".mysql_real_escape_string($snippet[snippet_created])."',
20: '".mysql_real_escape_string($snippet[snippet_user])."')";
21: if( !mysql_query( $query ) )
22: {
23: //Return False
24: return false;
25: }
26: //Return the new snippet
27: return $this->getOne( mysql_insert_id() );
28: } else {
29: $id = $snippet[snippet_id];
30: //Set up the query
31: $query = "UPDATE ".$this->table." SET
32: snippet_title = '".mysql_real_escape_string($snippet[snippet_title])."',
33: snippet_code = '".mysql_real_escape_string($snippet[snippet_code])."',
34: snippet_type = '".mysql_real_escape_string($snippet[snippet_type])."',
35: snippet_created = '".mysql_real_escape_string($snippet[snippet_created])."',
36: snippet_user = '".mysql_real_escape_string($snippet[snippet_user])."'
37: WHERE snippet_id =". $id;
38: //If there was a problem
39: if( !mysql_query( $query ) )
40: {
41: //Return false
42: return false;
43: }
44: //Return the created snippet
45: return $this->getOne( $id );
46: }
47: }
To Delete Data
Code for both server and client are provided as follows.
Use in SnippetList.mxml
1: //Display an alert to confirm the delete
2: private function removeSnippet():void
3: {
4: Alert.show( "Are you sure?", "Remove Snippet", 3, null, removeSnippetAlertHandler );
5: }
6:
7: //If they click yes in the alert then call the removeSnippet method passing the selected snippet as the id
8: private function removeSnippetAlertHandler( event:CloseEvent ):void
9: {
10: if ( event.detail == Alert.YES )
11: {
12: service.removeSnippet( lt_snippets.selectedItem.snippet_id );
13: }
14: }
Use in SnippetService.php
1: //Remove a snippet by the id
2: public function removeSnippet($id)
3: {
4: $sql = mysql_query( "DELETE FROM ".$this->table." WHERE snippet_id = ".$id );
5:
6: if( !$sql )
7: {
8: // trigger_error("Unable to delete Snippets", E_USER_ERROR);
9: return "There was an error removing this snippet";
10: }
11: else return $id;
12: }
Views
SnippetForm.mxml
1: <?xml version="1.0" encoding="utf-8"?>
2: <!--SnippetFormProxyService-->
3: <mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" width="100%" height="100%"
4: creationComplete="init()"
5: xmlns:components="com.jonniespratley.snippr.view.components.*">
6:
7: <mx:Script>
8: <![CDATA[
9: import mx.validators.Validator;
10: import mx.controls.Alert;
11: import mx.rpc.events.FaultEvent;
12: import mx.rpc.events.ResultEvent;
13:
14: import com.jonniespratley.snippr.vo.SnippetVO;
15: import com.jonniespratley.snippr.model.ModelLocator;
16: import com.jonniespratley.snippr.services.SnipprService;
17:
18: /* Out Model so we can bind to the selectedSnippet */
19: [Bindable] private var model:ModelLocator = ModelLocator.getInstance();
20:
21: /* Our validation array to hold the values of our validators */
22: [Bindable] private var validators:Array = new Array();
23:
24: /* Our custom remote proxy service for connection to amfphp */
25: private var service:SnipprService;
26:
27: /*
28: On init we create a new instance of our service proxy
29: We alway set our validators to our validator array
30: */
31: private function init():void
32: {
33: service = new SnipprService();
34:
35: validators = [ titleV, authorV, codeV, typeV ];
36: }
37:
38: /*
39: When the save button is clicked instead of sending the data right away
40: we first check it to see if it is indeed valid. If our validation array
41: is empty, then we can go ahead and send our value object to amfphp, other
42: wise we need to alert the user that there are some errors in the form
43: */
44: private function checkForm():void
45: {
46: var vals:Array = new Array();
47: vals = Validator.validateAll( validators );
48:
49: //If no errors
50: if ( vals.length == 0 )
51: {
52: saveSnippet();
53: //cleanForms();
54: } else {
55: Alert.show( "Please correct invalid form entries", "Validation Error" );
56: }
57: }
58:
59: /* Clears all form inputs, and resets the selected index of the snippet list */
60: private function cleanForms():void
61: {
62: //Set the model.selectedSnippet to null, so we dont have any fields used up
63: //model.selectedSnippet = null;
64: txt_title.text = "";
65: txt_author.text = "";
66: txt_code.text = "";
67: txt_type.text = "";
68: }
69:
70: /*
71: The saveSnippet function that gets called when there is no errors in our form
72: This is one function that is going to handle both creating a new snippet, and
73: updating an existing one. Our server side php script says that if the snippetVO[snippet_id]
74: is equal to 0, then go ahead and insert it as a new snippet. But if the snippetVO[snippet_id]
75: is not set to 0, then update that snippet where the recieved id is equal to the id we are updating.
76: */
77: private function saveSnippet():void
78: {
79: /* If the selectedSnippet is empty create a new snippet */
80: if ( model.selectedSnippet == null )
81: {
82: var createS:SnippetVO = new SnippetVO();
83: createS.snippet_id = 0;
84: createS.snippet_title = txt_title.text;
85: createS.snippet_code = txt_code.text;
86: createS.snippet_user = txt_author.text;
87: createS.snippet_type = txt_type.text;
88:
89: /* Service proxy */
90: service.saveSnippet( createS );
91:
92: } else {
93: /* Set the snippet id to the value of the selected snippet_id */
94: var updateS:SnippetVO = new SnippetVO();
95: updateS.snippet_id = model.selectedSnippet.snippet_id;
96: updateS.snippet_title = txt_title.text;
97: updateS.snippet_code = txt_code.text;
98: updateS.snippet_user = txt_author.text;
99: updateS.snippet_type = txt_type.text;
100:
101: service.saveSnippet( updateS );
102:
103: }
104: /* Do nothing */
105: }
106:
107: /* ******************* MXML Result and Fault handlers ********************* */
108: private function onResult( event:ResultEvent ):void
109: {
110: Alert.show(event.result.toString(), "Success" );
111: }
112:
113: private function onFault( event:FaultEvent ):void
114: {
115: Alert.show( event.fault.faultString );
116: }
117:
118:
119:
120: ]]>
121: </mx:Script>
122:
123: <!--MXML Remote Object-->
124:
125: <!--Remote Object-->
126: <mx:RemoteObject id="snipprSvc" source="snippr.SnipprService"
127: destination="amfphp"
128: showBusyCursor="true"
129: fault="onFault( event )">
130: <!--Methods that are on our server-->
131: <mx:method name="saveSnippet" result="onResult( event )"/>
132: <mx:method name="getSnippets" result="onResult( event )"/>
133: </mx:RemoteObject>
134:
135: <mx:ApplicationControlBar width="100%" styleName="formBar">
136: <mx:HBox width="100%" verticalAlign="middle">
137: <mx:Label text="Author:" fontWeight="bold"/>
138: <mx:TextInput id="txt_author"
139: text="{ model.selectedSnippet.snippet_user }"
140: width="100%"/>
141: </mx:HBox>
142: </mx:ApplicationControlBar>
143:
144: <mx:ApplicationControlBar width="100%" styleName="formBar">
145: <mx:HBox width="100%" verticalAlign="middle">
146:
147: <mx:Label text="Title:" fontWeight="bold"/>
148: <mx:TextInput id="txt_title"
149: text="{ model.selectedSnippet.snippet_title }"
150: width="100%"/>
151:
152: <mx:Label text="Type:" fontWeight="bold"/>
153: <mx:TextInput id="txt_type"
154: text="{ model.selectedSnippet.snippet_type }"
155: width="100%"/>
156:
157: <mx:Button id="btn_clear"
158: click="cleanForms()"
159: label="Clear"/>
160: <mx:Button id="btn_save"
161: click="checkForm()"
162: label="Save"/>
163: </mx:HBox>
164: </mx:ApplicationControlBar>
165: <mx:VBox width="100%" height="100%" label="Edit">
166: <mx:TextArea id="txt_code"
167: text="{ model.selectedSnippet.snippet_code }"
168: width="100%"
169: height="100%"
170: styleName="codeView"/>
171: </mx:VBox>
172:
173: <!-- Validators -->
174: <mx:StringValidator id="titleV"
175: source="{ txt_title }"
176: minLength="1"
177: maxLength="200"
178: required="true"
179: property="text"/>
180: <mx:StringValidator id="authorV"
181: source="{ txt_author }"
182: minLength="1"
183: maxLength="200"
184: required="true"
185: property="text"/>
186: <mx:StringValidator id="codeV"
187: source="{ txt_code }"
188: minLength="5"
189: required="true"
190: property="text"/>
191: <mx:StringValidator id="typeV"
192: source="{ txt_type }"
193: minLength="1"
194: maxLength="200"
195: required="true"
196: property="text"/>
197: </mx:VBox>
SnippetList.mxml
1: <?xml version="1.0" encoding="utf-8"?>
2: <!--SnippetList-->
3: <mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" width="200" height="100%" creationComplete="init()">
4:
5: <mx:Script>
6: <![CDATA[
7: import mx.controls.Alert;
8: import mx.events.CloseEvent;
9: import com.jonniespratley.snippr.services.SnipprService;
10: import com.jonniespratley.snippr.vo.SnippetVO;
11: import com.jonniespratley.snippr.events.SnippetGetEvent;
12: import com.jonniespratley.snippr.model.ModelLocator;
13:
14: //Make a instance of our model for our data display
15: [Bindable] private var model:ModelLocator = ModelLocator.getInstance();
16:
17: //Make a variable to check weither there is a selected snippet or not
18: [Bindable] private var isSelected:Boolean = false;
19:
20: //Make variable of our service
21: private var service:SnipprService;
22:
23:
24: private function init():void
25: {
26: service = new SnipprService();
27: getSnippets();
28: }
29:
30: //Send a call to get the snippets
31: private function getSnippets():void
32: {
33: service.getSnippets();
34: }
35:
36: private function removeSnippet():void
37: {
38: Alert.show( "Are you sure?", "Remove Snippet", 3, null, removeSnippetAlertHandler );
39: }
40:
41: private function removeSnippetAlertHandler( event:CloseEvent ):void
42: {
43: if ( event.detail == Alert.YES )
44: {
45: service.removeSnippet( lt_snippets.selectedItem.snippet_id );
46: }
47: }
48:
49: //Make sure we handle the selected snippet and bind it to our model
50: private function selectHandler( event:Event ):void
51: {
52: isSelected = true;
53: model.selectedSnippet = event.target.selectedItem as SnippetVO;
54: }
55:
56: ]]>
57: </mx:Script>
58:
59: <!--Helper for Data Binding-->
60: <mx:Binding destination="lt_snippets.selectedItem" source="model.selectedSnippet"/>
61:
62: <!--List of Snippets-->
63: <mx:List id="lt_snippets"
64: dataProvider="{ model.snippetCollection }"
65: change="selectHandler( event )"
66: labelField="snippet_title"
67: width="100%"
68: height="100%"/>
69:
70: <!--Remove Button-->
71: <mx:Button label="Remove"
72: click="removeSnippet()"
73: enabled="{ isSelected }"
74: width="100%"/>
75: </mx:VBox>
MainView.mxml
1: <?xml version="1.0" encoding="utf-8"?>
2: <!--MainView-->
3: <mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" width="100%" height="100%"
4: xmlns:snippets="com.jonniespratley.snippr.view.components.*"
5: xmlns:view="com.jonniespratley.snippr.view.*">
6:
7: <!--ApplicationControll Bar-->
8: <view:ApplicationBar id="applicationBar"/>
9:
10: <!--MainViewStack-->
11: <mx:ViewStack id="vs_main" width="100%" height="100%" paddingBottom="10" paddingLeft="10" paddingRight="10" paddingTop="10">
12: <view:SnipprProxyView id="snippetsProxyView" label="Snippets Proxy"/>
13: </mx:ViewStack>
14:
15: <!--ViewToggle-->
16: <mx:ToggleButtonBar dataProvider="vs_main" width="100%"/>
17:
18: </mx:VBox>
Ok, with that said, here is a list of files that goes with this




September 26th, 2008 at 7:27 pm
Hey Jonnie! Excellent post… will be a lot of help to flex devs new to AMFPHP
Keep up the great work!
Featured here:
http://alamgirdesigns.blogspot.com/2008/09/flex-cheatsheet-flex-and-amfphp.html
September 27th, 2008 at 7:38 am
Good Stuff.
>I’ve created one robust Flex / AMFPHP app using caringorm, so my questions are in that context
In ‘SnippetVO.as’ I don’t understand what is happening in your in constuctor. Any reason why just an empty constructor won’t do?
Next, in ‘SnippetVO.php’ , you have ‘mapObject’. Why is that? When I made my app, my php VO was just the variables, everything was always typed and uber cool.
Look forward to taking this apart. Thanks
September 27th, 2008 at 8:45 pm
Let me try to explain this..
If TableA has the following naming convention:
ID VARCHAR NOT NULL
poSTitle VARCHAR NOT NULL
POsTbODY TEXT NOT NULL
And we want to be able to rename our fields comming back, so we can create our own
names for the columns.
We want to create something alittle bit more readable, for example:
$post_id
$post_title
$post_body
The record set that we are taking is a object,
then we are filtering those fields, and assigning
them to the variables that we created.
we would use something like this
$this->VARIABLE = ARGUMENT["NAME-OF-COLUMN"];
Now we can get a clean output of our data,
I have tried using amfphp without doing this and it
wasn’t a pretty sight, all of the names were jacked up and I just couldn’t
stand looking at those horrible names from the database. Amfphp can be used
with out mapObject(obj) and it can, I prefer using it.
February 26th, 2009 at 12:17 pm
Hi,
What’s happened to the first part of the cookbook? I can’t access it at all – just a blank page with a title and no info….
I am looking for resources that explain AMFPHP/Cairngorm and Flex3 simply for someone new to Flex…
Compliments on a cool site tho
March 5th, 2009 at 7:26 am
Hi,
Thanks for your response…
I am busy going through your Cairngorm articles/recipes (Chapter4) – the cookbook is great but reading your code is extremely tedious! The black background and dark blue color of some of the code just does not work!! Make the background a lighter color to make it easy on our eyes
March 10th, 2009 at 8:02 pm
Hi again….
I need your help and hope for a quick response.
I am working on my first flex3/amfphp/Cairngorm project and have spent sleepless nights on basic issues! I just need some direction.
For the login section of my program, I created a LoginVO.as file as a value object to pass my userid and password to my php service. There is also a UserVO.as and UserVO.php value object files that are supposed to return the logged in user’s details (such as first_name, last_name, cell, etc.) The service works but I get an ArrayCollection returned instead of a UserVO object.
I have checked all my paths and they are correct. How can I fix this? Do I need to map the array collection returned to my VO. This seems to defeat the purpose of using amfphp and remote objects….
Please help urgently.
Thanks