Step 1: Create a PHP object with an 'add' method.
Step 2: Create relevant JPSpan handler
Step 3: Use javascript to call add method
Step 4: Call add method again.
Expected result:
One sale is created and two products are added
Actual result:
JPSpan reinitializes the remote Sale object with every
transaction (it would seem). There is no persistance on
the server side.
The below code attempts to illustrate the problem...
//Javascript
var sale;
var SaleHandler = {
addproductbyid: function(result) {
alert(result);
},
onError: function(e) {
alert(e.name+': '+e.message+' (JPSpan Code:
'+e.code+')');
}
}
function init() {
sale = new sale(SaleHandler);
}
function test() {
sale.addproductbyid(1,10);
setTimeout("sale.addproductbyid(2,10);", 1000);
setTimeout("sale.addproductbyid(3,10);", 2000);
}
init();
test();
//PHP
<?php
require_once 'js/JPSpan.php';
require_once JPSPAN . 'Serializer.php';
require_once JPSPAN . 'Server/PostOffice.php';
class JPSpanFactory {
/**
* JPSpanFactory
*
* @param $controller Controller Class name to manufacture
*/
public static function factory($controller) {
//if (include_once 'classes/' . $controller . '.php') {
$factory = & new JPSpan_Server_PostOffice();
$factory->encoding = 'php';
$factory->addHandler(new $controller);
if (isset($_SERVER['QUERY_STRING']) &&
strcasecmp($_SERVER['QUERY_STRING'], 'client')==0) {
define('JPSPAN_INCLUDE_COMPRESS',FALSE);
$factory->displayClient();
}
else {
require_once JPSPAN . 'ErrorHandler.php';
$factory->serve();
}
return $factory;
//}
//else {
// throw new Exception ($controller . ' not found');
//}
}
}
class Sale {
var $items;
function addProductById($id,$quantity) {
$this->items[] = array($id,$quantity);
return var_export($this);
}
}
public function run($args) {
$controller = JPSpanFactory::factory("Sale");
}
?>
Is this broken or not yet implemented? I can't tell.
Logged In: YES
user_id=257409
Neither broken nor unimplemented, AFAIK.
Each time you make a call to a PHP class/method, a new
xmlHttpRequest is made to the server. The serverside PHP
script is run anew each time. You can have persistence on
the severside using PHP sessions. So instead of storing
products in $this->items, you would store them in
$_SESSION['items'] and return that each time.
class Sale {
function addProductById($id,$quantity) {
$_SESSION['items'][] = array($id,$quantity);
return $_SESSION['items'];
}
}
Logged In: YES
user_id=569780
OK - JPSpan remains intentionally stateless on the
server-side - although it's claiming to be a "server" it's
still really just Apache (or whatever) + PHP - once the
server script execution finishes, everything is gone and
server memory related to the script is ditched.
If that's behaviour is strange to you, recommend a couple of
reads;
http://www.oracle.com/technology/pub/articles/php_experts/rasmus_php.html
http://www.sitepoint.com/blog-post-view.php?id=151665
Guess I need to stress that JPSpan is about representing PHP
classes, not objects, in Javascript. That may seem like a
fine distinction but a class is PHP is the most useful form
of "namespace" and is a useful unit for reflection, to work
out what methods it contains.
That said, I may consider building in something that makes
it easier to persist objects in something like a database
although I doubt it will be anything more that some hooks
for your code.
Moving this to feature requests.
Logged In: YES
user_id=257409
It is possible to store an entire PHP object in a session.
Although I have not tried it with JPSpan, it should be
possible to instantiate your served PHP class once the first
time a user uses it, and store it in their PHP session.
Each time your master server script runs, you pull the
object out of the session before running
$factory->addHandler() and save it again after
$factory->serve() finishes. Although I imagine this process
would be significantly slower than just storing selected
values and arrays in the session, it may be more elegant.
-matthew