wethersherbs/pineapple

This package is abandoned and no longer maintained. The author suggests using the may-den/pineapple package instead.

An API-compatible replacement, forked from and for PEAR DB

v0.3.9 2023-01-27 13:47 UTC

README

An API-compatible replacement, forked from and for PEAR DB.

master v0.3-dev
Build Status Build Status

This repository has moved (is moving?)

From August 2022, this repository will move from https://github.com/wethersherbs/pineapple to https://github.com/may-den/pineapple. Older references should still work, an archived fork will remain on the older URL for compatibility purposes. Please update any references, bookmarks, and composer/packagist references accordingly.

What?

A compatibility layer around PDO or Doctrine DBAL to provide backward compatibility to PEAR DB-based applications.

It's close to (but is not) a drop-in replacement; You'll need to make modifications to your application, but they should be minimal.

Why?

PEAR DB is very old (the copyright range ends 9 years prior to Pineapple's inception), and was obsoleted by MDB2, which has in turn become obsolete. Projects have been based on these modules, but need an upgrade path that means new code can be developed using modern DB access methods, whilst retaining access for legacy code without opening a second database connection.

Ultimately, it'll provide backward compatibility for everything you've done, and leave you to write something more modern for your future work.

How?

This package is a fork of PEAR and DB, heavily refactored. The purpose of it is to provide a method-compatible drop-in replacement, reproducing PEAR::raiseError and PEAR::isError, and all methods under the DB class. Connection-specific drivers are dropped and only two connection drivers are included: DoctrineDbal, a driver which takes a constructed doctrine/dbal object, and PdoDriver, a driver which takes a constructed PDO object. It is intended only as a path to PDO or Doctrine DBAL migration, to keep legacy systems working whilst retaining a single database connection per application.

The intention is to strip unused methods, clean (remove all warnings and notices), make PSR-2 clean and provide full test coverage of the DB compatibility layer. Global constants will be replaced with class constants to maintain a clean constant namespace.

It is up to your application to cache the constructed database connection object. Please do not use Pineapple to retrieve your connection object after it has been dependency injected.

Usage

In Doctrine DBAL mode:

<?php

use Pineapple\DB;
use Pineapple\DB\Driver\DoctrineDbal;

// lengthy dbal connection here...

$db = DB::factory(DoctrineDbal::class);
$db->setConnectionHandle($dbalConn);
$result = $db->query('SELECT USER(), DATABASE()');

In PDO mode:

<?php

use Pineapple\DB;
use Pineapple\DB\Driver\PdoDriver;

$db = DB::factory(PdoDriver::class);
$db->setConnectionHandle(new PDO('sqlite::memory:'));
$result = $db->query('SELECT CURRENT_TIMESTAMP');

Integrating into your project

Changes to class names

Firstly, you should be aware of the following changes to class names. If you typehint, use instanceOf or methods which check class name, you will need to be aware of the follow changes to class names:

Old class New class
DB Pineapple\DB
DB_Error Pineapple\DB\Error
DB_result Pineapple\DB\Result
DB_row Pineapple\DB\Row
DB_common Pineapple\DB\Driver\Common
PEAR Pineapple\Util
PEAR_Error Pineapple\Error
PEAR_Exception Pineapple\Exception

### Changes to constants

Secondly, the PEAR_ and DB_ global constants (defines) are now class constants and will need to be scoped accordingly. Anything starting PEAR_ resides within Pineapple\Util, and anything starting DB_ resides within Pineapple\DB. We recommend namespace aliasing, e.g.:

<?php
use Pineapple\DB;

$query = $db->query('SELECT CURRENT_TIMESTAMP');
if (DB::isError($query) && $query->getCode() === DB::DB_ERROR_INVALID) {
    die();
}

Deprecated methods & variable access.

Thirdly, significant chunks of both PEAR and DB have been unapologetically stripped out and discarded. Anything within the PEAR class which is not:

  • isError
  • raiseError
  • throwError

...is now gone. Calling the above methods both as class methods and static methods is retained (it has been determined that both methods are in vigorous use in examined code).

All of the DSN handling code is removed from the DB (now Pineapple\DB) class. It exists purely as a construction factory for driver classes and an override for error handling. The following methods are retained (everything else, e.g. connect()) is now removed:

  • factory
  • isError
  • isConnection
  • errorMessage

Most significantly, the following methods have been removed from the driver classes:

Replace these with query placeholders (parameterised queries):

  • quoteString
  • quote

If DBMS-abstracted inspection is required, replace these with calls to Doctrine DBAL:

  • getTables
  • getSpecialQuery
  • getListOf

Sequence facilities should be implemented in SQL:

  • createSequence
  • dropSequence
  • getSequenceName
  • nextId

With the removal of the above methods, class variables are now a mixture of private & protected and will not be available to your application. Several "getters" (and some setters) have been provided for your convenience. See:

  • getOption (accompanying DB's setOption)
  • getFeature
  • getLastQuery
  • getFetchMode
  • getFetchModeObjectClass
  • getLastQuery
  • getLastParameters
  • getNativeErrorCode

Changes to the _db property of a constructed driver object in order to switch database on-the-fly have been replaced by calls to method changeDatabase.

Lastly, autoPrepare and autoExecute will no longer perform an UPDATE or DELETE without a WHERE clause. Change this behaviour by calling method setAcceptConsequencesOfPoorCodingChoices.

Code change summary

  • All classes are namespaced. See the table in the previous section for the class name mappings.
  • All global variables have now been dropped.
  • Global constants have been moved to class constants.
  • All connectivity drivers have been removed. The only drivers provided are DoctrineDbal and PdoDriver to connect with Doctrine's DBAL and PDO respectively, and it is intended that all connectivity be performed through one of these two layers.
  • All methods in PEAR have been dropped, except for isError, raiseError and throwError. This includes PEAR's pseudo-destructors (shutdown functions).
  • Compatibility names for legacy constructors and '_Name' destructors have been removed.
  • PEAR & DB Error suppression has been removed.
  • Large swathes of code put in place to aid multi-driver compatibility have been removed.
  • Spit, polish & PSR-2. Refactoring to support some more modern aspects of PHP (e.g. method statics replaced with class statics).
  • Three new exceptions for unhandled events (which would normally cause a die): DriverException, FeatureException, StatementException.
  • Don't use connect(), use factory() and set the connection using setConnectionHandle().

Test suite

A suite of tests to aid in regression testing whilst refactoring has been built. Every attempt to reach 100% coverage across all methods and classes has been made. Please ensure the test suite is run before submitting patches or pull requests.

A script to run the suite has been put into the project's composer.json file. To execute it, run:

$ composer test

Unfortunately, composer squashes the colourised output which helps indicate failures whilst running interactively. If you wish to view the output with colourisation, run:

$ vendor/bin/phpunit --coverage-html='coverage/' --coverage-text='php://stdout' --colors=auto

We recommend that all changes are tested across the support PHP matrix (5.6-8.1).

Credits

Pineapple is the work of:

A multitude of thanks should be given to Mayden for supporting the author to complete the initial release of Pineapple.

The DB authors should take the most credit; the source was forked in its entirety for the refactor.

The following credits were taken from DB:

And these from PEAR:

Please see the file "CONTRIBUTORS.md" for other attribution.

License

Upstream PEAR is distributed under the BSD 2-clause license. This license is retained. This applies to classes Util, Error and Exception.

Upstream DB is distributed under the PHP License http://php.net/license/, which is a BSD-style license. This license is retained. This applies to all other classes and includes DoctrineDbal, which is derived from DB_mysqli (no longer included in this package).

Any additional code or test suites are provided under the PHP License http://php.net/license/.