Ext


Go Back   Ext JS Forums > Ext JS Community Forums (3.0) > Ext.Direct

Reply
 
Thread Tools
  #1  
Old 05-11-2009, 06:40 PM
TommyMaintz TommyMaintz is offline
Ext JS - Development Team
 
Join Date: Mar 2007
Location: Haarlem, Netherlands
Posts: 254
TommyMaintz is on a distinguished road
Send a message via MSN to TommyMaintz Send a message via Yahoo to TommyMaintz Send a message via Skype™ to TommyMaintz
Default Alternative Ext Direct PHP Implementation

Updated 08/04/2009: Fixed len property issue and class level path's

Hi guys,

I thought it would be nice to show another way of implementing Direct on a PHP server stack. It is using PHP comments and reflection to create the API for you automagically. I haven't documented it properly yet, and I dont have a client-side example to show it of, but I thought I would put it out here already anyway for you to try. I think the result is quite flexible and the router part should be easily extensible to use this with any server-side MVC framework out there . You can download the source code here.

It consists of 3 classes called:
  • ExtDirect_API
  • ExtDirect_Router
  • ExtDirect_CacheProvider

An example api.php that you would include in a <script> tag:

<?php
session_start
();

// Include ExtDirect PHP Helpers
require_once('ExtDirect/API.php');
require_once(
'ExtDirect/CacheProvider.php');

// I created a Cache to save the parsed API so it doesnt have to
// do all the reflecting and parsing over and over again
$cache = new ExtDirect_CacheProvider('cache/api_cache.txt');

// Create an ExtDirect_API instance
$api = new ExtDirect_API();

// Set up some special config options
$api->setRouterUrl('router.php'); // default
$api->setCacheProvider($cache);
$api->setNamespace('Ext.ss');
$api->setDescriptor('Ext.ss.APIDesc'); // defaults to Ext.app.REMOTING_API

// These defaults will be applied to each class when using the add method later on
$api->setDefaults(array(
    
'autoInclude' => true// this will automatically figure out file paths and include them
    
'basePath' => 'classes' // the base folder in which all your classes exist
));
// if you want to use autoInclude you have to make sure that your classes (without the prefix) 
// are named the exact same as the name of the file it exists in and that only one 
// class exists in each file.

// Now we have to add all the classes we want to scan for remotable methods
$api->add(
    array(
        
'Echo' => array('prefix' => 'Class_'), // Echo is a reserved keyword so i used a prefix
        
'Exception' => array('prefix' => 'Class_'), // Same reason as Echo
        
'Time',
        
'File'
    
)
);
// The config options you can specify for each individual class are:
// - autoInclude
// - subPath (to specify classes inside a nested folder structure, starts from the basePath)
// - prefix

// this will generate the API and output it properly for you
$api->output();

// by saving the state the router doesnt have to do all this parsing and 
// reflecting again. here i chose to save the state in a session but you
// can save it wherever you want
$_SESSION['ext-direct-state'] = $api->getState();
?>
Obviously another important part of the implementation is the router. Here is an example of a router.php:

<?php
session_start
();

require_once(
'ExtDirect/API.php');
require_once(
'ExtDirect/Router.php');

// this should always be set but if its not, then execute api.php without outputting it
if(!isset($_SESSION['ext-direct-state'])) {
    
ob_start();
    include(
'api.php');
    
ob_end_clean();
}

// A router needs an API instance aswell so thats why we create one and set its
// state to what we saved in the session in api.php
$api = new ExtDirect_API();
$api->setState($_SESSION['ext-direct-state']);
 
// Create the router, dispatch the call and output the response
$router = new ExtDirect_Router($api);
$router->dispatch();
$router->getResponse(true); // true to print the response instantly
?>
I also included some sample classes inside the /classes/ folder inside the rar file, but basically its a matter of putting comments about your function that include tags like @remotable, @formHandler and @remoteName (to specify a different name for a method on the client side). Here is an example of a simple Echo class that returns whatever you pass its send function:

<?php
    
class Class_Echo {
        
/**
         * @remotable
         */
        
public function send($string){
            return 
$string;
        }
    }
?>

Here is a simple File class that shows of some of the other options like @formHandler (see how it handles file uploads nicely) and @remoteName (list is a reserved keyword in PHP so thats why we have to use the @remoteName option)

<?php
    
class File {
        
/**
         * @remotable
         * @remoteName list
         */
        
public function listFiles($folder){
            if(
substr($folder03) === '../') {
                return 
'Nice try buddy';
            }
            return 
array_slice(scandir($folder), 2);
        }
        
        
/**
         * @remotable
         * @formHandler
         */
        
public function add($post$files){
            if(
$files && !empty($files[$post['formField']])) {
                
$file $files[$post['formField']];
                
move_uploaded_file($file['tmp_name'], 'data/' $file['name']);
                return 
pathinfo('data/' $file['name']);
            }            
        }
    }
?>
You can find all the source code and more examples inside the rar file.
Attached Files
File Type: zip ext-direct-php-1.01.zip (7.9 KB, 145 views)
Reply With Quote
  #2  
Old 05-11-2009, 09:17 PM
fabrizim's Avatar
fabrizim fabrizim is offline
Ext User
 
Join Date: Mar 2007
Location: Lowell, MA
Posts: 45
fabrizim is on a distinguished road
Default Nice!

Hi Tommy-

That is great. I wrote something similar for database field instantiantion / altering by parsing the files for doc comments in PHP4 - I didn't even realize the PHP5 reflection API lets you grab the doc comments. I plan on continuing development with my stuff and if I come up with any additional / generic parsing stuff, I'll post it back.

Best Regards-
Mark
Reply With Quote
  #3  
Old 05-12-2009, 12:28 PM
TommyMaintz TommyMaintz is offline
Ext JS - Development Team
 
Join Date: Mar 2007
Location: Haarlem, Netherlands
Posts: 254
TommyMaintz is on a distinguished road
Send a message via MSN to TommyMaintz Send a message via Yahoo to TommyMaintz Send a message via Skype™ to TommyMaintz
Default

Hi Fabrizim,

I had never looked at the Reflection capabilities in PHP5 before, but when I started doing this PHP router I thought it would be very useful. And it turned out it was. Im interested in what you come up with in regards to additional / generic parsing of the classes and looking forward to your post.
Reply With Quote
  #4  
Old 05-14-2009, 12:24 PM
mrsunshine's Avatar
mrsunshine mrsunshine is offline
Ext User
 
Join Date: Sep 2008
Location: Germany - Darmstadt
Posts: 171
mrsunshine is on a distinguished road
Send a message via Skype™ to mrsunshine
Default

Ported your nice classes to a TYPO3 Extension will it release it soon
Reply With Quote
  #5  
Old 05-18-2009, 09:08 AM
steffenk's Avatar
steffenk steffenk is offline
Ext User
 
Join Date: Jul 2007
Posts: 846
steffenk is on a distinguished road
Default

yeah, this can be used in TYPO3 very well, great! (increase the TYPO3 lobby )
__________________
vg Steffen
Reply With Quote
  #6  
Old 05-29-2009, 07:22 AM
meza's Avatar
meza meza is offline
Ext User
 
Join Date: Mar 2008
Posts: 5
meza is on a distinguished road
Default ExtDirectPack refactored

Hi!

There are some huge problems with the ExtJs's ExtDirectPack.
The first enormous design error is, that we definitely don't want a third-party tool to know the way our classes should be constructed. First I tried the reverse-engineers way to implement the Sphicy style automatic dependency injections. But still, that's not what we want from a third-party. The other trouble was the untestability. Anyone interested in php unit-testing can find a great slide by Sebastian Bergman at this link.

So I've started to solve these problems, and below is the first peak of it.
The key concept is to add already constructed instances to the api instead of classnames.

First of all, How a simple class looks like:
TestClass.php
<?php
class TestClass
{
    /**
     * @remotable
     */
    public function shout($what)
    {
        return 'SHOUT: '.$what;
    }

    /**
     * @remotable
     */
    public function postHandler($name,$files=array()){
        return array(
          'gotName'=>$name,
          'gotFiles'=>$files
        );
    }
}
?>
Now for the Api. It works the same way, you include it on client-side in a <script>

api.php
<?php

require_once('TestClass.php');
require_once('ExtDirect/Api.php');

$api=new ExtDirect_Api();
$api->add(new TestClass());

//$api->setRouterUrl('router.php');

echo $api->output();

?>
Because the router.php is still the default, it is commented out.

router.php
<?php

require_once('TestClass.php');
require_once('ExtDirect/Api.php');
require_once('ExtDirect/Router.php');

$api=new ExtDirect_Api();
$api->add(new TestClass());

//$api->setRouterUrl('router.php');

$router = new ExtDirect_Router($api);

echo $router->getResponse();

?>
And that's about it.
Grab the source from here.

The development is far from finished. Caching and the yet not refactored candy-s are soon to come. This release is just the absolute core

Due to the refactoring, the code is all covered with tests which ensure the stability and functionality. A bit later the project will be public to see for anyone.
Reply With Quote
  #7  
Old 06-04-2009, 06:44 AM
mark_l_lewis mark_l_lewis is offline
Ext JS Premium Member
 
Join Date: Jan 2008
Posts: 49
mark_l_lewis is on a distinguished road
Send a message via Skype™ to mark_l_lewis
Default

L]hi,

I'm having a little problem with the Ext.Direct PHP implementation. I have copied the entire example locally.

I then created a basic html file, included the api.php as script source. added a button and then implemented a handler.
The Handler below is called successfully, but the return value is undefined.


var rv Ext.ss.Echo.send('hello, world');

                
                
alert (rv
;

Using firebug I examined the router.php response as follows:


{"type":"rpc","tid":2,"action":"Echo","method":"send","result":"hello, world"
I'm not sure why the

rv 

is coming up as undefined?

I have downloaded the latest version of Ext RC2

Any help or direction would be appreciated.

Thanks,
Mark
Reply With Quote
  #8  
Old 06-04-2009, 07:00 AM
mrsunshine's Avatar
mrsunshine mrsunshine is offline
Ext User
 
Join Date: Sep 2008
Location: Germany - Darmstadt
Posts: 171
mrsunshine is on a distinguished road
Send a message via Skype™ to mrsunshine
Default

i think you have to handle the response like that,


 Ext.ss.Echo.send(text.getValue(), function(resulte){
                var 
e.getTransaction();
                
out.append(String.format('<p><b>Successful call to {0}.{1} with response:</b><xmp>{2}</xmp></p>',
                       
t.actiont.methodExt.encode(result)));
                
out.el.scrollTo('t'100000true);
            }); 
Reply With Quote
  #9  
Old 06-04-2009, 07:11 AM
mark_l_lewis mark_l_lewis is offline
Ext JS Premium Member
 
Join Date: Jan 2008
Posts: 49
mark_l_lewis is on a distinguished road
Send a message via Skype™ to mark_l_lewis
Default

and you truly are, mr sunshine :-)

that works a treat. although, is there another implementation which doesn't require a function handler for the return value?

the docs are a little thin on direct, although i'm piecing the bits together.
Reply With Quote
  #10  
Old 06-11-2009, 03:16 AM
JeffHowden's Avatar
JeffHowden JeffHowden is offline
Ext JS - Community Support Team
 
Join Date: Mar 2007
Location: Forest Grove, OR
Posts: 1,035
JeffHowden is on a distinguished road
Send a message via MSN to JeffHowden Send a message via Yahoo to JeffHowden
Default

Quote:
Originally Posted by mark_l_lewis View Post

var rv Ext.ss.Echo.send('hello, world');

                
alert (rv
;
Keep in mind that Ext.Direct is asynchronous. So, that means that in order to act upon the value being returned by the server, you'll have to specify a callback in your method call to the server. Mr. Sunshine illustrates that, but didn't specifically indicate the issue was with not staying within the asynch paradigm.
__________________
Jeff Howden
Ext JS - Support Team Volunteer
jeff@extjs.com

Any and all code samples that are authored by me and posted on the Ext forums or website are hereby released into the public domain and I release anyone or entity of liability by using said code samples unless explicitly stated otherwise.

Opinions are mine and not necessarily endorsed by Ext, LLC. Please do not contact me directly for assistance unless requested by me.
Reply With Quote
Reply

Thread Tools

Posting Rules

Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

All times are GMT -5. The time now is 08:57 PM.

© 2006-2009 Ext, LLC
Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2009, Jelsoft Enterprises Ltd.