Problem getting a module to work with services

Events happening in the community are now at Drupal community events on www.drupal.org.
avinoama2's picture

Hi in the last 4 days I am trying to do a simple "Hallo world" module with services.
I'm using Drupal 7 with Services 3.X Working with REST Server.
I read the API doc's.
I created an endpoint on my site.
Iv'e manage to use the default node and user module's in my Services module endpoint.
The services module recognized my module and methods all, index, retrieve etc...
And when i try to view data i get white page with no content.
And I can't get any good Example of a module that works with Services 3.x.

Any idea on how to do it ??
Or a link to a nice article ???

Comments

I have a working Drupal 6

bsenftner's picture

I have a working Drupal 6 Services 3.0 based module which publishes an API. It works, and I started by simply following the guide at http://drupal.org/node/783236, reading through http://drupal.org/node/783254 did not seem helpful until after completing the steps outlined by http://drupal.org/node/783460. The documentation really needs a complete rewrite, as there is very little in the way of explainers...

Note that the essential implementation logic for Services 3.0 is the same for D6 as D7, so that guide that worked for me should work for you.

hi it's working

avinoama2's picture

I used this post http://drupal.org/node/783460 to get it working
I did a little altering of the module to be able to work with D7.
*. db_fetch_object() dose not work in D7

This is a working version for D7
first file noteresources.module

<?php
// noteresources.module
   
/<strong>
     *
Implementation of hook_schema().
     */
    function
noteresource_schema() {
      return array(
       
'note' => array(
         
'description' => 'Stores information about notes',
         
'fields' => array(
           
'id' => array(
             
'description' => 'The primary identifier for a note.',
             
'type' => 'serial',
             
'unsigned' => TRUE,
             
'not null' => TRUE,
            ),
           
'uid' => array(
             
'description' => t('The user that created the note.'),
             
'type' => 'int',
             
'unsigned' => TRUE,
             
'not null' => TRUE,
             
'default' => 0,
            ),
           
'created' => array(
             
'description' => t('The timestamp for when the note was created.'),
             
'type' => 'int',
             
'unsigned' => TRUE,
             
'not null' => TRUE,
             
'default' => 0,
            ),
           
'modified' => array(
             
'description' => t('The timestamp for when the note was modified.'),
             
'type' => 'int',
             
'unsigned' => TRUE,
             
'not null' => TRUE,
             
'default' => 0,
            ),
           
'subject' => array(
             
'description' => t('The subject of the note'),
             
'type' => 'varchar',
             
'length' => 255,
             
'not null' => TRUE,
            ),
           
'note' => array(
             
'description' => t('The note'),
             
'type' => 'text',
             
'size' => 'medium',
            ),
          ),
         
'primary key' => array('id'),
        ),
      );
    }


   
// noteresource.module
   
/</strong>
     *
Gets a note object by id.
     *
     * @
param int $id
    
* @return object
    
*/
    function
noteresource_get_note($id) {
      return
db_query("SELECT * FROM {note} WHERE id='".$id."'");
    }

    /<
strong>
     *
Writes a note to the database
    
*
     * @
param object $note
    
* @return void
    
*/
    function
noteresource_write_note($note) {
     
$primary_key = !empty($note->id) ? array('id') : NULL;
     
drupal_write_record('note', $note, $primary_key);
    }

    /</
strong>
     *
Deletes a note from the database.
     *
     * @
param int $id
    
* @return void
    
*/
    function
noteresource_delete_note($id) {
     
db_query("DELETE FROM {note} WHERE id='".$id."'");
    }
 
// noteresource.module
    /**
     * Implementation of hook_services_resources().
     */
   
function noteresource_services_resources() {
      return array(
      
'note' => array(
        
'retrieve' => array(
          
'help' => 'Retrieves a note',
          
'file' => array('file' => 'inc', 'module' => 'noteresource'),
          
'callback' => '_noteresource_retrieve',
          
'access callback' => '_noteresource_access',
          
'access arguments' => array('view'),
          
'access arguments append' => TRUE,
          
'args' => array(
             array(
              
'name' => 'id',
              
'type' => 'int',
              
'description' => 'The id of the note to get',
              
'source' => array('path' => '0'),
              
'optional' => FALSE,
             ),
           ),
         ),
        
'create' => array(
          
'help' => 'Creates a note',
          
'file' => array('file' => 'inc', 'module' => 'noteresource'),
          
'callback' => '_noteresource_create',
          
'access arguments' => array('note resource create'),
          
'access arguments append' => FALSE,
          
'args' => array(
             array(
              
'name' => 'data',
              
'type' => 'struct',
              
'description' => 'The note object',
              
'source' => 'data',
              
'optional' => FALSE,
             ),
           ),
         ),
        
'update' => array(
          
'help' => 'Updates a note',
          
'file' => array('file' => 'inc', 'module' => 'noteresource'),
          
'callback' => '_noteresource_update',
          
'access callback' => '_noteresource_access',
          
'access arguments' => array('update'),
          
'access arguments append' => TRUE,
          
'args' => array(
             array(
              
'name' => 'id',
              
'type' => 'int',
              
'description' => 'The id of the node to update',
              
'source' => array('path' => '0'),
              
'optional' => FALSE,
             ),
             array(
              
'name' => 'data',
              
'type' => 'struct',
              
'description' => 'The note data object',
              
'source' => 'data',
              
'optional' => FALSE,
             ),
           ),
         ),
        
'delete' => array(
          
'help' => 'Deletes a note',
          
'file' => array('file' => 'inc', 'module' => 'noteresource'),
          
'callback' => '_noteresource_delete',
          
'access callback' => '_noteresource_access',
          
'access arguments' => array('delete'),
          
'access arguments append' => TRUE,
          
'args' => array(
             array(
              
'name' => 'nid',
              
'type' => 'int',
              
'description' => 'The id of the note to delete',
              
'source' => array('path' => '0'),
              
'optional' => FALSE,
             ),
           ),
         ),
        
'index' => array(
          
'help' => 'Retrieves a listing of notes',
          
'file' => array('file' => 'inc', 'module' => 'noteresource'),
          
'callback' => '_noteresource_index',
          
'access callback' => 'user_access',
          
'access arguments' => array('access content'),
          
'access arguments append' => FALSE,
          
'args' => array(array(
              
'name' => 'page',
              
'type' => 'int',
              
'description' => '',
              
'source' => array(
                
'params' => 'page',
               ),
              
'optional' => TRUE,
              
'default value' => 0,
             ),
             array(
              
'name' => 'parameters',
              
'type' => 'array',
              
'description' => '',
              
'source' => 'param',
              
'optional' => TRUE,
              
'default value' => array(),
             ),
           ),
         ),
       ),
      );
    }
?>

second file noteresource.inc

<?php
   
// noteresource.inc
   
/<strong>
     *
Callback for creating note resources.
     *
     * @
param object $data
    
* @return object
    
*/
    function
_noteresource_create($data) {
      global
$user;

      unset(
$data->id);
     
$data->uid = $user->uid;
     
$data->created = time();
     
$data->modified = time();

      if (!isset(
$data->subject)) {
        return
services_error('Missing note attribute subject', 406);
      }

      if (!isset(
$data->note)) {
        return
services_error('Missing note attribute note', 406);
      }

     
noteresource_write_note($data);
      return (object)array(
       
'id' => $data->id,
       
'uri' => services_resource_uri(array('note', $data->id)),
      );
    }

    
// noteresource.inc
   
/</strong>
     *
Callback for updating note resources.
     *
     * @
param int $id
    
* @param object $data
    
* @return object
    
*/
    function
_noteresource_update($id, $data) {
      global
$user;
     
$note = noteresource_get_note($id);

      unset(
$data->created);
     
$data->id = $id;
     
$data->uid = $note->uid;
     
$data->modified = time();

     
noteresource_write_note($data);
      return (object)array(
       
'id' => $id,
       
'uri' => services_resource_uri(array('note', $id)),
      );
    } 
    /<
strong>
     *
Callback for retrieving note resources.
     *
     * @
param int $id
    
* @return object
    
*/
    function
_noteresource_retrieve($id) {
      return
noteresource_get_note($id);
    }

    /</
strong>
     *
Callback for deleting note resources.
     *
     * @
param int $id
    
* @return object
    
*/
    function
_noteresource_delete($id) {
     
noteresource_delete_note($id);
      return (object)array(
       
'id' => $id,
      );
    }
    function
_noteresource_index($page, $parameters) {
      global
$user;

     
$notes = array();
     
$res = db_query("SELECT * FROM {note} WHERE uid='".$user->uid."' ORDER BY modified DESC");


   foreach (
$res as $note) {

       
$notes[] = $note;
      }

      return
$notes;
    }

   
/**
     * Access callback for the note resource.
     *
     * @param string $op
     *  The operation that's going to be performed.
     * @param array $args
     *  The arguments that will be passed to the callback.
     * @return bool
     *  Whether access is given or not.
     */

   
function _noteresource_access($op, $args) {
      global
$user;
     
$access = FALSE;

      switch (
$op) {
        case
'view':
         
$note = noteresource_get_note($args[0]);
         
$access = user_access('note resource view any note');
         
$access = $access || $note->uid == $user->uid && user_access('note resource view own notes');
          break;
        case
'update':
         
$note = noteresource_get_note($args[0]->id);
         
$access = user_access('note resource edit any note');
         
$access = $access || $note->uid == $user->uid && user_access('note resource edit own notes');
          break;
        case
'delete':
         
$note = noteresource_get_note($args[0]);
         
$access = user_access('note resource delete any note');
         
$access = $access || $note->uid == $user->uid && user_access('note resource delete own notes');
          break;
      }

      return
$access;
    }
?>

Thenks for pointing in the right direction... :)

Expected results question

happylrac's picture

avinoama2, thanks for the updated example!

I do have a question though. By looking at the D6 version of the example you can test the REST server by going to the js-api/note/1.yaml address. That works but what I see back is


dbh: [ ]
queryString: "SELECT * FROM note WHERE id='1'"

I did not expect to see the query. What I expected to see was the results of the query.

What am I doing wrong? Am I misunderstanding something?

I had the same problem. Just

tglynn's picture

I had the same problem. Just make sure you add "->fetchAll();" since the database api in 7 is using objects, requiring you to append that to the end of queries. This is what I did to test that it worked. I changed the function noteresource_get_note to this, simply adding "->fetchAll (and I personally hardcoded in the number 1 just in make sure):

function noteresource_get_note($id) {
return db_query("SELECT * FROM {note} WHERE id='1'")->fetchAll();
}

I then went to http://localhost/drupal-7.7/js-api/note/1.yaml in my browser, which gave me back:

---

id: 1
uid: 1
created: 1312988452
modified: 1312988452
subject: Here is the subject
note: |
    >
            This is the note text. This is the note text. This is the
            note text. This is the note text. This is the note text.
            This is the note text. This is the note text. This is the
            note text.

Services

Group organizers

Group categories

Group notifications

This group offers an RSS feed. Or subscribe to these personalized, sitewide feeds: