drupal - dbtng 25th anniversary edition

39
Drupal DataBase The next Generation Drupal for the Enterprise. David Diers, Developer Four Kitchens Austin, TX D.O - thebruce @beautyhammer Austin Drupal User’s Group

Upload: ddiers

Post on 09-Jul-2015

2.391 views

Category:

Technology


2 download

DESCRIPTION

Drupal database api presentation - given to austin adug 10/18/12

TRANSCRIPT

Page 1: Drupal - dbtng 25th Anniversary Edition

Drupal DataBase The next Generation

Drupal for the Enterprise.

David Diers, Developer Four Kitchens Austin, TX D.O - thebruce @beautyhammer

Austin Drupal User’s Group

Page 2: Drupal - dbtng 25th Anniversary Edition

What we’ll cover !  Basics of the Drupal DB API !  Using db_query !  Using and building dynamic queries including

!  Criteria clauses, joins, sorting, sub-selects, extenders, and tagging

!  How to work with result sets

Page 3: Drupal - dbtng 25th Anniversary Edition

Drupal and the DB !  Drupal uses the DB to:

!  Store content - where "content" is thought of very broadly.

!  Store user or module configurations

!  Store system values !  Drupal retrieves these values

all of the time.

Page 4: Drupal - dbtng 25th Anniversary Edition

Drupal and DB Abstraction !  What is DB Abstraction?

!  Uniformity !  Structure

!  DB Abstraction is nothing new for Drupal

Page 5: Drupal - dbtng 25th Anniversary Edition

Drupal 7 DB API uses PDO !  D7 had a facelift for DB Layer !  Built on PDO

!  PDO is PHPOOP !  Drupal extends PDO classes !  PDO used in many projects

Page 6: Drupal - dbtng 25th Anniversary Edition

It takes some learning. So why learn the DB API? !  You may say, with all due

respect: !  Isn’t most of this stuff in

functions already? !  Doesn’t views do this for

me? !  Can’t I just use raw SQL

like they did in ye olde days™?

Page 7: Drupal - dbtng 25th Anniversary Edition

A few reasons: !   Need a result set that you can’t get or requires custom

views development? !   Writing or supporting custom modules with their own

schema? !   Need results from the contrib module’s schema but there

isn’t a function to do so? !   Patching an existing modules’ database functionality? !   Need additional ways besides exportables (features, views,

panels) to migrate configuration via update hooks? !   Need to implement custom sql statements to improve the

performance of your site?

Page 8: Drupal - dbtng 25th Anniversary Edition

Using the DB API !  2 Primary ways to interact

with data in D7 ! Dbquery !  Dynamic queries

Page 9: Drupal - dbtng 25th Anniversary Edition

db_query – the basics !   IN SQL:

SELECT nid, title FROM node WHERE type = ‘article’;

!   IN db_query: <?php $type = ‘article’; $result = db_query("SELECT nid, title FROM {node} WHERE type = :type", array(':type' => $type,));

Page 10: Drupal - dbtng 25th Anniversary Edition

db_query – the breakdown $result = db_query("SELECT nid, title FROM {node} WHERE type = :type", array(':type' => $type,));

! db_query($query, $placeholders, $options) !   enclose tables in { } !   Placeholders start with ":"

!  EX: WHERE type = :type", array(':type' => 'page',)) !   Options array - 2 common ones are:

!  Target (default or slave) !  Fetch (pdo fetch type)

http://druptest7.dev:8888/example_dbq

Page 11: Drupal - dbtng 25th Anniversary Edition

db_query d6 => d7 transitions !   In transitioning D6 db_query to D7 be aware:

!  The syntax signature has changed – •  D6 parameters were less orderly •  % syntax for placeholders •  Lawless, unregulated SQL could be executed like a

dishonorable Klingon

Page 12: Drupal - dbtng 25th Anniversary Edition

Dynamic sql – the basics !  Dynamic Queries

!  Much more transportable, powerful, but complex !  You MUST use for ( INSERT, UPDATE,

DELETE) !  You may use for (SELECT)

•  http://www.lullabot.com/articles/simplify-your-code-with-drupal-7s-database-api ).

Page 13: Drupal - dbtng 25th Anniversary Edition

db_select – the basics !   IN SQL:

SELECT nid, title FROM node WHERE type = ‘article’;

!   IN db_select: <?php $type = ‘article’; $query = db_select(‘node’, ’n’); $result = $query->fields(‘n’, array(‘nid’,’title’) ->condition(‘n.type’,$type) ->execute();

Note: This is an example for comparison, selects are better served by dbquery.

Page 14: Drupal - dbtng 25th Anniversary Edition

db_select – the basics

(‘node’, ‘n’) Name of Table / Alias (fields(‘n’, array(‘nid’, ‘title’)) Alias, array of fields Single quotes are important for transferability.

!   IN db_select: <?php $type = ‘article’; $query = db_select(‘node’, ’n’); $result = $query->fields(‘n’, array(‘nid’,’title’) ->condition(‘n.type’,$type) ->execute();

Page 15: Drupal - dbtng 25th Anniversary Edition

DQ– of special note $query = db_select(‘node’, ’n’); $result = $query->fields(‘n’, array(‘nid’,’title’) ->condition(‘n.type’,$type) ->execute(); !  Fluid Interface !   ->execute(); !  Returns a result set / statement object

Page 16: Drupal - dbtng 25th Anniversary Edition

Working with Result Sets !   Use - foreach loop or !   or - Specificaly get the next record

!  $record = $result->fetch(); // Use the default fetch mode.

!   $record = $result->fetchObject(); // Fetch as a stdClass object.

!   $record = $result->fetchAssoc(); // Fetch as an associative array.

!   or - to get a single field !  $record = $result->fetchField($column_index);

Page 17: Drupal - dbtng 25th Anniversary Edition

But which should I use?

dbquery or dynamic query

Page 18: Drupal - dbtng 25th Anniversary Edition

Questions to help decide !   Is your query static? Use db_query it is faster. !  Does your query need to be constructed at run

time? Use dynamic queries !  Do you need to INSERT, UPDATE, or DELETE?

Use Dynamic queries.

Page 19: Drupal - dbtng 25th Anniversary Edition

More with Dynamic Queries !  How to add fields or select * !  Conditional Statements !  AND / OR !  Sub-selects !   JOINS !  SORT

Page 20: Drupal - dbtng 25th Anniversary Edition

Working with Fields !   Adding fields to a query:

$query->fields('n', array('nid', 'title', 'created', 'uid')); "select *" is fields with no field array indicated: $query->fields('n'); http://druptest7.dev:8888/example_dyn

Page 21: Drupal - dbtng 25th Anniversary Edition

Conditional Statements !   Signature: $query->condition($field, $value = NULL,

$operator = '=') Default operator is SQL =

!   can take ANSI sql comparators <, >, LIKE, = >= !  EX: $query->condition('nid',1) !  EX: $query->condition('nid',1, '<>')

!   In or between: !  EX: $query->condition('myfield', array(1, 2, 3), 'IN');

Page 22: Drupal - dbtng 25th Anniversary Edition

Conditional Statements (more) !   Nested Conditionals:

db_and() / db_or() / db_xor() are used to handle nested conditionals such as: ->condition(db_or()

->condition('field2', 5) ->condition('field3', 6)) Testing for NULL: $query->isNull('myfield'); $query->isNotNull('myfield');

Page 23: Drupal - dbtng 25th Anniversary Edition

An example from contrib…

!  Original d6 query: $result = db_query('SELECT * FROM {users} WHERE ((access <> 0 AND login <> 0 AND access < (%d - %d)) OR (login = 0 AND created < (%d - %d))) AND uid <> 1', REQUEST_TIME, $warn_time, REQUEST_TIME, $warn_time);

…ah, contrib.

Page 24: Drupal - dbtng 25th Anniversary Edition

Now In dynamic query format !   $query = db_select('users', 'u'); !   $query->fields('u', array('uid', 'name', 'mail', 'created', 'access')) !   ->condition(db_or() !   ->condition(db_and() !   ->condition('u.access', 0, '<>') !   ->condition('u.login', 0, '<>') !   ->condition('u.access', REQUEST_TIME - $warn_time, '<')) !   ->condition(db_and() !   ->condition('u.login', 0) !   ->condition('u.created', REQUEST_TIME - $warn_time, '<')) !   ) !   ->condition('u.uid', 1, '<>');

!   $results = $query->execute();

Page 25: Drupal - dbtng 25th Anniversary Edition

Subselects

! Subselects - form a query using dbtng then instead of executing it -

!  use that query variable in a condition. !  Best when:

•  one value is returned, •  A column return value is used with an IN clause.

!  $query->condition('myfield', $querysubselect, 'IN');

Page 26: Drupal - dbtng 25th Anniversary Edition

JOINS & db_select <?php $query = db_select('node', 'n'); $query->join('field_data_body', 'b', 'n.nid = b.entity_id'); $query ->fields('n', array('nid', 'title')) ->condition('n.type', 'page') ->condition('n.status', '1') ->orderBy('n.created', 'DESC') ->addTag('node_access'); ?>

Page 27: Drupal - dbtng 25th Anniversary Edition

dynamic queries: sorting ! orderBy(‘field’, ‘ASC’/’DESC’)

$result = db_select(‘node’, ‘n’) ->fields(‘n’, array(‘title’)) ->orderBy(‘n.created’, ‘DESC’) ->execute();

Page 28: Drupal - dbtng 25th Anniversary Edition

db_select Tagging Tagging – lets alter hooks take action ex: $query->addTag('node_access'); - this should be implemented on all queries that retrieve nodes. Node access query alter will then check to see if a user can see the nodes in the result. (http://druptest7.dev:8888/example_tag)

Page 29: Drupal - dbtng 25th Anniversary Edition

What about the others? ! db_update, db_insert,

db_delete !  Similar syntax !  Assemble and execute.

Page 30: Drupal - dbtng 25th Anniversary Edition

db_insert !   Syntax: $query = db_insert('node', $options);

$nid = db_insert('node') ->fields(array( 'title' => ’This Example', 'uid' => 1, 'created' => REQUEST_TIME, )) ->execute(); db_insert returns the auto-increment value defined by hook_schema.

(http://druptest7.dev:8888/example_insert)

Page 31: Drupal - dbtng 25th Anniversary Edition

db_update $num_updated = db_update('node') ->fields(array( 'uid' => 1 )) ->condition('uid', 2) ->execute(); db_update returns the number of records updated.

http://druptest7.dev:8888/example_update

Page 32: Drupal - dbtng 25th Anniversary Edition

db_delete

Signature: $query = db_delete('node', $options); $num_deleted = db_delete('node') ->condition('nid', 5) ->execute(); db_delete returns the number of rows deleted.

http://druptest7.dev:8888/example_delete

Page 33: Drupal - dbtng 25th Anniversary Edition

db_select extenders !   Extenders - implements a decorator pattern, currently only 2 !  

TableSort and PagerQuery = adds the methods for these extension to query

!   example: $query = $query ->extend('TableSort') ->orderByHeader($header);

!   Put these near the start. !   Not chainable, if you forget to return it to itself it will have odd

results.

http://druptest7.dev:8888/example_extend

Page 34: Drupal - dbtng 25th Anniversary Edition

TIME FOR BONUS ROUND YUB NUB

Page 35: Drupal - dbtng 25th Anniversary Edition

What is the ? Now that you have Drupal DB Chops You may start to consider…

To VIEWS or not to VIEWS

Page 36: Drupal - dbtng 25th Anniversary Edition

DB API an Alternative to Views !   Who will maintain the functionality? !   Does it require a lot of custom views code? !   Are you doing a lot of aggregated data work? !   Do you need a highly tuned SQL statement for performance? !   Do you need a lot of user facing, non programmer modifications,

will site builders be cloning views or modifying displays? !   Are you integrating with other modules (panels, voting, etc)? !   How complex are the changes you need to views default

queries/output?

To views or not to views (http://drupal.org/node/242311 )

Page 37: Drupal - dbtng 25th Anniversary Edition

Quick case study: •  Client wanted private comments •  Client wanted to see a listing of all comments

made against all nodes •  Views can do this but it is described as “hacky” •  Created a db_select with pager and table

extenders

Page 38: Drupal - dbtng 25th Anniversary Edition

Questions and Thank you!

David Diers, Developer Four Kitchens [email protected] D.O - thebruce @beautyhammer

Page 39: Drupal - dbtng 25th Anniversary Edition