THE DRUPAL 7 API Badiu Alexandru Drupalcamp Bucharest 2011
D7 API • New stuff in the Drupal 7 API • Things that have changed since D6 • Not gonna cover all • Just what I found interesting Drupalcamp Bucharest 2011
D7 API • Database API • Translation API • Render Arrays • Drupal Queues • File API Drupalcamp Bucharest 2011
DATABASE • Completly rewritten • Object oriented • Easier to hook into queries • Easier to support multiple db servers • Vendor agnostic Drupalcamp Bucharest 2011
DATABASE db_affected_rows(), db_distinct_field(), db_error(), db_last_insert_id(), db_placeholders(), db_lock_table(), db_prefix_tables(), db_result(), db_fetch_*(), db_version(), db_rewrite_sql(), hook_db_rewrite_sql(), pager_query(), tablesort_sql() etc are gone. Drupalcamp Bucharest 2011
DATABASE • SELECT // Drupal 6 $result = db_query("SELECT nid, title FROM {node} WHERE uid = %d AND type IN (" . db_placeholders(array('page', 'story'), 'varchar') . ")", 5, 'page', 'story'); // Drupal 7 $result = db_query("SELECT nid, title FROM {node} WHERE uid = :uid AND type IN (:type)", array(   ':uid' => 5,   ':type' => array('page', 'story'), )); Drupalcamp Bucharest 2011
DATABASE • Getting results // Drupal 6 while ($record = db_fetch_object($result)) {   // Do stuff with $record, which is an object } // Drupal 7 foreach ($result as $record) {   // Do stuff with $record, which is an object } Drupalcamp Bucharest 2011
DATABASE • INSERT // Drupal 6 db_query("INSERT INTO {mytable} (intvar, stringvar, floatvar) VALUES (%d, '%s', %f)", 5, 'hello world', 3.14); $id = db_last_insert_id(); // Drupal 7 $id = db_insert('mytable')   ->fields(array(     'intvar' => 5,     'stringvar' => 'hello world',     'floatvar' => 3.14,   ))   ->execute(); Drupalcamp Bucharest 2011
DATABASE • UPDATE // Drupal 6 db_query("UPDATE {node} SET title='%s', status=%d WHERE uid= %d", 'hello world', 1, 5); // Drupal 7 db_update('node')   ->fields(array('title' => 'hello world', 'status' => 1))   ->condition('uid', 5)   ->execute(); Drupalcamp Bucharest 2011
DATABASE • DELETE // Drupal 6 db_query("DELETE FROM {node} WHERE uid=%d AND created < %d", 5, REQUEST_TIME - 3600); // Drupal 7 db_delete('node')   ->condition('uid', 5)   ->condition('created', REQUEST_TIME - 3600, '<')   ->execute(); Drupalcamp Bucharest 2011
DATABASE • JOINS SELECT fm.filename, fm.uri FROM file_usage AS fu INNER JOIN file_managed AS fm ON fu.fid = fm.fid WHERE fu.id = 5; $query = db_select('file_usage', 'fu'); $query->join('file_managed', 'fm', 'fu.fid = fm.fid'); // inner_join file_usage table against file_managed $query ->fields('fu', array('fid')) // specifying fields from file_usage table ->fields('fm', array('filename', 'uri')) // specifying fields from file_managed table ->condition('fu.id', 5, '='); // specifying the condition where fu.id = 5   $result = $query->execute(); // executing the query once we finish building the query object Drupalcamp Bucharest 2011
DATABASE • Queries can have tags • hook_query_alter • hook_query_TAG_alter • Transactions Drupalcamp Bucharest 2011
DATABASE • $query->orderRandom() • $query->orderBy(“field”) • $query->orderBy(“field”)->orderRandom() • $query->groupBy() • $query->range(0, 20) • $query->countQuery()->execute()- >fetchField() Drupalcamp Bucharest 2011
TRANSLAT • The whole system has been improved • Localization server • Translations can be updated • Localization module (contrib) Drupalcamp Bucharest 2011
TRANSLAT • Contexts • Avoid Views vs 5 Views • Does not work with Javascript • Does not work with watchdog $long_may = t('May', array(), array('context' => 'Long month name')); Drupalcamp Bucharest 2011
RENDER • A page’s content is kept as an array until the last stage (theme layer) • A module can change the content at the very last minute • Instead of returning HTML you return an array Drupalcamp Bucharest 2011
RENDER $page = array(   '#show_messages' => TRUE,   '#theme' => 'page',   '#type' => 'page',   'content' => array(     'system_main' => array(...),     'another_block' => array(...),     '#sorted' => TRUE,   ),   'sidebar_first' => array(     ...   ),   'footer' => array(     ...   ),   ... ); Drupalcamp Bucharest 2011
RENDER • hook_page_alter function mymodule_page_alter(&$page) {   // Move search form into the footer.   $page['footer']['search_form'] = $page['sidebar_first'] ['search_form'];   unset($page['sidebar_first']['search_form']);     // Remove the "powered by Drupal" block   unset($page['footer']['system_powered-by']); } Drupalcamp Bucharest 2011
RENDER • Generating page output return array(   'first_para' => array(     '#type' => 'markup',     '#markup' => 'A first paragraph',   ),   'second_para' => array(     '#items' => array('first item', 'second item', 'third item'),     '#theme' => 'item_list',   ), ); Drupalcamp Bucharest 2011
RENDER • hide() <div class="content">   <?php     // We hide the comments and links now so that we can render them later.     hide($content['comments']);     hide($content['links']);     print render($content);   ?> </div> <?php print render($content['links']); ?> <?php print render($content['comments']); ?> Drupalcamp Bucharest 2011
DRUPAL • Stop doing lenghty operations on cron • Like: indexing Solr data, generating thumbnails • We have producers and workers • Backported to Drupal 6 Drupalcamp Bucharest 2011
DRUPAL • Reliable queues • Unreliable queues • Pluggable backends • Add Beanstalk and Supervisord and you’re good to go Drupalcamp Bucharest 2011
DRUPAL $queue = DrupalQueue::get('aggregator_feeds');   foreach ($result as $feed) {     if ($queue->createItem($feed)) {       // Add timestamp to avoid queueing item more than once.       db_update('aggregator_feed')         ->fields(array('queued' => REQUEST_TIME))         ->condition('fid', $feed->fid)         ->execute();     }   } Drupalcamp Bucharest 2011
DRUPAL function aggregator_cron_queue_info() { $queues['aggregator_feeds'] = array( 'worker callback' => 'aggregator_refresh', 'time' => 60, ); return $queues; } Drupalcamp Bucharest 2011
FILE API • Uses streams • public://file.txt • private://file.txt • temporary://file.txt • PHP’s provided: http://, ftp:// • A module can create a new stream Drupalcamp Bucharest 2011
FILE API • No more public or private • Uses streams • public://file.txt, private://file.txt, temporary://file.txt Drupalcamp Bucharest 2011
FILE API • Managed and unmanaged files • file_copy / file_unmanaged_copy • PHP’s provided: http://, ftp:// • A module can create a new stream Drupalcamp Bucharest 2011
FILE API function file_example_stream_wrappers() { $wrappers = array( 'session' => array( 'name' => t('Example: $_SESSION variable storage'), 'class' => 'FileExampleSessionStreamWrapper', 'description' => t('Store files in the $_SESSION variable as an example.'), ), ); return $wrappers; } Drupalcamp Bucharest 2011
THANK andu@ctrlz.ro http://ctrlz.ro Drupalcamp Bucharest 2011

What's new in the Drupal 7 API?

  • 1.
    THE DRUPAL 7API Badiu Alexandru Drupalcamp Bucharest 2011
  • 2.
    D7 API • New stuff in the Drupal 7 API • Things that have changed since D6 • Not gonna cover all • Just what I found interesting Drupalcamp Bucharest 2011
  • 3.
    D7 API • Database API • Translation API • Render Arrays • Drupal Queues • File API Drupalcamp Bucharest 2011
  • 4.
    DATABASE • Completly rewritten • Object oriented • Easier to hook into queries • Easier to support multiple db servers • Vendor agnostic Drupalcamp Bucharest 2011
  • 5.
    DATABASE db_affected_rows(), db_distinct_field(), db_error(), db_last_insert_id(), db_placeholders(),db_lock_table(), db_prefix_tables(), db_result(), db_fetch_*(), db_version(), db_rewrite_sql(), hook_db_rewrite_sql(), pager_query(), tablesort_sql() etc are gone. Drupalcamp Bucharest 2011
  • 6.
    DATABASE • SELECT // Drupal 6 $result = db_query("SELECT nid, title FROM {node} WHERE uid = %d AND type IN (" . db_placeholders(array('page', 'story'), 'varchar') . ")", 5, 'page', 'story'); // Drupal 7 $result = db_query("SELECT nid, title FROM {node} WHERE uid = :uid AND type IN (:type)", array(   ':uid' => 5,   ':type' => array('page', 'story'), )); Drupalcamp Bucharest 2011
  • 7.
    DATABASE • Getting results // Drupal 6 while ($record = db_fetch_object($result)) {   // Do stuff with $record, which is an object } // Drupal 7 foreach ($result as $record) {   // Do stuff with $record, which is an object } Drupalcamp Bucharest 2011
  • 8.
    DATABASE • INSERT // Drupal 6 db_query("INSERT INTO {mytable} (intvar, stringvar, floatvar) VALUES (%d, '%s', %f)", 5, 'hello world', 3.14); $id = db_last_insert_id(); // Drupal 7 $id = db_insert('mytable')   ->fields(array(     'intvar' => 5,     'stringvar' => 'hello world',     'floatvar' => 3.14,   ))   ->execute(); Drupalcamp Bucharest 2011
  • 9.
    DATABASE • UPDATE // Drupal 6 db_query("UPDATE {node} SET title='%s', status=%d WHERE uid= %d", 'hello world', 1, 5); // Drupal 7 db_update('node')   ->fields(array('title' => 'hello world', 'status' => 1))   ->condition('uid', 5)   ->execute(); Drupalcamp Bucharest 2011
  • 10.
    DATABASE • DELETE // Drupal 6 db_query("DELETE FROM {node} WHERE uid=%d AND created < %d", 5, REQUEST_TIME - 3600); // Drupal 7 db_delete('node')   ->condition('uid', 5)   ->condition('created', REQUEST_TIME - 3600, '<')   ->execute(); Drupalcamp Bucharest 2011
  • 11.
    DATABASE • JOINS SELECT fm.filename, fm.uri FROM file_usage AS fu INNER JOIN file_managed AS fm ON fu.fid = fm.fid WHERE fu.id = 5; $query = db_select('file_usage', 'fu'); $query->join('file_managed', 'fm', 'fu.fid = fm.fid'); // inner_join file_usage table against file_managed $query ->fields('fu', array('fid')) // specifying fields from file_usage table ->fields('fm', array('filename', 'uri')) // specifying fields from file_managed table ->condition('fu.id', 5, '='); // specifying the condition where fu.id = 5   $result = $query->execute(); // executing the query once we finish building the query object Drupalcamp Bucharest 2011
  • 12.
    DATABASE • Queries can have tags • hook_query_alter • hook_query_TAG_alter • Transactions Drupalcamp Bucharest 2011
  • 13.
    DATABASE • $query->orderRandom() • $query->orderBy(“field”) • $query->orderBy(“field”)->orderRandom() • $query->groupBy() • $query->range(0, 20) • $query->countQuery()->execute()- >fetchField() Drupalcamp Bucharest 2011
  • 14.
    TRANSLAT • The whole system has been improved • Localization server • Translations can be updated • Localization module (contrib) Drupalcamp Bucharest 2011
  • 15.
    TRANSLAT • Contexts • Avoid Views vs 5 Views • Does not work with Javascript • Does not work with watchdog $long_may = t('May', array(), array('context' => 'Long month name')); Drupalcamp Bucharest 2011
  • 16.
    RENDER • A page’s content is kept as an array until the last stage (theme layer) • A module can change the content at the very last minute • Instead of returning HTML you return an array Drupalcamp Bucharest 2011
  • 17.
    RENDER $page = array(  '#show_messages' => TRUE,   '#theme' => 'page',   '#type' => 'page',   'content' => array(     'system_main' => array(...),     'another_block' => array(...),     '#sorted' => TRUE,   ),   'sidebar_first' => array(     ...   ),   'footer' => array(     ...   ),   ... ); Drupalcamp Bucharest 2011
  • 18.
    RENDER • hook_page_alter function mymodule_page_alter(&$page) {   // Move search form into the footer.   $page['footer']['search_form'] = $page['sidebar_first'] ['search_form'];   unset($page['sidebar_first']['search_form']);     // Remove the "powered by Drupal" block   unset($page['footer']['system_powered-by']); } Drupalcamp Bucharest 2011
  • 19.
    RENDER • Generating page output return array(   'first_para' => array(     '#type' => 'markup',     '#markup' => 'A first paragraph',   ),   'second_para' => array(     '#items' => array('first item', 'second item', 'third item'),     '#theme' => 'item_list',   ), ); Drupalcamp Bucharest 2011
  • 20.
    RENDER • hide() <div class="content">   <?php     // We hide the comments and links now so that we can render them later.     hide($content['comments']);     hide($content['links']);     print render($content);   ?> </div> <?php print render($content['links']); ?> <?php print render($content['comments']); ?> Drupalcamp Bucharest 2011
  • 21.
    DRUPAL • Stop doing lenghty operations on cron • Like: indexing Solr data, generating thumbnails • We have producers and workers • Backported to Drupal 6 Drupalcamp Bucharest 2011
  • 22.
    DRUPAL • Reliable queues • Unreliable queues • Pluggable backends • Add Beanstalk and Supervisord and you’re good to go Drupalcamp Bucharest 2011
  • 23.
    DRUPAL $queue = DrupalQueue::get('aggregator_feeds');  foreach ($result as $feed) {     if ($queue->createItem($feed)) {       // Add timestamp to avoid queueing item more than once.       db_update('aggregator_feed')         ->fields(array('queued' => REQUEST_TIME))         ->condition('fid', $feed->fid)         ->execute();     }   } Drupalcamp Bucharest 2011
  • 24.
    DRUPAL function aggregator_cron_queue_info() { $queues['aggregator_feeds'] = array( 'worker callback' => 'aggregator_refresh', 'time' => 60, ); return $queues; } Drupalcamp Bucharest 2011
  • 25.
    FILE API • Uses streams • public://file.txt • private://file.txt • temporary://file.txt • PHP’s provided: http://, ftp:// • A module can create a new stream Drupalcamp Bucharest 2011
  • 26.
    FILE API • No more public or private • Uses streams • public://file.txt, private://file.txt, temporary://file.txt Drupalcamp Bucharest 2011
  • 27.
    FILE API • Managed and unmanaged files • file_copy / file_unmanaged_copy • PHP’s provided: http://, ftp:// • A module can create a new stream Drupalcamp Bucharest 2011
  • 28.
    FILE API function file_example_stream_wrappers(){ $wrappers = array( 'session' => array( 'name' => t('Example: $_SESSION variable storage'), 'class' => 'FileExampleSessionStreamWrapper', 'description' => t('Store files in the $_SESSION variable as an example.'), ), ); return $wrappers; } Drupalcamp Bucharest 2011
  • 29.
    THANK andu@ctrlz.ro http://ctrlz.ro Drupalcamp Bucharest 2011