I am working on a web application that will make extensive use of AJAX techniques for client/server communication...JSON-RPC specifically. Zend Framework is being used server-side, and it offers a nice JSON-RPC server that I would like to use.
My goal is to architect a maintainable system that exposes a large subset of server-side functionality to the client-side (javascript), without unnecessary code duplication. I've seen numerous blog posts and tutorials on how to use ZF's JSON-RPC server (see here and here), but they all seemed geared towards exposing a small, publicly consumable API. Code duplication is common, for example one blog post has the following method exposed:
public static function setTitle($bookId, $title) {
$book = new Nickel_Model_Book($bookId);
$book->setTitle($title);
$book->update();
return true;
}
I don't like the fact that there are two setTitle
methods. If the method signature for one changes, the other has to be kept in sync...seems like a maintainability nightmare if your API is extensive. It seems to me that there should be one Book
class, with one setTitle
method.
My initial thought is add a docblock annotation @export
to methods/classes that I want exposed. When I decide to expose the setTitle
method, I just add the annotation rather than a new method.
One potential problem I see involves object persistence. Server-side, it makes sense for setTitle
to set the object's title property...but not persist it in the database until update()
is called. Client-side, calling setTitle
should immediately affect the database. One potential solution is to modify all accessors such that they take a optional second parameter signifying the modification should update the database immediately:
function setTitle($title, $persist = false) {
$this->title = $title;
if ($persist) $this->update();
}
Some sort of proxy class could ensure that the $persist
flag is set for all client-side RPC invocations.
Another problem is the serialization of PHP objects. Server-side, it makes sense to do a OO-style $book->setTitle("foo")
call, but client-side book.setTitle(1234, "foo")
makes sense (where 1234 is the book's ID) due to the lack of state. My solution for this would be to have the aforementioned proxy class be responsible for somehow turning book.setTitle(1234, "foo")
into:
$book = new Book();
$book->load(1234);
return $book->setTitle($title);
I feel like this problem must have been tackled or discussed before...but I'm not finding many resources online. Does this seem like a sane solution?