3

I've set up web services using Drupal's services module. It outputs JSON for me which I am requesting through a Backbone.js front-end application.

I'm having issues with this set-up. If I request data through Backbone.js' fetch method of a model, the model's attributes are all typed as string after fetching, while there are some attributes that should be e.g. integer.

For example:

  • I have enabled the user resource, which is standard available in the Drupal services module
  • I can request a user, e.g.:

    http://mydevmachine/services/user/8
    

...which results in the following response (slimmed down version from the real response):

    {"uid":"8","name":"itsme","mail":"me@mydomain.nl"}
  • What I see in the response from the web service above, all values are quoted, however uid is really not a string but an integer in the database.
  • If I fetch the same user in my Backbone.js model, by setting the uid field of my model to 8 (integer), then call the fetch method. After fetching the uid field is typed as 'string'.

I assume the above leads to my model ending up with a uid attribute of not integer, but string. It also happens with all other web service resources I have created, using my own entities.

I need correct typing of attributes in my model due to sorting issues using Backbone's collection sorting. I.e. sorting a collection of models using a field of type 'integer' leads to different sorting results when sorting the field with the same values although stored as a string.

I'm not sure exactly where to look:

  • Is the JSON format output by the Drupal services module according to standards?
  • Is the JSON output format configurable or overridable in the Drupal services module?
  • Is it perhaps possible to keep the type of a model's attribute after a fetch in Backbone.js?
  • Should I provide a specific implementation for Backbone's collection comparator function, which handles this situation (seems hackey)?
  • Should I introduce other solutions, e.g. like posted here: How can I enforce attribute types in a Backbone model? (feels too heavy).

Thanks for any help.

Community
  • 1
  • 1
Vanderstaaij
  • 541
  • 5
  • 13
  • 1
    You can set up [`parse`](http://backbonejs.org/#Model-parse) methods in your Backbone as a last resort but there has to be a way to make your server treat send out numbers as numbers in the JSON. – mu is too short Jul 04 '13 at 15:34
  • Mmmmh, I haven't thought of that one yet. Indeed it feels a bit like double work if I was to do that, but it may also be some sort of extra layer on top of securing you receive the right data. Thanks for answering! – Vanderstaaij Jul 08 '13 at 08:17

1 Answers1

0

So I finally managed to crack this issue and I found my solution here: How to get numeric types from MySQL using PDO?. I thought I'd document the solution.

Drupal 7 uses PDO. Results fetched using PDO, using Drupal's default PDO settings result in stringified values.

In Drupal's includes/database.inc file you will find this around lines 40-50:

$connection_options['pdo'] += array(
  // So we don't have to mess around with cursors and unbuffered queries by default.
  PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => TRUE,
  // Because MySQL's prepared statements skip the query cache, because it's dumb.
  PDO::ATTR_EMULATE_PREPARES => TRUE,
);

The statement here that MySQL's prepared statements skip the query cache is not entirely true, as can be found here: http://dev.mysql.com/doc/refman/5.1/en/query-cache-operation.html. It states MySQL > 5.1.17 prepared statements use the query cache under certain conditions.

I used the info from the other stack overflow question/answers to override the PDO settings for the database connection in Drupal's sites/default/settings.php (please note I only did this for the database I was querying, which is different than Drupal's own database):

'database_name' =>
  array (
    'default' => 
    array (
      'database' => 'database_name',
      'username' => 'user_name',
      'password' => 'user_pass',
      'host' => 'localhost',
      'port' => '',
      'driver' => 'mysql',
      'prefix' => '',
      'pdo' => array(
        PDO::ATTR_STRINGIFY_FETCHES => FALSE,
        PDO::ATTR_EMULATE_PREPARES => FALSE
      ),
    ),
  ),

This resulted in integers being integers. Floats/decimals are incorrectly returned by PDO still, but this is different issue. At least my problems are solved now.

Community
  • 1
  • 1
Vanderstaaij
  • 541
  • 5
  • 13