123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711 |
- <?php
- /** @file
- * This package contains classes for handling database transactions from
- * within QueryPath.
- *
- * The tools here use the PDO (PHP Data Objects) library to execute database
- * functions.
- *
- * Using tools in this package, you can write QueryPath database queries
- * that query an RDBMS and then insert the results into the document.
- *
- * Example:
- *
- * @code
- * <?php
- * $template = '<?xml version="1.0"?><tr><td class="colOne"/><td class="colTwo"/><td class="colThree"/></tr>';
- * $qp = qp(QueryPath::HTML_STUB, 'body') // Open a stub HTML doc and select <body/>
- * ->append('<table><tbody/></table>')
- * ->dbInit($this->dsn)
- * ->queryInto('SELECT * FROM qpdb_test WHERE 1', array(), $template)
- * ->doneWithQuery()
- * ->writeHTML();
- * ?>
- * @endcode
- *
- * The code above will take the results of a SQL query and insert them into a n
- * HTML table.
- *
- * If you are doing many database operations across multiple QueryPath objects,
- * it is better to avoid using {@link QPDB::dbInit()}. Instead, you should
- * call the static {@link QPDB::baseDB()} method to configure a single database
- * connection that can be shared by all {@link QueryPath} instances.
- *
- * Thus, we could rewrite the above to look like this:
- * @code
- * <?php
- * QPDB::baseDB($someDN);
- *
- * $template = '<?xml version="1.0"?><tr><td class="colOne"/><td class="colTwo"/><td class="colThree"/></tr>';
- * $qp = qp(QueryPath::HTML_STUB, 'body') // Open a stub HTML doc and select <body/>
- * ->append('<table><tbody/></table>')
- * ->queryInto('SELECT * FROM qpdb_test WHERE 1', array(), $template)
- * ->doneWithQuery()
- * ->writeHTML();
- * ?>
- * @endcode
- *
- * Note that in this case, the QueryPath object doesn't need to call a method to
- * activate the database. There is no call to {@link dbInit()}. Instead, it checks
- * the base class to find the shared database.
- *
- * (Note that if you were to add a dbInit() call to the above, it would create
- * a new database connection.)
- *
- * The result of both of these examples will be identical.
- * The output looks something like this:
- *
- * @code
- * <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
- * <html xmlns="http://www.w3.org/1999/xhtml">
- * <head>
- * <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
- * <title>Untitled</title>
- * </head>
- *<body>
- *<table>
- * <tbody>
- * <tr>
- * <td class="colOne">Title 0</td>
- * <td class="colTwo">Body 0</td>
- * <td class="colThree">Footer 0</td>
- * </tr>
- * <tr>
- * <td class="colOne">Title 1</td>
- * <td class="colTwo">Body 1</td>
- * <td class="colThree">Footer 1</td>
- * </tr>
- * <tr>
- * <td class="colOne">Title 2</td>
- * <td class="colTwo">Body 2</td>
- * <td class="colThree">Footer 2</td>
- * </tr>
- * <tr>
- * <td class="colOne">Title 3</td>
- * <td class="colTwo">Body 3</td>
- * <td class="colThree">Footer 3</td>
- * </tr>
- * <tr>
- * <td class="colOne">Title 4</td>
- * <td class="colTwo">Body 4</td>
- * <td class="colThree">Footer 4</td>
- * </tr>
- * </tbody>
- *</table>
- *</body>
- *</html>
- * @endcode
- *
- * Note how the CSS classes are used to correlate DB table names to template
- * locations.
- *
- *
- * @author M Butcher <matt@aleph-null.tv>
- * @license http://opensource.org/licenses/lgpl-2.1.php LGPL or MIT-like license.
- * @see QueryPathExtension
- * @see QueryPathExtensionRegistry::extend()
- * @see QPDB
- */
-
- /**
- * Provide DB access to a QueryPath object.
- *
- * This extension provides tools for communicating with a database using the
- * QueryPath library. It relies upon PDO for underlying database communiction. This
- * means that it supports all databases that PDO supports, including MySQL,
- * PostgreSQL, and SQLite.
- *
- * Here is an extended example taken from the unit tests for this library.
- *
- * Let's say we create a database with code like this:
- * @code
- *<?php
- * public function setUp() {
- * $this->db = new PDO($this->dsn);
- * $this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
- * $this->db->exec('CREATE TABLE IF NOT EXISTS qpdb_test (colOne, colTwo, colThree)');
- *
- * $stmt = $this->db->prepare(
- * 'INSERT INTO qpdb_test (colOne, colTwo, colThree) VALUES (:one, :two, :three)'
- * );
- *
- * for ($i = 0; $i < 5; ++$i) {
- * $vals = array(':one' => 'Title ' . $i, ':two' => 'Body ' . $i, ':three' => 'Footer ' . $i);
- * $stmt->execute($vals);
- * $stmt->closeCursor();
- * }
- * }
- * ?>
- * @endcode
- *
- * From QueryPath with QPDB, we can now do very elaborate DB chains like this:
- *
- * @code
- * <?php
- * $sql = 'SELECT * FROM qpdb_test';
- * $args = array();
- * $qp = qp(QueryPath::HTML_STUB, 'body') // Open a stub HTML doc and select <body/>
- * ->append('<h1></h1>') // Add <h1/>
- * ->children() // Select the <h1/>
- * ->dbInit($this->dsn) // Connect to the database
- * ->query($sql, $args) // Execute the SQL query
- * ->nextRow() // Select a row. By default, no row is selected.
- * ->appendColumn('colOne') // Append Row 1, Col 1 (Title 0)
- * ->parent() // Go back to the <body/>
- * ->append('<p/>') // Append a <p/> to the body
- * ->find('p') // Find the <p/> we just created.
- * ->nextRow() // Advance to row 2
- * ->prependColumn('colTwo') // Get row 2, col 2. (Body 1)
- * ->columnAfter('colThree') // Get row 2 col 3. (Footer 1)
- * ->doneWithQuery() // Let QueryPath clean up. YOU SHOULD ALWAYS DO THIS.
- * ->writeHTML(); // Write the output as HTML.
- * ?>
- * @endcode
- *
- * With the code above, we step through the document, selectively building elements
- * as we go, and then populating this elements with data from our initial query.
- *
- * When the last command, {@link QueryPath:::writeHTML()}, is run, we will get output
- * like this:
- *
- * @code
- * <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
- * <html xmlns="http://www.w3.org/1999/xhtml">
- * <head>
- * <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- * <title>Untitled</title>
- * </head>
- * <body>
- * <h1>Title 0</h1>
- * <p>Body 1</p>
- * Footer 1</body>
- * </html>
- * @endcode
- *
- * Notice the body section in particular. This is where the data has been
- * inserted.
- *
- * Sometimes you want to do something a lot simpler, like give QueryPath a
- * template and have it navigate a query, inserting the data into a template, and
- * then inserting the template into the document. This can be done simply with
- * the {@link queryInto()} function.
- *
- * Here's an example from another unit test:
- *
- * @code
- * <?php
- * $template = '<?xml version="1.0"?><li class="colOne"/>';
- * $sql = 'SELECT * FROM qpdb_test';
- * $args = array();
- * $qp = qp(QueryPath::HTML_STUB, 'body')
- * ->append('<ul/>') // Add a new <ul/>
- * ->children() // Select the <ul/>
- * ->dbInit($this->dsn) // Initialize the DB
- * // BIG LINE: Query the results, run them through the template, and insert them.
- * ->queryInto($sql, $args, $template)
- * ->doneWithQuery()
- * ->writeHTML(); // Write the results as HTML.
- * ?>
- * @endcode
- *
- * The simple code above puts the first column of the select statement
- * into an unordered list. The example output looks like this:
- *
- * @code
- * <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
- * <html xmlns="http://www.w3.org/1999/xhtml">
- * <head>
- * <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
- * <title>Untitled</title>
- * </head>
- * <body>
- * <ul>
- * <li class="colOne">Title 0</li>
- * <li class="colOne">Title 1</li>
- * <li class="colOne">Title 2</li>
- * <li class="colOne">Title 3</li>
- * <li class="colOne">Title 4</li>
- * </ul>
- * </body>
- * </html>
- * @endcode
- *
- * Typical starting methods for this class are {@link QPDB::baseDB()},
- * {@link QPDB::query()}, and {@link QPDB::queryInto()}.
- *
- * @ingroup querypath_extensions
- */
- class QPDB implements QueryPathExtension {
- protected $qp;
- protected $dsn;
- protected $db;
- protected $opts;
- protected $row = NULL;
- protected $stmt = NULL;
-
- protected static $con = NULL;
-
- /**
- * Create a new database instance for all QueryPath objects to share.
- *
- * This method need be called only once. From there, other QPDB instances
- * will (by default) share the same database instance.
- *
- * Normally, a DSN should be passed in. Username, password, and db params
- * are all passed in using the options array.
- *
- * On rare occasions, it may be more fitting to pass in an existing database
- * connection (which must be a {@link PDO} object). In such cases, the $dsn
- * parameter can take a PDO object instead of a DSN string. The standard options
- * will be ignored, though.
- *
- * <b>Warning:</b> If you pass in a PDO object that is configured to NOT throw
- * exceptions, you will need to handle error checking differently.
- *
- * <b>Remember to always use {@link QPDB::doneWithQuery()} when you are done
- * with a query. It gives PDO a chance to clean up open connections that may
- * prevent other instances from accessing or modifying data.</b>
- *
- * @param string $dsn
- * The DSN of the database to connect to. You can also pass in a PDO object, which
- * will set the QPDB object's database to the one passed in.
- * @param array $options
- * An array of configuration options. The following options are currently supported:
- * - username => (string)
- * - password => (string)
- * - db params => (array) These will be passed into the new PDO object.
- * See the PDO documentation for a list of options. By default, the
- * only flag set is {@link PDO::ATTR_ERRMODE}, which is set to
- * {@link PDO::ERRMODE_EXCEPTION}.
- * @throws PDOException
- * An exception may be thrown if the connection cannot be made.
- */
- static function baseDB($dsn, $options = array()) {
-
- $opts = $options + array(
- 'username' => NULL,
- 'password' => NULL,
- 'db params' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION),
- );
-
- // Allow this to handle the case where an outside
- // connection does the initialization.
- if ($dsn instanceof PDO) {
- self::$con = $dsn;
- return;
- }
- self::$con = new PDO($dsn, $opts['username'], $opts['password'], $opts['db params']);
- }
-
- /**
- *
- * This method may be used to share the connection with other,
- * non-QueryPath objects.
- */
- static function getBaseDB() {return self::$con;}
-
- /**
- * Used to control whether or not all rows in a result should be cycled through.
- */
- protected $cycleRows = FALSE;
-
- /**
- * Construct a new QPDB object. This is usually done by QueryPath itself.
- */
- public function __construct(QueryPath $qp) {
- $this->qp = $qp;
- // By default, we set it up to use the base DB.
- $this->db = self::$con;
- }
-
- /**
- * Create a new connection to the database. Use the PDO DSN syntax for a
- * connection string.
- *
- * This creates a database connection that will last for the duration of
- * the QueryPath object. This method ought to be used only in two cases:
- * - When you will only run a couple of queries during the life of the
- * process.
- * - When you need to connect to a database that will only be used for
- * a few things.
- * Otherwise, you should use {@link QPDB::baseDB} to configure a single
- * database connection that all of {@link QueryPath} can share.
- *
- * <b>Remember to always use {@link QPDB::doneWithQuery()} when you are done
- * with a query. It gives PDO a chance to clean up open connections that may
- * prevent other instances from accessing or modifying data.</b>
- *
- * @param string $dsn
- * The PDO DSN connection string.
- * @param array $options
- * Connection options. The following options are supported:
- * - username => (string)
- * - password => (string)
- * - db params => (array) These will be passed into the new PDO object.
- * See the PDO documentation for a list of options. By default, the
- * only flag set is {@link PDO::ATTR_ERRMODE}, which is set to
- * {@link PDO::ERRMODE_EXCEPTION}.
- * @return QueryPath
- * The QueryPath object.
- * @throws PDOException
- * The PDO library is configured to throw exceptions, so any of the
- * database functions may throw a PDOException.
- */
- public function dbInit($dsn, $options = array()) {
- $this->opts = $options + array(
- 'username' => NULL,
- 'password' => NULL,
- 'db params' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION),
- );
- $this->dsn = $dsn;
- $this->db = new PDO($dsn, $this->opts['username'], $this->opts['password'], $this->opts['db params']);
- /*
- foreach ($this->opts['db params'] as $key => $val)
- $this->db->setAttribute($key, $val);
- */
-
- return $this->qp;
- }
-
- /**
- * Execute a SQL query, and store the results.
- *
- * This will execute a SQL query (as a prepared statement), and then store
- * the results internally for later use. The data can be iterated using
- * {@link nextRow()}. QueryPath can also be instructed to do internal iteration
- * using the {@link withEachRow()} method. Finally, on the occasion that the
- * statement itself is needed, {@link getStatement()} can be used.
- *
- * Use this when you need to access the results of a query, or when the
- * parameter to a query should be escaped. If the query takes no external
- * parameters and does not return results, you may wish to use the
- * (ever so slightly faster) {@link exec()} function instead.
- *
- * Make sure you use {@link doneWithQuery()} after finishing with the database
- * results returned by this method.
- *
- * <b>Usage</b>
- *
- * Here is a simple example:
- * <code>
- * <?php
- * QPQDB::baseDB($someDSN);
- *
- * $args = array(':something' => 'myColumn');
- * qp()->query('SELECT :something FROM foo', $args)->doneWithQuery();
- * ?>
- * </code>
- *
- * The above would execute the given query, substituting myColumn in place of
- * :something before executing the query The {@link doneWithQuery()} method
- * indicates that we are not going to use the results for anything. This method
- * discards the results.
- *
- * A more typical use of the query() function would involve inserting data
- * using {@link appendColumn()}, {@link prependColumn()}, {@link columnBefore()},
- * or {@link columnAfter()}. See the main documentation for {@link QPDB} to view
- * a more realistic example.
- *
- * @param string $sql
- * The query to be executed.
- * @param array $args
- * An associative array of substitutions to make.
- * @throws PDOException
- * Throws an exception if the query cannot be executed.
- */
- public function query($sql, $args = array()) {
- $this->stmt = $this->db->prepare($sql);
- $this->stmt->execute($args);
- return $this->qp;
- }
-
- /**
- * Query and append the results.
- *
- * Run a query and inject the results directly into the
- * elements in the QueryPath object.
- *
- * If the third argument is empty, the data will be inserted directly into
- * the QueryPath elements unaltered. However, if a template is provided in
- * the third parameter, the query data will be merged into that template
- * and then be added to each QueryPath element.
- *
- * The template will be merged once for each row, even if no row data is
- * appended into the template.
- *
- * A template is simply a piece of markup labeled for insertion of
- * data. See {@link QPTPL} and {@link QPTPL.php} for more information.
- *
- * Since this does not use a stanard {@link query()}, there is no need
- * to call {@link doneWithQuery()} after this method.
- *
- * @param string $sql
- * The SQL query to execute. In this context, the query is typically a
- * SELECT statement.
- * @param array $args
- * An array of arguments to be substituted into the query. See {@link query()}
- * for details.
- * @param mixed $template
- * A template into which query results will be merged prior to being appended
- * into the QueryPath. For details on the template, see {@link QPTPL::tpl()}.
- * @see QPTPL.php
- * @see QPTPL::tpl()
- * @see query()
- */
- public function queryInto($sql, $args = array(), $template = NULL) {
- $stmt = $this->db->prepare($sql);
- $stmt->setFetchMode(PDO::FETCH_ASSOC);
- $stmt->execute($args);
-
- // If no template, put all values in together.
- if (empty($template)) {
- foreach ($stmt as $row) foreach ($row as $datum) $this->qp->append($datum);
- }
- // Otherwise, we run the results through a template, and then append.
- else {
- foreach ($stmt as $row) $this->qp->tpl($template, $row);
- }
-
- $stmt->closeCursor();
- return $this->qp;
- }
-
- /**
- * Free up resources when a query is no longer used.
- *
- * This function should <i>always</i> be called when the database
- * results for a query are no longer needed. This frees up the
- * database cursor, discards the data, and resets resources for future
- * use.
- *
- * If this method is not called, some PDO database drivers will not allow
- * subsequent queries, while others will keep tables in a locked state where
- * writes will not be allowed.
- *
- * @return QueryPath
- * The QueryPath object.
- */
- public function doneWithQuery() {
- if (isset($this->stmt) && $this->stmt instanceof PDOStatement) {
- // Some drivers choke if results haven't been iterated.
- //while($this->stmt->fetch()) {}
- $this->stmt->closeCursor();
- }
-
- unset($this->stmt);
- $this->row = NULL;
- $this->cycleRows = FALSE;
- return $this->qp;
- }
-
- /**
- * Execute a SQL query, but expect no value.
- *
- * If your SQL query will have parameters, you are encouraged to
- * use {@link query()}, which includes built-in SQL Injection
- * protection.
- *
- * @param string $sql
- * A SQL statement.
- * @throws PDOException
- * An exception will be thrown if a query cannot be executed.
- */
- public function exec($sql) {
- $this->db->exec($sql);
- return $this->qp;
- }
-
- /**
- * Advance the query results row cursor.
- *
- * In a result set where more than one row was returned, this will
- * move the pointer to the next row in the set.
- *
- * The PDO library does not have a consistent way of determining how many
- * rows a result set has. The suggested technique is to first execute a
- * COUNT() SQL query and get the data from that.
- *
- * The {@link withEachRow()} method will begin at the next row after the
- * currently selected one.
- *
- * @return QueryPath
- * The QueryPath object.
- */
- public function nextRow() {
- $this->row = $this->stmt->fetch(PDO::FETCH_ASSOC);
- return $this->qp;
- }
-
- /**
- * Set the object to use each row, instead of only one row.
- *
- * This is used primarily to instruct QPDB to iterate through all of the
- * rows when appending, prepending, inserting before, or inserting after.
- *
- * @return QueryPath
- * The QueryPath object.
- * @see appendColumn()
- * @see prependColumn()
- * @see columnBefore()
- * @see columnAfter()
- */
- public function withEachRow() {
- $this->cycleRows = TRUE;
- return $this->qp;
- }
-
- /**
- * This is the implementation behind the append/prepend and before/after methods.
- *
- * @param mixed $columnName
- * The name of the column whose data should be added to the currently selected
- * elements. This can be either a string or an array of strings.
- * @param string $qpFunc
- * The name of the QueryPath function that should be executed to insert data
- * into the object.
- * @param string $wrap
- * The HTML/XML markup that will be used to wrap around the column data before
- * the data is inserted into the QueryPath object.
- */
- protected function addData($columnName, $qpFunc = 'append', $wrap = NULL) {
- $columns = is_array($columnName) ? $columnName : array($columnName);
- $hasWrap = !empty($wrap);
- if ($this->cycleRows) {
- while (($row = $this->stmt->fetch(PDO::FETCH_ASSOC)) !== FALSE) {
- foreach ($columns as $col) {
- if (isset($row[$col])) {
- $data = $row[$col];
- if ($hasWrap)
- $data = qp()->append($wrap)->deepest()->append($data)->top();
- $this->qp->$qpFunc($data);
- }
- }
- }
- $this->cycleRows = FALSE;
- $this->doneWithQuery();
- }
- else {
- if ($this->row !== FALSE) {
- foreach ($columns as $col) {
- if (isset($this->row[$col])) {
- $data = $this->row[$col];
- if ($hasWrap)
- $data = qp()->append($wrap)->deepest()->append($data)->top();
- $this->qp->$qpFunc($data);
- }
- }
- }
- }
- return $this->qp;
- }
-
- /**
- * Get back the raw PDOStatement object after a {@link query()}.
- *
- * @return PDOStatement
- * Return the PDO statement object. If this is called and no statement
- * has been executed (or the statement has already been cleaned up),
- * this will return NULL.
- */
- public function getStatement() {
- return $this->stmt;
- }
-
- /**
- * Get the last insert ID.
- *
- * This will only return a meaningful result when used after an INSERT.
- *
- * @return mixed
- * Return the ID from the last insert. The value and behavior of this
- * is database-dependent. See the official PDO driver documentation for
- * the database you are using.
- * @since 1.3
- */
- public function getLastInsertID() {
- $con = self::$con;
- return $con->lastInsertId();
- }
-
- /**
- * Append the data in the given column(s) to the QueryPath.
- *
- * This appends data to every item in the current QueryPath. The data will
- * be retrieved from the database result, using $columnName as the key.
- *
- * @param mixed $columnName
- * Either a string or an array of strings. The value(s) here should match
- * one or more column headers from the current SQL {@link query}'s results.
- * @param string $wrap
- * IF this is supplied, then the value or values retrieved from the database
- * will be wrapped in this HTML/XML before being inserted into the QueryPath.
- * @see QueryPath::wrap()
- * @see QueryPath::append()
- */
- public function appendColumn($columnName, $wrap = NULL) {
- return $this->addData($columnName, 'append', $wrap);
- }
-
- /**
- * Prepend the data from the given column into the QueryPath.
- *
- * This takes the data from the given column(s) and inserts it into each
- * element currently found in the QueryPath.
- * @param mixed $columnName
- * Either a string or an array of strings. The value(s) here should match
- * one or more column headers from the current SQL {@link query}'s results.
- * @param string $wrap
- * IF this is supplied, then the value or values retrieved from the database
- * will be wrapped in this HTML/XML before being inserted into the QueryPath.
- * @see QueryPath::wrap()
- * @see QueryPath::prepend()
- */
- public function prependColumn($columnName, $wrap = NULL) {
- return $this->addData($columnName, 'prepend', $wrap);
- }
-
- /**
- * Insert the data from the given column before each element in the QueryPath.
- *
- * This inserts the data before each element in the currently matched QueryPath.
- *
- * @param mixed $columnName
- * Either a string or an array of strings. The value(s) here should match
- * one or more column headers from the current SQL {@link query}'s results.
- * @param string $wrap
- * IF this is supplied, then the value or values retrieved from the database
- * will be wrapped in this HTML/XML before being inserted into the QueryPath.
- * @see QueryPath::wrap()
- * @see QueryPath::before()
- * @see prependColumn()
- */
- public function columnBefore($columnName, $wrap = NULL) {
- return $this->addData($columnName, 'before', $wrap);
- }
-
- /**
- * Insert data from the given column(s) after each element in the QueryPath.
- *
- * This inserts data from the given columns after each element in the QueryPath
- * object. IF HTML/XML is given in the $wrap parameter, then the column data
- * will be wrapped in that markup before being inserted into the QueryPath.
- *
- * @param mixed $columnName
- * Either a string or an array of strings. The value(s) here should match
- * one or more column headers from the current SQL {@link query}'s results.
- * @param string $wrap
- * IF this is supplied, then the value or values retrieved from the database
- * will be wrapped in this HTML/XML before being inserted into the QueryPath.
- * @see QueryPath::wrap()
- * @see QueryPath::after()
- * @see appendColumn()
- */
- public function columnAfter($columnName, $wrap = NULL) {
- return $this->addData($columnName, 'after', $wrap);
- }
-
- }
- // The define allows another class to extend this.
- if (!defined('QPDB_OVERRIDE'))
- QueryPathExtensionRegistry::extend('QPDB');
|