With Drupal 6, menu tokens are able to automatically load database records given an object id, this is a great feature, however this requires developers to implement 'load functions' for loading their records. Those 'load functions' are often just a wrapper around 'SELECT * from {mytable} WHERE mykey = %d'.
We could do better, and allow automatically load operations, and even better, enable automatic basic CRUD.
How?
CRUD API functions
We can add wrappers to CRUD functions, and avoid calling them directly.
drupal_load($id);
drupal_save($data);
drupal_delete($id);This way, the menu system would call drupal_load('mytable', $id), instead of direct calling mytable_load(). drupal_load() would then firstly look for mytable_load(), falling back to schema based loading, so such basic wrappers around SELECT queries wouldn't be needed anymore.
Benefits:
Example implementation:
<?php
function mymodule_schema() {
$schema['mymodule_object'] = array(
'description' => t('Stores data for mymodule.'),
'fields' => array(
'oid' => array(
'type' => 'serial',
'not null' => TRUE,
'description' => t('Primary Key: Unique object ID.'),
),
'title' => array(
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
'default' => '',
'description' => t('My object title.'),
),
'primary key' => array('oid'),
);
}
?>Done. You can now use drupal_load('mymodule_object', $oid) to load data, drupal_save('mymodule_object', $data) to insert/update records on the table, and drupal_delete('mymodule_object', $oid) to delete records.
Also you can easily implement menu items/callbacks to show your objects. All you would need to do is:
<?php
/**
* Implementation of hook_menu().
*/
function mymodule_menu() {
$items['mymodule/%mymodule_object'] = array(
'title' => 'Show my precious object',
'page callback' => 'mymodule_show',
'page arguments' => array(1),
'type' => MENU_CALLBACK,
);
}
/**
* Menu callback.
*/
function mymodule_show($object) {
// Enjoy, you have an object to play with. Let's just theme and output that for now.
return theme('mymodule_object', $object);
}
?>If you want to do something advanced with you data when loading, saving or deleting them you can still implement your complex data handling functions. E.g.:
<?php
/**
* CRUD load implementation.
*/
function mymodule_object_load($oid) {
// Do some magic to load our object.
}
?>Blocker issues:
- Currently all schema data is cached in one record, this needs to be changed for performance, i.e. splitting schema cache to one record per table.
- Some tables are not prefixed with module name (e.g. 'term_data'), this would cause the CRUD system to search for e.g.
term_data_load()instead oftaxonomy_term_data_load()when callingdrupal_load('term_data'), this could enforce inconsistent module namespaces. - Possibly conflict with node hooks: Node hooks such as
hook_load(),hook_save(), etc, needs to be renamed to e.g.hook_node_load_nodetype(). I've posted a patch trying to address this. - Some tables have plural names (e.g. 'comments') which can make CRUD APIs inconsistent, i.e. we would need to use e.g.
drupal_load('comments', $cid)instead ofdrupal_load('comment', $cid).
Related issues:
Data API: first steps
Creating a library of CRUD API functions for Drupal
Consistent table names to facilitate CRUD operations
Make node hooks/APIs more consistent
Simplify hook_user() and user_save(), etc. to be more consistent with other object methods
Come on folks, lets make Drupal 7 "The Awesome CRUDy Drupal Release"!

Comments
CRUD based on schema
For implementation of CRUD based on schema, I have a D6 module that does just
that, but allows even more complex items to be passed than just IDs. I'm just
getting ready to commit it to CVS for D6, but I'm not sure if there's even any
interest.
I was thinking that while replacing the {entity}_load is definitely valuable,
it might be interesting to start using crud methods in module as well:
right now an example of use for a module looks like this:
In the case I'm using, there are three base concepts:
$where: definition of a filter with fields, operations and values
$meta: meta informations such as LIMIT and ORDER BY
or a fields list if not all fields should be returned
$entity: field value definitions
node.crud.inc:
function node_create($entity) {
return abstract_create('node','node',$entity);
}
function node_update($entity,$where,$meta='') {
return abstract_update('node','node',$entity,$where,$meta);
}
function node_load($where,$meta='') {
return abstract_load('node','node',$where,$meta);
}
function node_delete($where,$meta=') {
return abstract_delete('node','node',$where,$meta)
}
function nodeauthor_load($where,$meta) {
return abstract_load(
'node',
array(
'node' => array('alias'=>'n'),
'user' => array( 'alias'=>'u', 'join' => 'LEFT JOIN', 'on' =>
'n.uid=u.uid')
),
$where,
$meta
)
}
node.module:
$node = node_load(13);
$nodes = node_load(array(1,2,3,4));
$nodes = node_load(
array(
'uid' => array( 1,2,3,4,5,6,7,8 ),
'create' => array('op' => 'between' , 'start' => '20090601' , 'stop' =>
20080601' ),
'update' => array( 'op' => 'not empty' )
),
);
$nodes_with_authors =
nodeauthor_load(
'all',
array(
'limit'=>10,
'order'=>array('field'=>'n.nid','order'=>''desc')
)
);
There are even multiple table selects as well, where multiple tables are
defined with join types and aliases.
The whole system just builds sql and arg arrays, to pass into db_query
I was also thinking that it would be easy to have this concept handle
serialization automatically by expanding the hook_schema concept.
I placed a copy of my D6 module with documentation here:
http://develop.12thirty4.com/db_schema.tar.gz
How can I access to the file?
How can I access to the file? It seems like there has to be user in order to access develop.12thirty4.com