Introducing JsTable
by Naneau
I stumbled across Jester a little while ago. Jester is a Javascript library built on top of Prototype for working with Ruby on Rails (RoR) ActiveResource. And it made me think. I am not a RoR man, I may turn into one in the future, but for now I’m quite happy using PHP. Since the Zend Framework has become quite stable, I’ve used that for most of what I do. So obviously Jester isn’t for me, but I still like the philosophy behind it. In a web 2.0 world linking server and client side code is very interesting, for numerous reasons.
In applications designed with the Zend Framework most models extend Zend_Db_Table. So on the client side you’d want to be able to work with something similar. I decided to create a set of classes that mimic the behaviour of Zend_Db_Table, Zend_Db_Table_Rowset and Zend_Db_Table_Row in Javascript. This way you can work with the ‘same’ models both on the server and the client side.
Enter jsTable. JsTable is a Prototype class that allows you to work with Zend_Db_Table objects directly from Javascript. It has mechanisms for basic communication with a server that holds the ‘real’ models. It gets it’s information in Json, either synchronously or asynchronously.
Let’s assume we have an application that has both users and posts, like a forum. You want to find a post that has an id of 1, and edit it’s title. But because you are a hip young webdeveloper you want to be able to do this via Ajax, just because you can!
In PHP:
1 2 3 4 5 6 7 | $mP = new Post(); //class Post extends Zend_Db_Table $rowset = $mP->find(1); //find returns an object of the class Zend_Db_Table_Rowset $row = $rowset->current(); $row->title = 'This is the new title'; $row->save(); |
In Javascript, with JsTable:
1 2 3 4 5 6 | var mP = new JsTable('Post'); var rowset = mP.find(1); //find returns an object of the class JsTableRowset var row = rowset.current(); row.title = 'This is a new title, but set in JavaScript'; row.save(); |
Now that’s pretty similar! Let’s do another example, creating a new Post:
in PHP:
1 2 3 4 5 | $mP = new Post(); $row = $mP->fetchNew(); $row->title = 'A title'; $row->content = 'This is my new post!'; $row->save(); |
in Javascript:
1 2 3 4 5 | var mP = new JsTable('Post'); var row = mP.fetchNew(); row.title = 'Another title'; row.content = 'I don\'t write very interesting posts'; row.save(); |
Again… Pretty similar, and pretty easy too!
Now before you start using buzzwords. This isn’t ajax. It doesn’t use xml, and it isn’t asynchronous. The find method will accept a second parameter, which, if given, will act as a callback, making the whole thing asynchronous. Depending on the circumstances you may or may not want to use it. Synchronous requests will freeze up the browser, but asynchronous requests will require additional logic. The save method for a single row also has an optional callback parameter, which will get a boolean true on succes, and false on failure.
1 2 3 4 5 | mP.find(1, callbackFunction); function callbackFunction(rowset) { //will get called when find() has finished //do something with the rowset } |
Another interesting thing is that JsTableRowset mixes in prototype’s enumerable, so you can do something like this:
1 2 3 4 5 6 7 | var mU = new JsTable('User'); var ids = $R(1,50).toArray(); //array of integer 1 to 50, lazy prototype style! var rowset = mU.find(ids); rowset.each(function(user){alert(user.name);}); //50 irritating alert boxes, with 50 usernames //(assuming there are 50 corresponding rows) |
The Javascript has documentation, so it should be fairly easy to understand it’s basic functionality, especially since it mimics behaviour you’re probably already familiar with. I have also included a sample controller, for use with JsTable.
I would like to warn you though, there are some serious security issues with the provided controller. Please don’t use it without modification, read up on Zend_Acl if you’re not sure about access restriction. I have also written my own little tutorial about securing JsTable
If this sounds interesting to you, why don’t you give it a try:
JsTable.zip
Comments
This looks interesting, but as you’ve mentioned, there are some pretty serious security issues that could show up if this were ever exposed on a publicly available site. Open up firebug and you’ve got yourself a query window where you can query for any data in a table and then modify it. At least you didn’t add a delete method to the row or expose full query capabilities! Interesting project though…
Well, the point really is to be able to modify all data, like you would be able to do in php. The real question is, who should be able to edit what data. As for the lack of a delete method, I was planning on creating that next. I just feel it should be there. A user who has the rights to delete a row should be able to do it. As I have mentioned in the post, the security issues can be solved on the server, like they should be solved in any other application.
I think you need to change your tiny security warning into a big fat red box above the download links, and a note not to link directly to the files (so all users see your warning). This has the potential to be extremely dangerous if not used properly.
That said, I can see some nice uses for it. I’ve added it to my del.icio.us bookmarks and might come back to it at a later date to investigate it more thoroughly.
Since when did JavaScript support object->property notation? Perhaps you meant to use object.property?
Otherwise, this is kinda neat, I’m all for consistent backend/frontend APIs, and whether you pass data from a form, or from an API such as this to PHP, it will always require validation and filtering, and when passed to the DB, escaping.
- Davey
Thank you both. I have fixed the -> notation. When you try to prove similarities it’s easy to forget there really are differences between languages
.
The security message should be really visible now.
Hi My Name Is ivaats.
hello
i’m trying your solution in a .Net web project with:
- nhibernate
- activerecord on top of it
- your jsTable on top of it all
i’m already using prototype in my solution.
i’m testing it with your piece of code:
var mP = new JsTable(‘project’);
var rowset = mP.find(1);
//find returns an object of the class JsTableRowset
var row = rowset.current();
row.nome = ‘new name’;
row.save();
however, the return of mP.find(1) always returns me undefined.
debugging it, I see that you build the url with what’s defined in urlRoot and urlFind.
I’ve already changed the urlRoot, but to what should I map urlfind?? your solution does not have the folders you refer in your urlFind ‘jstable/index/find/’
where can I find your ‘index’ and ‘find’ folders?? Am I missing something?
tks in advance!
Ok, I believe it maps to where the .cs are. But still I get undefined…
My solution is made for a Zend Framework project. It is absolutely not suited for what you are describing, I’m very sorry.
Hi,
Thanks. It helped lot, but in zend framework you can not assign the class in the .phtml file in should be in the Indexcontroller area.