I haven’t had much time to complete that Advanced Guide To Flex project that I brought up awhile ago, but I am now going to release all of the examples that I did, even though I won’t explain them, I am sure most of you guys will be able to understand how the code works.
You may use this class as a REST type service or as a general class. Its great, CRUD on any database and table.
To create a table record, do the same as above just make the id field for your table 0, this is because the class does a check, to see if there is a key with the value of ( table primary key ), if there is a key, then it continues and checks the value of that key, in the array if the value is set to 0 or ‘ ‘, then it creates a new record, otherwise it updates that record in which is specified in the value of the key array.
To update a table record, simply just specify the the values for the fields in which you are wanting to update.
Make sure it is an assoc array containing array keys ( which are table columns ) and values ( which are the //updated values )
Here is a fun little library (kinda) that I created because I wanted to learn how to integrate Flash and Flex, the purpose of this experiment is to see how and what could I do in Flash/Illustrator and use in Flex, there is more great things that could have been done but o’well.
As you may not know, but I selected to write a article for the great people over at Flash & Flex Developers Magazine.
I just received a copy of the issue in the mail, and it looks great. Although I haven’t read my article yet, and I don’t plan on it… (I would just pick it apart and point out everything wrong.)
I want you guys to read it. I have attached a copy of the article, but if you want the real magazine plus tons of other great content, head over to your local bookstore and ask for Flash & Flex Magazine.
My First plugin attempt, I wanted to make a power user editor for making quick edits to the textpattern database. You know that it gets old
waiting for the page to reload every time in textpattern when you just want to make a few quick changes to the sections. Ok lets see how far I got.
There is a plugin composer that you can download and it will help you out when pasting the code from
your IDE to textpattern, make sure you grab that.
Ok this is going to go fast. I also commented my code really good so make sure you check that out. Lets do this.
First you need to register the tab and the event that is going to be handled by the plugin.
Here is the first part of the plugin before the functions got put in.
$plugin [ 'name' ] = 'jps_db_manager';
$plugin [ 'version' ] = '0.1';
$plugin [ 'author' ] = 'Jonnie Spratley';
$plugin [ 'author_uri' ] = 'http://jonniespratley.com';
$plugin [ 'description' ] = 'Database Manager';
$plugin [ 'order' ] = '5';
$plugin [ 'type' ] = '3';//only on the admin side
if ( ! defined ( 'txpinterface' ) ) @include_once ( 'zem_tpl.php' );
# --- BEGIN PLUGIN CODE ---
if ( @txpinterface == 'admin' )
{
$jpsDBTab = 'Fxk DB Manager';
$jpsDBEvent = 'jps_db_manager';
add_privs ( $jpsDBEvent, '1' );
/* ===============================================================================
* Register all callbacks and tabs, also permissions on all of the events
* That is something they don't tell you.
*
* I hate the resources on textpattern plugins, and the documentation, is shitty,
* actually... what documentation??
* ===============================================================================*/
register_tab ( 'extensions', $jpsDBEvent, $jpsDBTab );
register_callback ( $jpsDBEvent, $jpsDBEvent, null, 1 );
}//ends @txpinterface == admin
Now after that is in place, you have to create the callback function that will be triggered once the user clicks the tab we just registered. Before that we are going to have to create the mini private functions that help out the main function.
_getTables() – This gets all of the tables in the textpattern database. Then for every table in the
it creates a flex tree ready array holding the name of the table and the children which are the fields.
/**
* I get all of the tables in the database
*
* @return [array] - A array ready for Flex
*/
function _getTables()
{
//This is the textpattern config.php file. txpcfg holds the info in an assoc array;
global $txpcfg;
//Get the database name
$dbDB = $txpcfg [ 'db' ];
//Build the query
$sql = 'SHOW TABLES FROM ' . $dbDB;
//Get the results
$query = getThings ( $sql );
//Set up the result array
$tables = array ();
//Loop the results
foreach ( $query as $key => $value )
{
//Set up a array for the fields
$fields = array ();
//For each table get the fields
$fields = _describeTable ( $dbDB, $value );
//and now each table, add the table name and the fields array
$tables [] = array (
'label' => $value, 'children' => $fields
);
}
//Return that shit
return $tables;
}
_describeTable( table ) – This gets all of the fields in the table.
/**
* I describe a database table, I get information about the fields in the table.
*
* @param [string] $db - The database name from the txp configuration.
* @param [string] $tbl - The table name that you want information about.
* @return [array] An array containing the information.
*/
function _describeTable( $db, $tbl )
{
$sql = 'SHOW FIELDS FROM ' . $db . '.' . $tbl;
$results = getThings ( $sql );
$fields = array ();
//Loop the results from the getThings( sql ) method
foreach ( $results as $key => $value )
{
//Add each field to the array
$fields [] = array (
'label' => $value
);
}
//Return that shit
return $fields;
}
jps_db_manager( event, step ) – This function will poop out the ui, which is going to be a heading,
and then a div tag containing my flex application. It also added the neccessary javascript to the page.
I have a switch statement inside of the body of the function that checks the url to see what to do,
but I am not sure how to implement that.
/**
* array (
* 'db' => 'fxktextpattern',
* 'user' => 'root',
* 'pass' => 'fred',
* 'host' => 'localhost',
* 'table_prefix' => '',
* 'txpath' => '/Applications/MAMP/htdocs/fxk-textpattern/textpattern',
* 'dbcharset' => 'utf8',
* 'doc_root' => '/Applications/MAMP/htdocs',
* )
*
*
* @param [string] $event - what event does textpattern trigger,
* ( categories, articles, forms, etc. ) Look at the end of the url and you will see it.
* @param [string] $step - what event step is textpattern triggering,
* ( for categories, when you create a category this is the step: category_article_create ).
*/
function jps_db_manager( $event, $step )
{
//Default header and navigation, this took me so fucking long to figure out,
//no other part of the textpattern admin was showing up.
//and no one would ever tell you to watch out for that, fuck.
pagetop ( "Textpattern", '' );//DONT FORGET TO HAVE THIS IF YOU WANT THE UGLY TEXTPATTERN TABS AND SHIT
$dbJSON = '';//get the JSON ready
//Start building the top of OUR plugin
$html = '
Database Manager
';
//Shoot that shit out really quick.
echo $html;
/* ==================================================================================
* First part is complete, now we are going to set up for our REST admin stuff
* I know its tacky but so is textpattern, but I still love it <3;
*
* We are going to have a few different modes, and going to check if the url query
* string has any of what we want, and if it does we want to go ahead and do the
* correct function for it.
*
* Watch
* ================================================================================== */
//the mode variable ( ie: http://textpattern/index.php?event=OUR_PLUGIN_EVENT_NAME&m=GETDATA )
$mode = '';// m = GETDATA
$query = '';// q = the sql you want to call
$dbJSON = json_encode ( _getTables () );
/**
* Here is another shitty name for the textpattern variable, gps( what );
* this shit checks for a GET variable from the url or something.
* So we check if the url has a m in it for our MODE
*/
if ( gps ( 'm' ) )
{
//It does, good. set the m to the mode variable
$mode = gps ( 'm' );
//Good there is a mode so lets check for a q
if( gps ( 'q' ) )
{
$query = gps ( 'q' );
}
//Now lets switch depending on what mode is specified
switch ( $mode )
{
//case they want the tables, call the getTables() and set the return value to the $dbJSON variable we declared earlier
case 'getTables':
$dbJSON = json_encode ( _getTables () );
break;
case 'execute':
$dbJSON = json_encode( _executeQuery( $query ) );
break;
}
} //ends mode check
$html = <<
EOF;
echo $html;
}
Now that the plugin code is finished, it was time to goto the flex side. Notice that the javascript functions inside of the code, that is what I am going to be calling on, via flex’s external interface.
Here is the actionscript that will be calling on the javascript that I placed inside of the page.
import com.adobe.serialization.json.JSON;
import mx.collections.ArrayCollection;
import mx.events.ListEvent;
[Bindable] private var isResults:Boolean = false;
[Bindable] private var isAvailable:Boolean = false;
[Bindable] private var isProcessing:Boolean = false;
[Bindable] private var isValid:Boolean = false;
[Bindable] private var resultCollection:ArrayCollection = new ArrayCollection();
[Bindable] private var tableCollection:ArrayCollection = new ArrayCollection();
private function init():void
{
//Register all event listeners
btn_clear.addEventListener( MouseEvent.CLICK, clear );
btn_execute.addEventListener( MouseEvent.CLICK, execute );
btn_refresh.addEventListener( MouseEvent.CLICK, refresh );
tree_tables.addEventListener( ListEvent.CHANGE, onTreeChange );
isAvailable = ExternalInterface.available
getTables();
registerCallbacks();
}
private function registerCallbacks():void
{
ExternalInterface.addCallback( 'gotTables', onGotTables );
}
private function onGotTables( raw:String ):void
{
var jsonArray:Array = ( JSON.decode( raw ) as Array );
tableCollection = new ArrayCollection( jsonArray );
}
private function executeQuery( query:String ):void
{
var raw:String = ExternalInterface.call( 'execute', query );
var jsonArray:Array = ( JSON.decode( raw ) as Array );
resultCollection = new ArrayCollection( jsonArray );
}
private function getTables():void
{
var raw:String = ExternalInterface.call( 'getTables' );
var jsonArray:Array = ( JSON.decode( raw ) as Array );
tableCollection = new ArrayCollection( jsonArray );
}
private function refresh( event:MouseEvent ):void
{
getTables();
}
private function clear( event:MouseEvent ):void
{
txt_query.text = '';
}
private function execute( event:MouseEvent ):void
{
//Todo
}
private function onTreeChange( event:Event ):void
{
//Todo
ExternalInterface.call( 'tableSelected', event.currentTarget.selectedItem.label );
}
And the view
This is where I got stuck, I don’t know how to go about when a user selects a table, in flex, then send that table to javascript, then javascript to php?
This is a pretty big release, I found out that some of the classes didn’t work in the amfphp service browser, and some other amfphp internal issues was keeping it from fully being ran correctly.
I am sick of using it and sick of it not being reliable, and among other things. If you ask me, I think it is a hack-jab, but that is a different topic.
I have make some changes to the CodeGen 1.4-1.6 but it wasn’t noticeable to post about it, so here we are at 1.7, and the changes include:
Framework choice - Cairngorm / General Flex AS3
Added a GUI and form with tool tips for creation.
Dumps all the output from when files are created.
Saves Config.xml and Schema.xml with the applications name in front of it, more application, more configuration files, so you can run the generator multiple times, and keep all old config files.
REST style php classes that handle CRUD on that table, fully prepared for REST type calls to the class itself… More on that later.
Database REST service class that holds all of the table classes so one script, all data.
Added an optional Class and Service file that will handle CRUD on any database and/or table (MySQL) guaranteed. So instead of running the CodeGen every time you create a new table, you can just place the database and table name in the URL query and have your data right there.
Added an optional Developers Copywrite to be placed at the top of every generated file.
Huge Update, I have had a lot of questions about not being able to get this thing running consistently. Well I went ahead and created a GUI for it.
Now when you goto CodeGen on your localhost, you will be prompted with 3 forms.
One to enter in your config information.
One to review your information, and then when correct, generating the schema.xml file.
One form holding the location of both config.xml and schema.xml, when ready all you need to do is press “Generate Application” and you are finished.
I have tested this just now on MAMP and WAMP. So both are working perfectly, If anything happens please let me know and we can fix the issue.
Now generates the main application file, with the controller and services added to it.
On the save method on the server side, it now checks to see whether or not the id equals zero (0) or equals ” “, just because I am not guessing how to set that id field to 0, its all generated.
I see that some people have downloaded it, let me know how its working! Please I want some feedback.
Don’t you just hate having to create all of the Amfphp server database files, and then all of the value objects, then mirror that on the client side with the same things but in Flex builder?
Well I did, so I have decided to create a little generator that will create all of the following from an XML file.
Cairngorm Folder Structure
Cairngorm Service Locator – ( service per-table )
Cairngorm Service Delegate ( per-table )
Cairngorm Commands ( per-table; save, remove, get )
Cairngorm Events ( per-table; save, remove, get )
Cairngorm Value Objects – ( per-table )
Cairngorm Model Locator – ( per-application )
Cairngorm Controller – ( per-application )
Table Main – ( per-table )
PHP Service files – ( per-table )
PHP Value Objects – ( per-table )
And that’s not all.
Every file is generated from a template which is included in the download, you can change the templates, just be sure to look over the template key at the top of the file.
Also I guarantee this to be a full CRUD application on your MySQL database using Amfphp.
Most generators aren’t reliable or either working out of the box right from being generated, so I was just like screw that, I am going to make this, just because I hate copy and pasting my old scripts time and time again just to do the same thing.
The features that it generates:
Flex validation on all table columns that are required.
Flex Data Grid listing all of the records in the database.
Flex Form that lets you view the details of the selected record, and/or editing/creating of a new record.
Here is how to use this CodeGen
1. Require the php script inside of your file. ( just use the one included )
require_once 'CodeGen.php';
2. There is a config.xml file that is in the output folder, open it up and fill in your info.
3. Create a new instance of the CodeGen specifying the config.xml file as a constructor argument
4. Use this to write a copy of your database schema in the output folder.
$codegen->writeSchema();
5. After you have your schema, you this below to generate the code.
$codegen->generateCode( $schema );
6. Just drop inside the services folder of your Amfphp installation, and your ready to roll.
Server side gets generated into the output/server folder – You place this inside of the Amfphp/services folder, starting with the namespace root folder, ie. com/namespace/project
Client side get generated into the output/client folder – You place this inside of your src folder of your Flex builder project, also make sure you have the Cairngorm.swc inside of your libs folder of your Flex project.