-
27 Jun 2010 10:58 AM #11
Sweet, excellent job, J!
I had the same issue as khebs, thanks for the fix.
Well, how about the formHandler support?
My quick fix would be
ExtDirect.php line 114
and in your api.php (or example.php) I do this:PHP Code:// Count only required parameters or count them all, according to "count_only_required_params" configuration
if ( self::$count_only_required_params )
$newMethod = array( 'name' => $method->getName(), 'len' => $method->getNumberOfRequiredParameters() );
else
$newMethod = array( 'name' => $method->getName(), 'len' => $method->getNumberOfParameters() );
if (in_array(Array("$class"=>$method->getName()),self::$formHandlers)) $newMethod["formHandler"]=true;
$methods[]=$newMethod;
at this point we need to adapt parameters sent by the forms to params received by the func. The quick and dirty fix isPHP Code:ExtDirect::$formHandlers = Array(Array('someClass'=>'someFunc'));
This is a 1 min fix. I would love to see official support by the developerPHP Code:...
function someFunc($data) {
global $_REQUEST;
$data = $_REQUEST;
...
}
Grgur Grisogono
Ext JS in Action SE co-author
Exercising awesomeness at Modus Create - Official Sencha Partner
Get in touch for Sencha Touch Training
@ggrgur
-
27 Jun 2010 2:46 PM #12
+1, I would like to see official fix from the developer as-well..
-
29 Jun 2010 10:32 AM #13
Thanks for the bug report.
It is not related to the number of classes, though. It is related to the number of parameters of the method.
If the method does not require any parameter (zero required parameters), i.e., when "len" = 0 (zero) in the API declaration, Ext sends "null" as data (instead of an empty array)... this "null" is interpreted as an empty string when PHP reads the JSON input...
Anyway, I have just coded the fix and I will soon upload the modified code.
I appended the following two lines to ExtDirectAction::__construct
PHP Code:if ( empty( $this->parameters ) )
$this->parameters = array();
-
29 Jun 2010 11:49 AM #14
-
3 Jul 2010 10:24 PM #15
New Version Available
New Version Available
A new version has been released today.
The biggest change is the formHandler support.
Another important change was the bug fix for methods with zero parameters (len = 0).
Thanks for grgur and khebs for the valuable feedback.
Below, the complete changelog. In the next post, I will share the exciting details about the new formHandler support!
Thanks.
COMPLETE CHANGELOG:
- Added "form_handlers" configuration option to flag method(s) as formHandler
- Added "@formhandler" doc comment check to automatically flag a method as formHandler
- Added ExtDirectAction::$form_handler boolean property
- Added "form_handler" parameter to ExtDirectAction constructor, to initialize "form_handler" property value
- Implemented special "parameters" array preparation for formHandler methods
- Included comment to ExtDirect::provide method
- FIX: "rpc" extType is checked on form actions
- FIX: "include_inherited_methods" configuration is checked on action call
- BUG FIX: empty "parameters" is now transformed into an empty array (when "len" = 0, ExtJS sends data = "null")
- BUG FIX: "upload" boolean is now set correctly
- DOC FIX: ExtDirectAction::$parameters is of type "array" (not "mixed")
-
3 Jul 2010 11:18 PM #16
formHandler - How-To
formHandler - How-To
There are two different ways to flag a method as a "formHandler".
Method 1: use the new ExtDirect::$form_handlers configuration option.
- name: form_handlers
- type: array of strings
- meaning: Name of the class/methods to be flagged as formHandler in the Ext.Direct API
- default: empty
- comments: The string format for each method must be "className::methodName".
- example
Method 2: include "@formHandler" in the DOC comment of the method.PHP Code:ExtDirect::$form_handlers = array( 'someClass::someMethod', 'Server::date' );
Example:
In the example above, due to the "@formHandler" string inside the method's DOC comment, it will be flagged as a "formHandler" method.PHP Code:class FTP_Manager
{
/**
* Sets FTP password for a specific account
*
* @formHandler
* @param string $account Name of the account
* @param string $password New password
* @param string $password_confirm New password confirmation
* @return string
*/
public function set_ftp_password( $account, $password, $password_confirm )
{
// do stuff
return $result;
}
}
It has the same effect as this:
* Receiving parameters *PHP Code:ExtDirect::$form_handlers[] = 'FTP_Manager::set_ftp_password';
The parameters sent by forms are adapted to be received by the class method.
Pay attention now, because this is not usual.
I will use the "set_ftp_password" method above as the example.
First, note that we don't want that all formHandler methods have the same not-friendly signature, like this:
Where $data is the user input (usually $_POST)PHP Code:function set_ftp_password( $data );
function do_something( $data );
function do_something_completely_different( $data );
So, to be able to keep normal method signatures, like this...
...I have implemented the following solution:PHP Code:function set_ftp_password( $account, $password, $password_confirm )
When the method/action function is a formHandler, its parameter values are taken from the input names that matches the parameter's names.
So... $_POST['account'] will automatically become the $account parameter...
$_POST['password'] value will be the $password parameter value...
...and from where the $password_confirm parameter value will come from? Yes! From $_POST['password_confirm']
That's it: the method's parameters' names matches the $_POST array keys.
Advantages:
- Don't need to worry with parameter order
- Can use meaningful and clean method/function signature
- Don't need to sniff with $_POST array - the ExtDirect controller does this for us (forget "isset" checkings... if a certain parameter value is not set in the $_POST array, the default value - if available - or null is passed to the method/function)
Disadvantages:
- The input names must match the method/function parameter names (IMHO, an advantage!)
- This approach may just not be the best for you (in this case, just ignore all this stuff and go for the $_POST / $_GET / $_REQUEST arrays!)
Of course, all validation / filtering / sanitization of input data, as always, must be carefully considered.
Additional note about file upload:
If your file input name is "userfile", it will be available in your method/function parameter named $userfile
In other words: your $userfile parameter will receive the value from $_FILES['userfile']
-
7 Jul 2010 5:51 AM #17
A lot of thanks for your great integration !
One thing though: be aware that the functions you call need "return $blahblah" and not "echo $blahblah".
For wathever reasons I was echo'ing my return values in my class and when you do this, PHP's function "call_user_func_array" used in ExtDirect.php not only returns nothing, but nothing is executed in the PHP code after that line. So ExtDirect.php didn't return the complete response and ExtJS was crashing clientside.
-
7 Jul 2010 10:46 AM #18
return / echo / exit
return / echo / exit
Thanks, netsuo.
You are pointing to two different issues.
*** Issue #1 = echo vs. return
Yes, the API functions (methods) should return the values, not echo them. If you echo or print anything, these outputs will corrupt the final JSON which the ExtDirect classes prepare.
It is always a good idea to think in a "MVC" (model view controller) way - or at least in a VC (view / controller) way. I like to always do all calculation and collect all data first, and only in a final and separated step take care of the "view" (truly, the "output").
*** Issue #2 = "nothing is executed in the PHP code after that line" = exit
If you look at line 480 of ExtDirect.php file, you will see an exit(); command, in the constructor method of the ExtDirectController class.
This is why nothing is executed after a call to ExtDirect::provide()
In fact, ExtDirect::provide is merely an alias to new ExtDirectController(), i.e., ExtDirectController::__construct
This constructor accepts two parameters. The first is the $api_classes array, where you define the classes you want in your API. The second is an optional parameter: $autorun. It defaults to true.
Just look at ExtDirectController::__construct full code:
The $autorun parameter makes the controller call its "run" and "output" methods, and then exit.PHP Code:public function __construct( $api_classes = null, $autorun = true )
{
if ( is_array( $api_classes ) )
ExtDirect::$api_classes = $api_classes;
elseif ( is_string( $api_classes ) )
ExtDirect::$api_classes = array( $api_classes );
$this->request = new ExtDirectRequest();
$this->response = new ExtDirectResponse();
if ( $autorun )
{
$this->run();
$this->output();
exit();
}
}
Instead of calling ExtDirect::provide( $api_classes ), you may want to make a call setting $autorun to false:
If you do this, you will need to manually call:PHP Code:$extdirect = new ExtDirectController( $api_classes, false );
This will run the controller (i.e., process the HTTP request, and generate the corresponding HTTP response).PHP Code:$extdirect->run();
So, after this, all response (output) will be available on $extdirect->response
This output is only echoed when you call the output method, if you want:
Makes sense?PHP Code:$extdirect->output();
-
8 Jul 2010 3:43 AM #19
I'm sorry I think you misunderstood what I tried to say (English is not my language).
I was just saying that if you echo the value in the class you're linking with extdirect, the JSON won't be correct AND the PHP function "call_user_func_array" that you use in your ExtDirect.php will crash without any errors nor log.
It simply crashes and all code that's after "call_user_func_array" will not be executed (you can test yourself by echo'ing value in the function that "call_user_func_array" call and adding somethin' like "echo 'test';" after that line in ExtDirect.php).
It looks like PHP doesn't like at all that you're echo'ing something in a function called by "call_user_func_array".
-
8 Jul 2010 6:25 AM #20
Hi, netsuo. I understood you well. Your English is good.
I haven't done any test to check what you said, when I wrote my previous reply to you.
Right now I did. I changed an API function so it calls echo instead of returning a value. I also added more code after call_user_func_array to see what happened.
For me it does not crash at all.
The API function:
And after the "call_user_func_array" in ExtDirect.php I added:PHP Code:class SW_LayoutManager
{
function get_layouts_data()
{
echo 'tralala';
}
}
Below, the response:PHP Code:echo 'trilili';
FYI, I am using Firebug Console to see the server response.Code:tralalatrilili{"type":"rpc","tid":6,"action":"SW_LayoutManager","method":"get_layouts_data","result":null}
So, according to my experience, echo in an API function/method does not crash, and the code after call_user_func_array is normally executed.
As I said, we have two different issues:
1) "the JSON won't be correct"
This is true. The echo corrupts the JSON, as we can see in the example above.
2) "the PHP function 'call_user_func_array' that you use in your ExtDirect.php will crash without any errors nor log"
This is not true. I think it depends on PHP version and/or settings, operational system, etc.
I am using Linux Ubuntu 10.04 (Lucid Lynx) and PHP 5.3, with default php.ini settings.
I can call echo, and "call_user_func_array" does not crash for me. And I believe it really shouldn't crash.
It would be nice if we had more feedback from another users...
What is your OS and PHP version?
Are you sure "echo" is the problem?
Can you post some of this PHP code?
Anyway, thanks a lot for your feedback.
Similar Threads
-
Ext.Direct PHP backend
By ckr in forum Ext.DirectReplies: 34Last Post: 11 Jun 2012, 1:30 PM -
Alternative Ext Direct PHP Implementation
By TommyMaintz in forum Ext.DirectReplies: 36Last Post: 26 Sep 2011, 12:08 AM -
Easy Ext.Direct integration with PHP
By j.bruni in forum Ext.DirectReplies: 2Last Post: 23 Jun 2010, 11:27 AM -
Simple Ext.Direct PHP apps
By pkristiana in forum Community DiscussionReplies: 1Last Post: 11 Feb 2010, 1:12 AM




Reply With Quote