Kohana v3.3.5

This commit is contained in:
Deon George
2016-05-01 20:50:24 +10:00
parent 8888719653
commit 68c7f4f159
170 changed files with 4565 additions and 1176 deletions

View File

@@ -0,0 +1,37 @@
sudo: false
language: php
# Only build the main develop/master branches - feature branches will be covered by PRs
branches:
only:
- /^[0-9\.]+\/(develop|master)$/
cache:
directories:
- vendor
- $HOME/.composer/cache
php:
- 5.3
- 5.4
- 5.5
- 5.6
- 7.0
- hhvm
matrix:
include:
- php: 5.3
env: 'COMPOSER_PHPUNIT="lowest"'
before_script:
- composer install --prefer-dist
- if [ "$COMPOSER_PHPUNIT" = "lowest" ]; then composer update --prefer-lowest --with-dependencies phpunit/phpunit; fi;
- vendor/bin/koharness
script:
- cd /tmp/koharness && ./vendor/bin/phpunit --bootstrap=modules/unittest/bootstrap.php modules/unittest/tests.php
notifications:
email: false

View File

@@ -0,0 +1,6 @@
# Kohana - database access module
| ver | Stable | Develop |
|-------|--------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------|
| 3.3.x | [![Build Status - 3.3/master](https://travis-ci.org/kohana/database.svg?branch=3.3%2Fmaster)](https://travis-ci.org/kohana/database) | [![Build Status - 3.3/develop](https://travis-ci.org/kohana/database.svg?branch=3.3%2Fdevelop)](https://travis-ci.org/kohana/database) |
| 3.4.x | [![Build Status - 3.4/master](https://travis-ci.org/kohana/database.svg?branch=3.4%2Fmaster)](https://travis-ci.org/kohana/database) | [![Build Status - 3.4/develop](https://travis-ci.org/kohana/database.svg?branch=3.4%2Fdevelop)](https://travis-ci.org/kohana/database) |

View File

@@ -0,0 +1,3 @@
<?php defined('SYSPATH') OR die('No direct script access.');
class Database_MySQLi extends Kohana_Database_MySQLi {}

View File

@@ -0,0 +1,3 @@
<?php defined('SYSPATH') OR die('No direct script access.');
class Database_MySQLi_Result extends Kohana_Database_MySQLi_Result {}

View File

@@ -9,7 +9,7 @@
* @copyright (c) 2012 Kohana Team
* @license http://kohanaframework.org/license
*/
class Kohana_Config_Database extends Kohana_Config_Database_Writer
class Kohana_Config_Database extends Config_Database_Writer
{
}

View File

@@ -3,6 +3,15 @@
/**
* Database writer for the config system
*
* Schema for configuration table:
*
* CREATE TABLE IF NOT EXISTS `config` (
* `group_name` varchar(128) NOT NULL,
* `config_key` varchar(128) NOT NULL,
* `config_value` text,
* PRIMARY KEY (`group_name`,`config_key`)
* ) ENGINE=InnoDB;
*
* @package Kohana
* @category Configuration
* @author Kohana Team

View File

@@ -51,6 +51,9 @@ class Kohana_Database_MySQL_Result extends Database_Result {
// Increment internal row for optimization assuming rows are fetched in order
$this->_internal_row++;
// FIXME mysql_fetch_object has been deprecated as of php 5.5!
// Please use mysqli_fetch_object or PDOStatement::fetch(PDO::FETCH_OBJ) instead.
if ($this->_as_object === TRUE)
{
// Return an stdClass
@@ -58,8 +61,32 @@ class Kohana_Database_MySQL_Result extends Database_Result {
}
elseif (is_string($this->_as_object))
{
// Return an object of given class name
return mysql_fetch_object($this->_result, $this->_as_object, $this->_object_params);
/* The second and third argument for mysql_fetch_object are optional, but do
* not have default values defined. Passing _object_params with a non-array value results
* in undefined behavior that varies by PHP version. For example, if NULL is supplied on
* PHP 5.3, the resulting behavior is identical to calling with array(), which results in the
* classes __construct function being called with no arguments. This is only an issue when
* the _as_object class does not have an explicit __construct method resulting in the
* cryptic error "Class %s does not have a constructor hence you cannot use ctor_params."
* In contrast, the same function call on PHP 5.5 will 'functionally' interpret
* _object_params == NULL as an omission of the third argument, resulting in the original
* intended functionally.
*
* Because the backing code for the mysql_fetch_object has not changed between 5.3 and 5.5,
* I suspect this discrepancy is due to the way the classes are instantiated on a boarder
* level. Additionally, mysql_fetch_object has been deprecated in 5.5 and should probably be
* replaced by mysqli_fetch_object or PDOStatement::fetch(PDO::FETCH_OBJ) in Kohana 3.4.
*/
if ($this->_object_params !== NULL)
{
// Return an object of given class name with constructor params
return mysql_fetch_object($this->_result, $this->_as_object, $this->_object_params);
}
else
{
// Return an object of given class name without constructor params
return mysql_fetch_object($this->_result, $this->_as_object);
}
}
else
{

View File

@@ -0,0 +1,422 @@
<?php defined('SYSPATH') OR die('No direct script access.');
/**
* MySQLi database connection.
*
* @package Kohana/Database
* @category Drivers
* @author Kohana Team
* @copyright (c) 2008-2009 Kohana Team
* @license http://kohanaphp.com/license
*/
class Kohana_Database_MySQLi extends Database {
// Database in use by each connection
protected static $_current_databases = array();
// Use SET NAMES to set the character set
protected static $_set_names;
// Identifier for this connection within the PHP driver
protected $_connection_id;
// MySQL uses a backtick for identifiers
protected $_identifier = '`';
public function connect()
{
if ($this->_connection)
return;
if (Database_MySQLi::$_set_names === NULL)
{
// Determine if we can use mysqli_set_charset(), which is only
// available on PHP 5.2.3+ when compiled against MySQL 5.0+
Database_MySQLi::$_set_names = ! function_exists('mysqli_set_charset');
}
// Extract the connection parameters, adding required variabels
extract($this->_config['connection'] + array(
'database' => '',
'hostname' => '',
'username' => '',
'password' => '',
'socket' => '',
'port' => 3306,
'ssl' => NULL,
));
// Prevent this information from showing up in traces
unset($this->_config['connection']['username'], $this->_config['connection']['password']);
try
{
if(is_array($ssl))
{
$this->_connection = mysqli_init();
$this->_connection->ssl_set(
Arr::get($ssl, 'client_key_path'),
Arr::get($ssl, 'client_cert_path'),
Arr::get($ssl, 'ca_cert_path'),
Arr::get($ssl, 'ca_dir_path'),
Arr::get($ssl, 'cipher')
);
$this->_connection->real_connect($hostname, $username, $password, $database, $port, $socket, MYSQLI_CLIENT_SSL);
}
else
{
$this->_connection = new mysqli($hostname, $username, $password, $database, $port, $socket);
}
}
catch (Exception $e)
{
// No connection exists
$this->_connection = NULL;
throw new Database_Exception(':error', array(':error' => $e->getMessage()), $e->getCode());
}
// \xFF is a better delimiter, but the PHP driver uses underscore
$this->_connection_id = sha1($hostname.'_'.$username.'_'.$password);
if ( ! empty($this->_config['charset']))
{
// Set the character set
$this->set_charset($this->_config['charset']);
}
if ( ! empty($this->_config['connection']['variables']))
{
// Set session variables
$variables = array();
foreach ($this->_config['connection']['variables'] as $var => $val)
{
$variables[] = 'SESSION '.$var.' = '.$this->quote($val);
}
$this->_connection->query('SET '.implode(', ', $variables));
}
}
public function disconnect()
{
try
{
// Database is assumed disconnected
$status = TRUE;
if (is_resource($this->_connection))
{
if ($status = $this->_connection->close())
{
// Clear the connection
$this->_connection = NULL;
// Clear the instance
parent::disconnect();
}
}
}
catch (Exception $e)
{
// Database is probably not disconnected
$status = ! is_resource($this->_connection);
}
return $status;
}
public function set_charset($charset)
{
// Make sure the database is connected
$this->_connection or $this->connect();
if (Database_MySQLi::$_set_names === TRUE)
{
// PHP is compiled against MySQL 4.x
$status = (bool) $this->_connection->query('SET NAMES '.$this->quote($charset));
}
else
{
// PHP is compiled against MySQL 5.x
$status = $this->_connection->set_charset($charset);
}
if ($status === FALSE)
{
throw new Database_Exception(':error', array(':error' => $this->_connection->error), $this->_connection->errno);
}
}
public function query($type, $sql, $as_object = FALSE, array $params = NULL)
{
// Make sure the database is connected
$this->_connection or $this->connect();
if (Kohana::$profiling)
{
// Benchmark this query for the current instance
$benchmark = Profiler::start("Database ({$this->_instance})", $sql);
}
// Execute the query
if (($result = $this->_connection->query($sql)) === FALSE)
{
if (isset($benchmark))
{
// This benchmark is worthless
Profiler::delete($benchmark);
}
throw new Database_Exception(':error [ :query ]', array(
':error' => $this->_connection->error,
':query' => $sql
), $this->_connection->errno);
}
if (isset($benchmark))
{
Profiler::stop($benchmark);
}
// Set the last query
$this->last_query = $sql;
if ($type === Database::SELECT)
{
// Return an iterator of results
return new Database_MySQLi_Result($result, $sql, $as_object, $params);
}
elseif ($type === Database::INSERT)
{
// Return a list of insert id and rows created
return array(
$this->_connection->insert_id,
$this->_connection->affected_rows,
);
}
else
{
// Return the number of rows affected
return $this->_connection->affected_rows;
}
}
public function datatype($type)
{
static $types = array
(
'blob' => array('type' => 'string', 'binary' => TRUE, 'character_maximum_length' => '65535'),
'bool' => array('type' => 'bool'),
'bigint unsigned' => array('type' => 'int', 'min' => '0', 'max' => '18446744073709551615'),
'datetime' => array('type' => 'string'),
'decimal unsigned' => array('type' => 'float', 'exact' => TRUE, 'min' => '0'),
'double' => array('type' => 'float'),
'double precision unsigned' => array('type' => 'float', 'min' => '0'),
'double unsigned' => array('type' => 'float', 'min' => '0'),
'enum' => array('type' => 'string'),
'fixed' => array('type' => 'float', 'exact' => TRUE),
'fixed unsigned' => array('type' => 'float', 'exact' => TRUE, 'min' => '0'),
'float unsigned' => array('type' => 'float', 'min' => '0'),
'geometry' => array('type' => 'string', 'binary' => TRUE),
'int unsigned' => array('type' => 'int', 'min' => '0', 'max' => '4294967295'),
'integer unsigned' => array('type' => 'int', 'min' => '0', 'max' => '4294967295'),
'longblob' => array('type' => 'string', 'binary' => TRUE, 'character_maximum_length' => '4294967295'),
'longtext' => array('type' => 'string', 'character_maximum_length' => '4294967295'),
'mediumblob' => array('type' => 'string', 'binary' => TRUE, 'character_maximum_length' => '16777215'),
'mediumint' => array('type' => 'int', 'min' => '-8388608', 'max' => '8388607'),
'mediumint unsigned' => array('type' => 'int', 'min' => '0', 'max' => '16777215'),
'mediumtext' => array('type' => 'string', 'character_maximum_length' => '16777215'),
'national varchar' => array('type' => 'string'),
'numeric unsigned' => array('type' => 'float', 'exact' => TRUE, 'min' => '0'),
'nvarchar' => array('type' => 'string'),
'point' => array('type' => 'string', 'binary' => TRUE),
'real unsigned' => array('type' => 'float', 'min' => '0'),
'set' => array('type' => 'string'),
'smallint unsigned' => array('type' => 'int', 'min' => '0', 'max' => '65535'),
'text' => array('type' => 'string', 'character_maximum_length' => '65535'),
'tinyblob' => array('type' => 'string', 'binary' => TRUE, 'character_maximum_length' => '255'),
'tinyint' => array('type' => 'int', 'min' => '-128', 'max' => '127'),
'tinyint unsigned' => array('type' => 'int', 'min' => '0', 'max' => '255'),
'tinytext' => array('type' => 'string', 'character_maximum_length' => '255'),
'year' => array('type' => 'string'),
);
$type = str_replace(' zerofill', '', $type);
if (isset($types[$type]))
return $types[$type];
return parent::datatype($type);
}
/**
* Start a SQL transaction
*
* @link http://dev.mysql.com/doc/refman/5.0/en/set-transaction.html
*
* @param string $mode Isolation level
* @return boolean
*/
public function begin($mode = NULL)
{
// Make sure the database is connected
$this->_connection or $this->connect();
if ($mode AND ! $this->_connection->query("SET TRANSACTION ISOLATION LEVEL $mode"))
{
throw new Database_Exception(':error', array(
':error' => $this->_connection->error
), $this->_connection->errno);
}
return (bool) $this->_connection->query('START TRANSACTION');
}
/**
* Commit a SQL transaction
*
* @return boolean
*/
public function commit()
{
// Make sure the database is connected
$this->_connection or $this->connect();
return (bool) $this->_connection->query('COMMIT');
}
/**
* Rollback a SQL transaction
*
* @return boolean
*/
public function rollback()
{
// Make sure the database is connected
$this->_connection or $this->connect();
return (bool) $this->_connection->query('ROLLBACK');
}
public function list_tables($like = NULL)
{
if (is_string($like))
{
// Search for table names
$result = $this->query(Database::SELECT, 'SHOW TABLES LIKE '.$this->quote($like), FALSE);
}
else
{
// Find all table names
$result = $this->query(Database::SELECT, 'SHOW TABLES', FALSE);
}
$tables = array();
foreach ($result as $row)
{
$tables[] = reset($row);
}
return $tables;
}
public function list_columns($table, $like = NULL, $add_prefix = TRUE)
{
// Quote the table name
$table = ($add_prefix === TRUE) ? $this->quote_table($table) : $table;
if (is_string($like))
{
// Search for column names
$result = $this->query(Database::SELECT, 'SHOW FULL COLUMNS FROM '.$table.' LIKE '.$this->quote($like), FALSE);
}
else
{
// Find all column names
$result = $this->query(Database::SELECT, 'SHOW FULL COLUMNS FROM '.$table, FALSE);
}
$count = 0;
$columns = array();
foreach ($result as $row)
{
list($type, $length) = $this->_parse_type($row['Type']);
$column = $this->datatype($type);
$column['column_name'] = $row['Field'];
$column['column_default'] = $row['Default'];
$column['data_type'] = $type;
$column['is_nullable'] = ($row['Null'] == 'YES');
$column['ordinal_position'] = ++$count;
switch ($column['type'])
{
case 'float':
if (isset($length))
{
list($column['numeric_precision'], $column['numeric_scale']) = explode(',', $length);
}
break;
case 'int':
if (isset($length))
{
// MySQL attribute
$column['display'] = $length;
}
break;
case 'string':
switch ($column['data_type'])
{
case 'binary':
case 'varbinary':
$column['character_maximum_length'] = $length;
break;
case 'char':
case 'varchar':
$column['character_maximum_length'] = $length;
case 'text':
case 'tinytext':
case 'mediumtext':
case 'longtext':
$column['collation_name'] = $row['Collation'];
break;
case 'enum':
case 'set':
$column['collation_name'] = $row['Collation'];
$column['options'] = explode('\',\'', substr($length, 1, -1));
break;
}
break;
}
// MySQL attributes
$column['comment'] = $row['Comment'];
$column['extra'] = $row['Extra'];
$column['key'] = $row['Key'];
$column['privileges'] = $row['Privileges'];
$columns[$row['Field']] = $column;
}
return $columns;
}
public function escape($value)
{
// Make sure the database is connected
$this->_connection or $this->connect();
if (($value = $this->_connection->real_escape_string( (string) $value)) === FALSE)
{
throw new Database_Exception(':error', array(
':error' => $this->_connection->error,
), $this->_connection->errno);
}
// SQL standard is to use single-quotes for all values
return "'$value'";
}
} // End Database_MySQLi

View File

@@ -0,0 +1,71 @@
<?php defined('SYSPATH') OR die('No direct script access.');
/**
* MySQLi database result. See [Results](/database/results) for usage and examples.
*
* @package Kohana/Database
* @category Query/Result
* @author Kohana Team
* @copyright (c) 2008-2009 Kohana Team
* @license http://kohanaphp.com/license
*/
class Kohana_Database_MySQLi_Result extends Database_Result {
protected $_internal_row = 0;
public function __construct($result, $sql, $as_object = FALSE, array $params = NULL)
{
parent::__construct($result, $sql, $as_object, $params);
// Find the number of rows in the result
$this->_total_rows = $result->num_rows;
}
public function __destruct()
{
if (is_resource($this->_result))
{
$this->_result->free();
}
}
public function seek($offset)
{
if ($this->offsetExists($offset) AND $this->_result->data_seek($offset))
{
// Set the current row to the offset
$this->_current_row = $this->_internal_row = $offset;
return TRUE;
}
else
{
return FALSE;
}
}
public function current()
{
if ($this->_current_row !== $this->_internal_row AND ! $this->seek($this->_current_row))
return NULL;
// Increment internal row for optimization assuming rows are fetched in order
$this->_internal_row++;
if ($this->_as_object === TRUE)
{
// Return an stdClass
return $this->_result->fetch_object();
}
elseif (is_string($this->_as_object))
{
// Return an object of given class name
return $this->_result->fetch_object($this->_as_object, (array) $this->_object_params);
}
else
{
// Return an array of the row
return $this->_result->fetch_assoc();
}
}
} // End Database_MySQLi_Result_Select

View File

@@ -60,6 +60,12 @@ class Kohana_Database_PDO extends Database {
array(':error' => $e->getMessage()),
$e->getCode());
}
if ( ! empty($this->_config['charset']))
{
// Set the character set
$this->set_charset($this->_config['charset']);
}
}
/**

View File

@@ -80,7 +80,7 @@ abstract class Kohana_Database_Query_Builder extends Database_Query {
// Convert "val = NULL" to "val IS NULL"
$op = 'IS';
}
elseif ($op === '!=')
elseif ($op === '!=' OR $op === '<>')
{
// Convert "val != NULL" to "valu IS NOT NULL"
$op = 'IS NOT';

View File

@@ -31,7 +31,7 @@ class Kohana_Database_Query_Builder_Insert extends Database_Query_Builder {
if ($table)
{
// Set the inital table name
$this->_table = $table;
$this->table($table);
}
if ($columns)
@@ -47,11 +47,14 @@ class Kohana_Database_Query_Builder_Insert extends Database_Query_Builder {
/**
* Sets the table to insert into.
*
* @param mixed $table table name or array($table, $alias) or object
* @param string $table table name
* @return $this
*/
public function table($table)
{
if ( ! is_string($table))
throw new Kohana_Exception('INSERT INTO syntax does not allow table aliasing');
$this->_table = $table;
return $this;
@@ -86,8 +89,11 @@ class Kohana_Database_Query_Builder_Insert extends Database_Query_Builder {
// Get all of the passed values
$values = func_get_args();
$this->_values = array_merge($this->_values, $values);
foreach ($values as $value)
{
$this->_values[] = $value;
}
return $this;
}

View File

@@ -309,7 +309,7 @@ class Kohana_Database_Query_Builder_Select extends Database_Query_Builder_Where
*/
public function offset($number)
{
$this->_offset = $number;
$this->_offset = ($number === NULL) ? NULL : (int) $number;
return $this;
}
@@ -404,13 +404,14 @@ class Kohana_Database_Query_Builder_Select extends Database_Query_Builder_Where
if ( ! empty($this->_union))
{
$query = '('.$query.')';
foreach ($this->_union as $u) {
$query .= ' UNION ';
if ($u['all'] === TRUE)
{
$query .= 'ALL ';
}
$query .= $u['select']->compile($db);
$query .= '('.$u['select']->compile($db).')';
}
}

View File

@@ -172,7 +172,7 @@ abstract class Kohana_Database_Query_Builder_Where extends Database_Query_Builde
*/
public function limit($number)
{
$this->_limit = $number;
$this->_limit = ($number === NULL) ? NULL : (int) $number;
return $this;
}

View File

@@ -204,6 +204,9 @@ class Kohana_Session_Database extends Session {
// Execute the query
$query->execute($this->_db);
// Delete the old session id
$this->_update_id = NULL;
// Delete the cookie
Cookie::delete($this->_name);
}

View File

@@ -22,8 +22,13 @@
"require": {
"composer/installers": "~1.0",
"kohana/core": ">=3.3",
"php": ">=5.3.3"
"php": ">=5.3.6"
},
"require-dev": {
"kohana/core": "3.3.*@dev",
"kohana/unittest": "3.3.*@dev",
"kohana/koharness": "*@dev"
},
"suggest": {
"ext-mysql": "*",
"ext-pdo": "*"
@@ -32,6 +37,9 @@
"branch-alias": {
"dev-3.3/develop": "3.3.x-dev",
"dev-3.4/develop": "3.4.x-dev"
}
},
"installer-paths": {
"vendor/{$vendor}/{$name}": ["type:kohana-module"]
}
}
}

View File

@@ -53,4 +53,38 @@ return array
'charset' => 'utf8',
'caching' => FALSE,
),
/**
* MySQLi driver config information
*
* The following options are available for MySQLi:
*
* string hostname server hostname, or socket
* string database database name
* string username database username
* string password database password
* boolean persistent use persistent connections?
* array ssl ssl parameters as "key => value" pairs.
* Available keys: client_key_path, client_cert_path, ca_cert_path, ca_dir_path, cipher
* array variables system variables as "key => value" pairs
*
* Ports and sockets may be appended to the hostname.
*
* MySQLi driver config example:
*
*/
// 'alternate_mysqli' => array
// (
// 'type' => 'MySQLi',
// 'connection' => array(
// 'hostname' => 'localhost',
// 'database' => 'kohana',
// 'username' => FALSE,
// 'password' => FALSE,
// 'persistent' => FALSE,
// 'ssl' => NULL,
// ),
// 'table_prefix' => '',
// 'charset' => 'utf8',
// 'caching' => FALSE,
// ),
);

View File

@@ -10,6 +10,7 @@ The database configuration file contains an array of configuration groups. The s
'table_prefix' => string TABLE_PREFIX,
'charset' => string CHARACTER_SET,
),
Understanding each of these settings is important.
@@ -17,7 +18,7 @@ INSTANCE_NAME
: Connections can be named anything you want, but you should always have at least one connection called "default".
DATABASE_TYPE
: One of the installed database drivers. Kohana comes with "mysql" and "pdo" drivers. Drivers must extend the Database class.
: One of the installed database drivers. Kohana comes with "MySQL", "MySQLi", and "PDO" drivers. Drivers must extend the Database class. This parameter is case sensitive. Note the mysql php extension used by the MySQL driver is deprecated as of PHP 5.5 and you should look to use an alternative driver.
CONNECTION_ARRAY
: Specific driver options for connecting to your database. (Driver options are explained [below](#connection-settings).)
@@ -49,7 +50,7 @@ The example file below shows 2 MySQL connections, one local and one remote.
(
'default' => array
(
'type' => 'mysql',
'type' => 'MySQL',
'connection' => array(
'hostname' => 'localhost',
'username' => 'dbuser',
@@ -61,7 +62,7 @@ The example file below shows 2 MySQL connections, one local and one remote.
'charset' => 'utf8',
),
'remote' => array(
'type' => 'mysql',
'type' => 'MySQL',
'connection' => array(
'hostname' => '55.55.55.55',
'username' => 'remote_user',
@@ -74,6 +75,8 @@ The example file below shows 2 MySQL connections, one local and one remote.
),
);
[!!] Note that the 'type' parameter is case sensitive (eg 'MySQL', 'PDO').
## Connections and Instances
Each configuration group is referred to as a database instance. Each instance can be accessed by calling [Database::instance]. If you don't provide a parameter, the default instance is used.
@@ -114,6 +117,24 @@ Type | Option | Description | Default value
`boolean` | persistent | Persistent connections | `FALSE`
`string` | database | Database name | `kohana`
### MySQLi
A [MySQL database](http://php.net/manual/en/book.mysqli.php) can accept the following options in the `connection` array:
Type | Option | Description | Default value
----------|------------|----------------------------| -------------------------
`string` | hostname | Hostname of the database | `localhost`
`integer` | port | Port number | `NULL`
`string` | socket | UNIX socket | `NULL`
`string` | username | Database username | `NULL`
`string` | password | Database password | `NULL`
`boolean` | persistent | Persistent connections | `FALSE`
`string` | database | Database name | `kohana`
`array` | ssl | SSL parameters | `NULL`
SSL parameters should be specified as `key` => `value` pairs.
Available keys: client_key_path, client_cert_path, ca_cert_path, ca_dir_path, cipher
### PDO
A [PDO database](http://php.net/manual/en/book.pdo.php) can accept these options in the `connection` array:
@@ -128,4 +149,4 @@ Type | Option | Description | Default value
The connection character set should be configured using the DSN string or `options` array.
[!!] If you are using PDO and are not sure what to use for the `dsn` option, review [PDO::__construct](http://php.net/pdo.construct).
[!!] If you are using PDO and are not sure what to use for the `dsn` option, review [PDO::__construct](http://php.net/pdo.construct).

View File

@@ -25,7 +25,7 @@ In this example, we loop through an array of whitelisted input fields and for ea
//copy the query & execute it
$pagination_query = clone $query;
$count = $pagination_query->select(DB::expr('COUNT(*)) AS mycount')->execute()->get('mycount');
$count = $pagination_query->select(DB::expr('COUNT(*) AS mycount'))->execute()->get('mycount');
//pass the total item count to Pagination
$config = Kohana::$config->load('pagination');
@@ -49,4 +49,4 @@ In this example, we loop through an array of whitelisted input fields and for ea
TODO: example goes here
[!!] We could use more examples on this page.
[!!] We could use more examples on this page.

View File

@@ -76,7 +76,7 @@ This query would generate the following SQL:
Often you will want the results in a particular order and rather than sorting the results, it's better to have the results returned to you in the correct order. You can do this by using the order_by() method. It takes the column name and an optional direction string as the parameters. Multiple `order_by()` methods can be used to add additional sorting capability.
$query = DB::select()->from(`posts`)->order_by(`published`, `DESC`);
$query = DB::select()->from('posts')->order_by('published', 'DESC');
This query would generate the following SQL:
@@ -248,4 +248,4 @@ Once you are done building, you can execute the query using `execute()` and use
To use a different database [config group](config) pass either the name or the config object to `execute()`.
$result = $query->execute('config_name')
$result = $query->execute('config_name')

View File

@@ -0,0 +1,8 @@
<?php
// Configuration for koharness - builds a standalone skeleton Kohana app for running unit tests
return array(
'modules' => array(
'database' => __DIR__,
'unittest' => __DIR__ . '/vendor/kohana/unittest'
),
);