mirror of
https://github.com/dg/dibi.git
synced 2025-08-12 00:54:11 +02:00
* added DibiTable
* new connection options: "result:objects" & "result:withtables" * renamed DibiDriverInterface -> IDibiDriver, DibiVariableInterface -> IDibiVariable
This commit is contained in:
@@ -36,7 +36,7 @@ class DibiConnection extends NObject
|
||||
private $config;
|
||||
|
||||
/**
|
||||
* DibiDriverInterface
|
||||
* IDibiDriver
|
||||
* @var array
|
||||
*/
|
||||
private $driver;
|
||||
@@ -254,7 +254,7 @@ class DibiConnection extends NObject
|
||||
$time = -microtime(TRUE);
|
||||
dibi::notify($this, 'beforeQuery', $sql);
|
||||
|
||||
$res = $this->driver->query($sql) ? new DibiResult(clone $this->driver) : TRUE; // backward compatibility - will be changed to NULL
|
||||
$res = $this->driver->query($sql) ? new DibiResult(clone $this->driver, $this->config) : TRUE; // backward compatibility - will be changed to NULL
|
||||
|
||||
$time += microtime(TRUE);
|
||||
dibi::$elapsedTime = $time;
|
||||
|
@@ -26,6 +26,7 @@
|
||||
* $result = dibi::query('SELECT * FROM [table]');
|
||||
*
|
||||
* $row = $result->fetch();
|
||||
* $obj = $result->fetch(TRUE);
|
||||
* $value = $result->fetchSingle();
|
||||
* $table = $result->fetchAll();
|
||||
* $pairs = $result->fetchPairs();
|
||||
@@ -43,7 +44,7 @@
|
||||
class DibiResult extends NObject implements IteratorAggregate, Countable
|
||||
{
|
||||
/**
|
||||
* DibiDriverInterface
|
||||
* IDibiDriver
|
||||
* @var array
|
||||
*/
|
||||
private $driver;
|
||||
@@ -60,7 +61,6 @@ class DibiResult extends NObject implements IteratorAggregate, Countable
|
||||
*/
|
||||
private $metaCache;
|
||||
|
||||
|
||||
/**
|
||||
* Already fetched? Used for allowance for first seek(0)
|
||||
* @var bool
|
||||
@@ -73,6 +73,12 @@ class DibiResult extends NObject implements IteratorAggregate, Countable
|
||||
*/
|
||||
private $withTables = FALSE;
|
||||
|
||||
/**
|
||||
* Fetch as object?
|
||||
* @var bool
|
||||
*/
|
||||
public $asObjects = FALSE;
|
||||
|
||||
|
||||
|
||||
private static $types = array(
|
||||
@@ -85,13 +91,19 @@ class DibiResult extends NObject implements IteratorAggregate, Countable
|
||||
|
||||
|
||||
|
||||
|
||||
public function __construct($driver)
|
||||
/**
|
||||
* @param IDibiDriver
|
||||
* @param array
|
||||
*/
|
||||
public function __construct($driver, $config)
|
||||
{
|
||||
$this->driver = $driver;
|
||||
$this->setWithTables(!empty($config['result:withtables']));
|
||||
$this->asObjects = !empty($config['result:objects']);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Automatically frees the resources allocated for this result set
|
||||
*
|
||||
@@ -207,9 +219,10 @@ class DibiResult extends NObject implements IteratorAggregate, Countable
|
||||
* Fetches the row at current position, process optional type conversion
|
||||
* and moves the internal cursor to the next position
|
||||
*
|
||||
* @param bool fetch as object? Overrides $this->asObjects
|
||||
* @return array|FALSE array on success, FALSE if no next record
|
||||
*/
|
||||
final public function fetch()
|
||||
final public function fetch($asObject = NULL)
|
||||
{
|
||||
if ($this->withTables === FALSE) {
|
||||
$row = $this->getDriver()->fetch(TRUE);
|
||||
@@ -232,6 +245,10 @@ class DibiResult extends NObject implements IteratorAggregate, Countable
|
||||
}
|
||||
}
|
||||
|
||||
if ($asObject || ($asObject === NULL && $this->asObjects)) {
|
||||
$row = (object) $row;
|
||||
}
|
||||
|
||||
return $row;
|
||||
}
|
||||
|
||||
@@ -268,7 +285,7 @@ class DibiResult extends NObject implements IteratorAggregate, Countable
|
||||
final function fetchAll()
|
||||
{
|
||||
$this->seek(0);
|
||||
$row = $this->fetch();
|
||||
$row = $this->fetch(FALSE);
|
||||
if (!$row) return array(); // empty resultset
|
||||
|
||||
$data = array();
|
||||
@@ -276,10 +293,10 @@ class DibiResult extends NObject implements IteratorAggregate, Countable
|
||||
$key = key($row);
|
||||
do {
|
||||
$data[] = $row[$key];
|
||||
} while ($row = $this->fetch());
|
||||
} while ($row = $this->fetch(FALSE));
|
||||
|
||||
} else {
|
||||
|
||||
if ($this->asObjects) $row = (object) $row;
|
||||
do {
|
||||
$data[] = $row;
|
||||
} while ($row = $this->fetch());
|
||||
@@ -302,7 +319,7 @@ class DibiResult extends NObject implements IteratorAggregate, Countable
|
||||
final function fetchAssoc($assoc)
|
||||
{
|
||||
$this->seek(0);
|
||||
$row = $this->fetch();
|
||||
$row = $this->fetch(FALSE);
|
||||
if (!$row) return array(); // empty resultset
|
||||
|
||||
$data = NULL;
|
||||
@@ -366,7 +383,7 @@ class DibiResult extends NObject implements IteratorAggregate, Countable
|
||||
if ($leaf === '=') $x = $row; else $x = (object) $row;
|
||||
}
|
||||
|
||||
} while ($row = $this->fetch());
|
||||
} while ($row = $this->fetch(FALSE));
|
||||
|
||||
unset($x);
|
||||
return $data;
|
||||
@@ -385,7 +402,7 @@ class DibiResult extends NObject implements IteratorAggregate, Countable
|
||||
final function fetchPairs($key = NULL, $value = NULL)
|
||||
{
|
||||
$this->seek(0);
|
||||
$row = $this->fetch();
|
||||
$row = $this->fetch(FALSE);
|
||||
if (!$row) return array(); // empty resultset
|
||||
|
||||
$data = array();
|
||||
@@ -412,7 +429,7 @@ class DibiResult extends NObject implements IteratorAggregate, Countable
|
||||
if ($key === NULL) { // indexed-array
|
||||
do {
|
||||
$data[] = $row[$value];
|
||||
} while ($row = $this->fetch());
|
||||
} while ($row = $this->fetch(FALSE));
|
||||
return $data;
|
||||
}
|
||||
|
||||
@@ -423,7 +440,7 @@ class DibiResult extends NObject implements IteratorAggregate, Countable
|
||||
|
||||
do {
|
||||
$data[ $row[$key] ] = $row[$value];
|
||||
} while ($row = $this->fetch());
|
||||
} while ($row = $this->fetch(FALSE));
|
||||
|
||||
return $data;
|
||||
}
|
||||
@@ -558,7 +575,7 @@ class DibiResult extends NObject implements IteratorAggregate, Countable
|
||||
/**
|
||||
* Safe access to property $driver
|
||||
*
|
||||
* @return DibiDriverInterface
|
||||
* @return IDibiDriver
|
||||
* @throws DibiException
|
||||
*/
|
||||
private function getDriver()
|
||||
|
@@ -129,7 +129,7 @@ final class DibiResultIterator implements Iterator
|
||||
*/
|
||||
public function valid()
|
||||
{
|
||||
return is_array($this->row) && ($this->limit < 0 || $this->pointer < $this->limit);
|
||||
return !empty($this->row) && ($this->limit < 0 || $this->pointer < $this->limit);
|
||||
}
|
||||
|
||||
|
||||
|
248
dibi/libs/DibiTable.php
Normal file
248
dibi/libs/DibiTable.php
Normal file
@@ -0,0 +1,248 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* dibi - tiny'n'smart database abstraction layer
|
||||
* ----------------------------------------------
|
||||
*
|
||||
* Copyright (c) 2005, 2008 David Grudl aka -dgx- (http://www.dgx.cz)
|
||||
*
|
||||
* This source file is subject to the "dibi license" that is bundled
|
||||
* with this package in the file license.txt.
|
||||
*
|
||||
* For more information please see http://dibiphp.com/
|
||||
*
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @license http://dibiphp.com/license dibi license
|
||||
* @link http://dibiphp.com/
|
||||
* @package dibi
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Experimental object-oriented interface to database tables.
|
||||
*
|
||||
* @author David Grudl
|
||||
* @copyright Copyright (c) 2005, 2008 David Grudl
|
||||
* @package dibi
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
abstract class DibiTable extends NObject
|
||||
{
|
||||
/** @var string primary key mask */
|
||||
public static $primaryMask = 'id';
|
||||
|
||||
/** @var bool */
|
||||
public static $lowerCase = TRUE;
|
||||
|
||||
/** @var DibiConnection */
|
||||
private $connection;
|
||||
|
||||
/** @var array */
|
||||
private $options;
|
||||
|
||||
/** @var string table name */
|
||||
protected $name;
|
||||
|
||||
/** @var string primary key name */
|
||||
protected $primary;
|
||||
|
||||
/** @var string primary key type */
|
||||
protected $primaryModifier = '%i';
|
||||
|
||||
|
||||
/**
|
||||
* Table constructor
|
||||
* @param array
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(array $options = array())
|
||||
{
|
||||
$this->options = $options;
|
||||
|
||||
$this->setup();
|
||||
|
||||
if ($this->connection === NULL) {
|
||||
$this->connection = dibi::getConnection();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the table name
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the primary key name
|
||||
* @return string
|
||||
*/
|
||||
public function getPrimary()
|
||||
{
|
||||
return $this->primary;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the dibi connection
|
||||
* @return DibiConnection
|
||||
*/
|
||||
public function getConnection()
|
||||
{
|
||||
return $this->connection;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Setup object
|
||||
* @return void
|
||||
*/
|
||||
protected function setup()
|
||||
{
|
||||
// autodetect table name
|
||||
if ($this->name === NULL) {
|
||||
$name = $this->getClass();
|
||||
if (FALSE !== ($pos = strrpos($name, ':'))) {
|
||||
$name = substr($name, $pos + 1);
|
||||
}
|
||||
if (self::$lowerCase) {
|
||||
$name = strtolower($name);
|
||||
}
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
// autodetect primary key name
|
||||
if ($this->primary === NULL) {
|
||||
$this->primary = str_replace(
|
||||
array('%p', '%s'),
|
||||
array($this->name, trim($this->name, 's')), // the simplest inflector in the world :-))
|
||||
self::$primaryMask
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Inserts row into a table
|
||||
* @param array|object
|
||||
* @return int new primary key
|
||||
*/
|
||||
public function insert($data)
|
||||
{
|
||||
if (is_object($data)) {
|
||||
$data = (array) $data;
|
||||
} elseif (!is_array($data)) {
|
||||
throw new DibiException('Dataset must be array or anonymous object');
|
||||
}
|
||||
|
||||
$this->connection->query(
|
||||
'INSERT INTO %n', $this->name, '%v', $data
|
||||
);
|
||||
return $this->connection->insertId();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Updates rows in a table
|
||||
* @param mixed primary key value(s)
|
||||
* @param array|object
|
||||
* @return int number of updated rows
|
||||
*/
|
||||
public function update($where, $data)
|
||||
{
|
||||
if (is_object($data)) {
|
||||
$data = (array) $data;
|
||||
} elseif (!is_array($data)) {
|
||||
throw new DibiException('Dataset must be array or anonymous object');
|
||||
}
|
||||
|
||||
$this->connection->query(
|
||||
'UPDATE %n', $this->name,
|
||||
'SET %a', $data,
|
||||
'WHERE %n', $this->primary, 'IN (' . $this->primaryModifier, $where, ')'
|
||||
);
|
||||
return $this->connection->affectedRows();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Deletes rows from a table by primary key
|
||||
* @param mixed primary key value(s)
|
||||
* @return int number of deleted rows
|
||||
*/
|
||||
public function delete($where)
|
||||
{
|
||||
$this->connection->query(
|
||||
'DELETE FROM %n', $this->name,
|
||||
'WHERE %n', $this->primary, 'IN (' . $this->primaryModifier, $where, ')'
|
||||
);
|
||||
return $this->connection->affectedRows();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Finds rows by primary key
|
||||
* @param mixed primary key value(s)
|
||||
* @return DibiResult
|
||||
*/
|
||||
public function find($what)
|
||||
{
|
||||
if (!is_array($what)) {
|
||||
$what = func_get_args();
|
||||
}
|
||||
return $this->connection->query(
|
||||
'SELECT * FROM %n', $this->name,
|
||||
'WHERE %n', $this->primary, 'IN (' . $this->primaryModifier, $what, ')'
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Selects all rows
|
||||
* @param string column to order by
|
||||
* @return DibiResult
|
||||
*/
|
||||
public function findAll($order = NULL)
|
||||
{
|
||||
if ($order === NULL) {
|
||||
return $this->connection->query(
|
||||
'SELECT * FROM %n', $this->name
|
||||
);
|
||||
} else {
|
||||
$order = func_get_args();
|
||||
return $this->connection->query(
|
||||
'SELECT * FROM %n', $this->name,
|
||||
'ORDER BY %n', $order
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Fetches single row
|
||||
* @param scalar primary key value
|
||||
* @return array row
|
||||
*/
|
||||
public function fetch($what)
|
||||
{
|
||||
$this->connection->query(
|
||||
'SELECT * FROM %n', $this->name,
|
||||
'WHERE %n', $this->primary, '=' . $this->primaryModifier, $what
|
||||
)->fetch();
|
||||
}
|
||||
|
||||
}
|
@@ -35,7 +35,7 @@ final class DibiTranslator extends NObject
|
||||
/** @var string NOT USED YET */
|
||||
public $mask;
|
||||
|
||||
/** @var DibiDriverInterface */
|
||||
/** @var IDibiDriver */
|
||||
private $driver;
|
||||
|
||||
/** @var string last modifier */
|
||||
@@ -55,7 +55,7 @@ final class DibiTranslator extends NObject
|
||||
|
||||
|
||||
|
||||
public function __construct(DibiDriverInterface $driver)
|
||||
public function __construct(IDibiDriver $driver)
|
||||
{
|
||||
$this->driver = $driver;
|
||||
}
|
||||
@@ -207,7 +207,7 @@ final class DibiTranslator extends NObject
|
||||
return 'NULL';
|
||||
}
|
||||
|
||||
if ($value instanceof DibiVariableInterface) {
|
||||
if ($value instanceof IDibiVariable) {
|
||||
return $value->toSql($this->driver, $modifier);
|
||||
}
|
||||
|
||||
@@ -311,7 +311,7 @@ final class DibiTranslator extends NObject
|
||||
if ($value === NULL)
|
||||
return 'NULL';
|
||||
|
||||
if ($value instanceof DibiVariableInterface)
|
||||
if ($value instanceof IDibiVariable)
|
||||
return $value->toSql($this->driver, NULL);
|
||||
|
||||
$this->hasError = TRUE;
|
||||
|
@@ -20,26 +20,10 @@
|
||||
|
||||
|
||||
/**
|
||||
* Interface for user variable, used for generating SQL
|
||||
* Default implemenation of IDibiVariable
|
||||
* @package dibi
|
||||
*/
|
||||
interface DibiVariableInterface
|
||||
{
|
||||
/**
|
||||
* Format for SQL
|
||||
*
|
||||
* @param object destination DibiDriverInterface
|
||||
* @param string optional modifier
|
||||
* @return string SQL code
|
||||
*/
|
||||
public function toSql(DibiDriverInterface $driver, $modifier);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class DibiVariable extends NObject implements DibiVariableInterface
|
||||
class DibiVariable extends NObject implements IDibiVariable
|
||||
{
|
||||
/** @var mixed */
|
||||
public $value;
|
||||
@@ -55,7 +39,7 @@ class DibiVariable extends NObject implements DibiVariableInterface
|
||||
}
|
||||
|
||||
|
||||
public function toSql(DibiDriverInterface $driver, $modifier)
|
||||
public function toSql(IDibiDriver $driver, $modifier)
|
||||
{
|
||||
return $driver->format($this->value, $this->type);
|
||||
}
|
||||
|
@@ -25,8 +25,9 @@
|
||||
*
|
||||
* It defines some handful methods and enhances object core of PHP:
|
||||
* - access to undeclared members throws exceptions
|
||||
* - ability to add new methods to class (extension methods)
|
||||
* - support for conventional properties with getters and setters
|
||||
* - support for event raising functionality
|
||||
* - ability to add new methods to class (extension methods)
|
||||
*
|
||||
* Properties is a syntactic sugar which allows access public getter and setter
|
||||
* methods as normal object variables. A property is defined by a getter method
|
||||
@@ -38,6 +39,15 @@
|
||||
* Property names are case-sensitive, and they are written in the camelCaps
|
||||
* or PascalCaps.
|
||||
*
|
||||
* Event functionality is provided by declaration using pseudo-keyword 'event'.
|
||||
* Multiple handlers are allowed.
|
||||
* <code>
|
||||
* public $onClick = event; // declaration in class
|
||||
* $this->onClick[] = 'callback'; // attaching event handler
|
||||
* if (empty($this->onClick)) ... // are there any handler?
|
||||
* $this->onClick($sender, $arg); // raises the event with arguments
|
||||
* </code>
|
||||
*
|
||||
* Adding method to class (i.e. to all instances) works similar to JavaScript
|
||||
* prototype property. The syntax for adding a new method is:
|
||||
* <code>
|
||||
@@ -93,9 +103,23 @@ abstract class NObject
|
||||
throw new BadMethodCallException("Call to method without name");
|
||||
}
|
||||
|
||||
$class = get_class($this);
|
||||
|
||||
// event functionality
|
||||
if (self::hasEvent($class, $name)) {
|
||||
$list = $this->$name;
|
||||
if (is_array($list) || $list instanceof Traversable) {
|
||||
foreach ($list as $handler) {
|
||||
if ($handler === '') continue;
|
||||
call_user_func_array($handler, $args);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// object prototypes support Class__method()
|
||||
// (or use class Class__method { static function ... } with autoloading?)
|
||||
$cl = $class = get_class($this);
|
||||
$cl = $class;
|
||||
do {
|
||||
if (function_exists($nm = $cl . '_prototype_' . $name)) {
|
||||
array_unshift($args, $this);
|
||||
@@ -199,7 +223,7 @@ abstract class NObject
|
||||
|
||||
|
||||
/**
|
||||
* Has property accessor?
|
||||
* Has property an accessor?
|
||||
*
|
||||
* @param string class name
|
||||
* @param string method name
|
||||
@@ -221,4 +245,26 @@ abstract class NObject
|
||||
return isset($cache[$c][$m]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Is property an event?
|
||||
*
|
||||
* @param string class name
|
||||
* @param string method name
|
||||
* @return bool
|
||||
*/
|
||||
private static function hasEvent($c, $m)
|
||||
{
|
||||
if (strncmp($m, 'on', 2)) return FALSE;
|
||||
|
||||
static $cache;
|
||||
if (!isset($cache[$c])) {
|
||||
// get_class_vars returns ONLY PUBLIC properties
|
||||
// but returns static methods too (nothing doing...)
|
||||
$cache[$c] = get_class_vars($c);
|
||||
}
|
||||
return isset($cache[$c][$m]) && $cache[$c][$m] === '';
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -19,6 +19,26 @@
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Interface for user variable, used for generating SQL
|
||||
* @package dibi
|
||||
*/
|
||||
interface IDibiVariable
|
||||
{
|
||||
/**
|
||||
* Format for SQL
|
||||
*
|
||||
* @param object destination IDibiDriver
|
||||
* @param string optional modifier
|
||||
* @return string SQL code
|
||||
*/
|
||||
public function toSql(IDibiDriver $driver, $modifier);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* dibi driver interface
|
||||
*
|
||||
@@ -27,7 +47,7 @@
|
||||
* @package dibi
|
||||
* @version $Revision$ $Date$
|
||||
*/
|
||||
interface DibiDriverInterface
|
||||
interface IDibiDriver
|
||||
{
|
||||
|
||||
/**
|
Reference in New Issue
Block a user