Upgrade Your Drupal Skills

We trained 1,000+ Drupal Developers over the last decade.

See Advanced Courses NAH, I know Enough

Tip of the day: Standalone DBTNG outside Drupal

Parent Feed: 

A few days ago, while I was writing a bit of Silex code and grumbling at Doctrine DBAL's lack of support for a SQL Merge operation, I wondered if it wouldn't be possible to use DBTNG without the rest of Drupal.

Obviously, although DBTNG is described as having been designed for standalone use: DBTNG should be a stand-alone library with no external dependences other than PHP 5.2 and the PDO database library, in actual use, the Github DBTNG repo has seen no commit in the last 3 years, and the D8 version is still not a Drupal 8 "Component" (i.e. decoupled code), but still a plain library with Drupal dependencies. How would it fare on its own ? Let's give it a try...

Bring DBTNG to a non-Drupal Composer project

Since Composer does not support sparse checkouts (yet ?), the simplest way to do bring in DBTNG for this little test is to just import the code manually and declare it to the autoloader manually. Let's start by getting just DBTNG out of the latest Drupal 8 checkout:

# Create a fresh repository to hold the example
mkdir dbtng_example
cd dbtng_example
git init

# Declare a remote
git remote add drupal http://git.drupal.org/project/drupal.git

# Enable sparse checkouts to just checkout DBTNG
git config core.sparsecheckout true

# Declare just what we want to checkout:
# 1. The DBTNG classes
echo core/lib/Drupal/Core/Database >> .git/info/sparse-checkout
# 2. The procedural wrappers, for simplicity in an example
echo core/includes/database.inc >> .git/info/sparse-checkout

# And checkout DBTNG
git pull drupal 8.x

ls -l core/
total 8
drwxrwxr-x 2 marand www-data 4096 févr.  8 09:32 includes
drwxrwxr-x 3 marand www-data 4096 févr.  8 09:32 lib
That's it: DBTNG classes are now available in core/lib/Drupal/Core/Database. We can now build a Composer file with PSR-4 autoloading on that code:
{
  "autoload": {
    "psr-4": {
      "Drupal\\Core\\Database\\": "core/lib/Drupal/Core/Database/"
    }
  },
  "description": "Drupal Database API as a standalone component",
  "license": "GPL-2.0+",
}
We can now build the autoloader:
php composer.phar install

Build the demo app

For this example, we can use the traditional settings.php configuration for DBTNG, say we store it in app/config/settings.php and point to a typical Drupal 8 MySQL single-server database:

<?php
// app/config/settings.php$databases['default']['default'] = array (
 
'database' => 'somedrupal8db',
 
'username' => 'someuser',
 
'password' => 'somepass',
 
'prefix' => '',
 
'host' => 'localhost',
 
'port' => '',
 
'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql',
 
'driver' => 'mysql',
);
?>

At this point, our dependencies are ready, let's build some Hello, world in app/hellodbtng.php. Since this is just an example, we will just list a table using the DBTNG Select query builder:

<?php
// app/hellodbtng.php

// Bring in the Composer autoloader.

require_once __DIR__ . '/../vendor/autoload.php';// Bring in the DBTNG procerural wrappers.
// @see https://wiki.php.net/rfc/function_autoloading
require_once __DIR__ . '/../core/includes/database.inc';// Finally load DBTNG configuration.
require_once __DIR__ . '/config/settings.php';$columns = array(
 
'collection',
 
'name',
 
'value',
);
// DBTNG FTW !
$result = db_select('key_value', 'kv')
  ->
fields('kv', $columns)
  ->
condition('kv.collection', 'system.schema')
  ->
range(0, 10)
  ->
execute();

foreach (

$result as $v) {
 
$v = (array) $v;
 
$value = print_r(unserialize($v['value']), true);
 
printf("%-32s %-32s %s\n", $v['collection'], $v['name'], $value);
}
?>

Enjoy the query results

php app/hellodbtng.php

system.schema                    block                            8000
system.schema                    breakpoint                       8000
system.schema                    ckeditor                         8000
system.schema                    color                            8000
system.schema                    comment                          8000
system.schema                    config                           8000
system.schema                    contact                          8000
system.schema                    contextual                       8000
system.schema                    custom_block                     8000
system.schema                    datetime                         8000

Going further

In real life:

  • a production project would hopefully not be built like this, by manually extracting files from a repo
  • ... and it would probably not use the procedural wrappers, but wrap DBTNG in a service and pass it configuration using a DIC
  • I seem to remember a discussion in which the full decoupling of DBTNG for D8 was considered but postponed as nice-to-have rather than essential for Drupal 8.0.
  • Which means that a simple integration would probably either
    • use the currently available (but obsolete) pre-7.0 version straight from Github (since that package is not available on Packagist, just declare it directly in composer.json as explained on http://www.craftitonline.com/2012/03/how-to-use-composer-without-packagi... ),
    • or (better) do the required work to decouple DBTNG from D8 core and submit a core patch for that decoupled version, and use it from the newly-independent DBTNG Component.
Original Post: 

About Drupal Sun

Drupal Sun is an Evolving Web project. It allows you to:

  • Do full-text search on all the articles in Drupal Planet (thanks to Apache Solr)
  • Facet based on tags, author, or feed
  • Flip through articles quickly (with j/k or arrow keys) to find what you're interested in
  • View the entire article text inline, or in the context of the site where it was created

See the blog post at Evolving Web

Evolving Web