Upload
ddiers
View
2.391
Download
2
Embed Size (px)
DESCRIPTION
Drupal database api presentation - given to austin adug 10/18/12
Citation preview
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
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
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.
Drupal and DB Abstraction ! What is DB Abstraction?
! Uniformity ! Structure
! DB Abstraction is nothing new for Drupal
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
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™?
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?
Using the DB API ! 2 Primary ways to interact
with data in D7 ! Dbquery ! Dynamic queries
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,));
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
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
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 ).
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.
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();
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
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);
But which should I use?
dbquery or dynamic query
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.
More with Dynamic Queries ! How to add fields or select * ! Conditional Statements ! AND / OR ! Sub-selects ! JOINS ! SORT
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
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');
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');
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.
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();
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');
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'); ?>
dynamic queries: sorting ! orderBy(‘field’, ‘ASC’/’DESC’)
$result = db_select(‘node’, ‘n’) ->fields(‘n’, array(‘title’)) ->orderBy(‘n.created’, ‘DESC’) ->execute();
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)
What about the others? ! db_update, db_insert,
db_delete ! Similar syntax ! Assemble and execute.
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)
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
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
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
TIME FOR BONUS ROUND YUB NUB
What is the ? Now that you have Drupal DB Chops You may start to consider…
To VIEWS or not to VIEWS
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 )
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
Questions and Thank you!
David Diers, Developer Four Kitchens [email protected] D.O - thebruce @beautyhammer