Init with KH 3.1.3.1
This commit is contained in:
118
includes/kohana/modules/database/guide/database/config.md
Normal file
118
includes/kohana/modules/database/guide/database/config.md
Normal file
@@ -0,0 +1,118 @@
|
||||
# Configuration
|
||||
|
||||
The default config file is located in `MODPATH/database/config/database.php`. You should copy this file to `APPPATH/config/database.php` and make changes there, in keeping with the [cascading filesystem](../kohana/files).
|
||||
|
||||
The database configuration file contains an array of configuration groups. The structure of each database configuration group, called an "instance", looks like this:
|
||||
|
||||
string INSTANCE_NAME => array(
|
||||
'type' => string DATABASE_TYPE,
|
||||
'connection' => array CONNECTION_ARRAY,
|
||||
'table_prefix' => string TABLE_PREFIX,
|
||||
'charset' => string CHARACTER_SET,
|
||||
'profiling' => boolean QUERY_PROFILING,
|
||||
),
|
||||
|
||||
Understanding each of these settings is important.
|
||||
|
||||
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.
|
||||
|
||||
CONNECTION_ARRAY
|
||||
: Specific driver options for connecting to your database. (Driver options are explained [below](#connection-settings).)
|
||||
|
||||
TABLE_PREFIX
|
||||
: Prefix that will be added to all table names by the [query builder](#query_building). Prepared statements will **not** use the table prefix.
|
||||
|
||||
QUERY_PROFILING
|
||||
: Enables [profiling](../kohana/profiling) of database queries. This is useful for seeing how many queries each page is using, and which are taking the longest. You must enable the profiler the view these stats.
|
||||
|
||||
## Example
|
||||
|
||||
The example file below shows 2 MySQL connections, one local and one remote.
|
||||
|
||||
return array
|
||||
(
|
||||
'default' => array
|
||||
(
|
||||
'type' => 'mysql',
|
||||
'connection' => array(
|
||||
'hostname' => 'localhost',
|
||||
'username' => 'dbuser',
|
||||
'password' => 'mypassword',
|
||||
'persistent' => FALSE,
|
||||
'database' => 'my_db_name',
|
||||
),
|
||||
'table_prefix' => '',
|
||||
'charset' => 'utf8',
|
||||
'profiling' => TRUE,
|
||||
),
|
||||
'remote' => array(
|
||||
'type' => 'mysql',
|
||||
'connection' => array(
|
||||
'hostname' => '55.55.55.55',
|
||||
'username' => 'remote_user',
|
||||
'password' => 'mypassword',
|
||||
'persistent' => FALSE,
|
||||
'database' => 'my_remote_db_name',
|
||||
),
|
||||
'table_prefix' => '',
|
||||
'charset' => 'utf8',
|
||||
'profiling' => TRUE,
|
||||
),
|
||||
);
|
||||
|
||||
## 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.
|
||||
|
||||
// This would connect to the database defined as 'default'
|
||||
$default = Database::instance();
|
||||
|
||||
// This would connect to the database defined as 'remote'
|
||||
$remote = Database::instance('remote');
|
||||
|
||||
To disconnect the database, simply destroy the object:
|
||||
|
||||
unset($default)
|
||||
|
||||
// Or
|
||||
|
||||
unset(Database::$instances['default']);
|
||||
|
||||
If you want to disconnect all of the database instances at once:
|
||||
|
||||
Database::$instances = array();
|
||||
|
||||
## Connection Settings
|
||||
|
||||
Every database driver has different connection settings.
|
||||
|
||||
### MySQL
|
||||
|
||||
A [MySQL database](http://www.php.net/manual/en/book.mysql.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`
|
||||
|
||||
### PDO
|
||||
|
||||
A [PDO database](http://php.net/manual/en/book.pdo.php) can accept these options in the `connection` array:
|
||||
|
||||
Type | Option | Description | Default value
|
||||
----------|------------|----------------------------| -------------------------
|
||||
`string` | dsn | PDO data source identifier | `localhost`
|
||||
`string` | username | Database username | `NULL`
|
||||
`string` | password | Database password | `NULL`
|
||||
`boolean` | persistent | Persistent connections | `FALSE`
|
||||
|
||||
[!!] If you are using PDO and are not sure what to use for the `dsn` option, review [PDO::__construct](http://php.net/pdo.construct).
|
52
includes/kohana/modules/database/guide/database/examples.md
Normal file
52
includes/kohana/modules/database/guide/database/examples.md
Normal file
@@ -0,0 +1,52 @@
|
||||
# Examples
|
||||
|
||||
Here are some "real world" examples of using the database library to construct your queries and use the results.
|
||||
|
||||
## Examples of Prepared Statements
|
||||
|
||||
TODO: 4-6 examples of prepared statements of varying complexity, including a good bind() example.
|
||||
|
||||
## Pagination and search/filter
|
||||
|
||||
In this example, we loop through an array of whitelisted input fields and for each allowed non-empty value we add it to the search query. We make a clone of the query and then execute that query to count the total number of results. The count is then passed to the [Pagination](../pagination) class to determine the search offset. The last few lines search with Pagination's items_per_page and offset values to return a page of results based on the current page the user is on.
|
||||
|
||||
$query = DB::select()->from('users');
|
||||
|
||||
//only search for these fields
|
||||
$form_inputs = array('first_name', 'last_name', 'email');
|
||||
foreach ($form_inputs as $name)
|
||||
{
|
||||
$value = Arr::get($_GET, $name, FALSE);
|
||||
if ($value !== FALSE AND $value != '')
|
||||
{
|
||||
$query->where($name, 'like', '%'.$value.'%');
|
||||
}
|
||||
}
|
||||
|
||||
//copy the query & execute it
|
||||
$pagination_query = clone $query;
|
||||
$count = $pagination_query->select('COUNT("*") AS mycount')->execute()->get('mycount');
|
||||
|
||||
//pass the total item count to Pagination
|
||||
$config = Kohana::config('pagination');
|
||||
$pagination = Pagination::factory(array(
|
||||
'total_items' => $count,
|
||||
'current_page' => array('source' => 'route', 'key' => 'page'),
|
||||
'items_per_page' => 20,
|
||||
'view' => 'pagination/pretty',
|
||||
'auto_hide' => TRUE,
|
||||
));
|
||||
$page_links = $pagination->render();
|
||||
|
||||
//search for results starting at the offset calculated by the Pagination class
|
||||
$query->order_by('last_name', 'asc')
|
||||
->order_by('first_name', 'asc')
|
||||
->limit($pagination->items_per_page)
|
||||
->offset($pagination->offset);
|
||||
$results = $query->execute()->as_array();
|
||||
|
||||
## Having
|
||||
|
||||
TODO: example goes here
|
||||
|
||||
[!!] We could use more examples on this page.
|
17
includes/kohana/modules/database/guide/database/index.md
Normal file
17
includes/kohana/modules/database/guide/database/index.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# Database
|
||||
|
||||
Kohana 3.0 comes with a robust module for working with databases. By default, the database module supports drivers for [MySQL](http://php.net/mysql) and [PDO](http://php.net/pdo), but new drivers can be made for other database servers.
|
||||
|
||||
The database module is included with the Kohana 3.0 install, but needs to be enabled before you can use it. To enable, open your `application/bootstrap.php` file and modify the call to [Kohana::modules] by including the database module like so:
|
||||
|
||||
Kohana::modules(array(
|
||||
...
|
||||
'database' => MODPATH.'database',
|
||||
...
|
||||
));
|
||||
|
||||
Next, you will then need to [configure](config) the database module to connect to your database.
|
||||
|
||||
Once that is done then you can make [queries](query) and use the [results](results).
|
||||
|
||||
The database module also provides a [config driver](../api/Kohana_Config_Database) (for storing [configuration](../kohana/files/config) in the database) and a [session driver](Session_Database).
|
7
includes/kohana/modules/database/guide/database/menu.md
Normal file
7
includes/kohana/modules/database/guide/database/menu.md
Normal file
@@ -0,0 +1,7 @@
|
||||
## [Database]()
|
||||
- [Configuration](config)
|
||||
- [Querying](query)
|
||||
- [Prepared Statements](query/prepared)
|
||||
- [Query Builder](query/builder)
|
||||
- [Results](results)
|
||||
- [Examples](examples)
|
5
includes/kohana/modules/database/guide/database/query.md
Normal file
5
includes/kohana/modules/database/guide/database/query.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# Making Queries
|
||||
|
||||
There are two different ways to make queries. The simplest way to make a query is to use [Database_Query], via [DB::query], to manually create queries. These queries are called [prepared statements](query/prepared) and allow you to set query parameters which are automatically escaped. The second way to make a query is by building the query using method calls. This is done using the [query builder](query/builder).
|
||||
|
||||
[!!] All queries are run using the `execute` method, which accepts a [Database] object or instance name. See [Database_Query::execute] for more information.
|
253
includes/kohana/modules/database/guide/database/query/builder.md
Normal file
253
includes/kohana/modules/database/guide/database/query/builder.md
Normal file
@@ -0,0 +1,253 @@
|
||||
# Query Builder
|
||||
|
||||
Creating queries dynamically using objects and methods allows queries to be written very quickly in an agnostic way. Query building also adds identifier (table and column name) quoting, as well as value quoting.
|
||||
|
||||
[!!] At this time, it is not possible to combine query building with prepared statements.
|
||||
|
||||
## Select
|
||||
|
||||
Each type of database query is represented by a different class, each with their own methods. For instance, to create a SELECT query, we use [DB::select] which is a shortcut to return a new [Database_Query_Builder_Select] object:
|
||||
|
||||
$query = DB::select();
|
||||
|
||||
Query Builder methods return a reference to itself so that method chaining may be used. Select queries ussually require a table and they are referenced using the `from()` method. The `from()` method takes one parameter which can be the table name (string), an array of two strings (table name and alias), or an object (See Subqueries in the Advanced Queries section below).
|
||||
|
||||
$query = DB::select()->from('users');
|
||||
|
||||
Limiting the results of queries is done using the `where()`, `and_where()` and `or_where()` methods. These methods take three parameters: a column, an operator, and a value.
|
||||
|
||||
$query = DB::select()->from('users')->where('username', '=', 'john');
|
||||
|
||||
Multiple `where()` methods may be used to string together multiple clauses connected by the boolean operator in the method's prefix. The `where()` method is a wrapper that just calls `and_where()`.
|
||||
|
||||
$query = DB::select()->from('users')->where('username', '=', 'john')->or_where('username', '=', 'jane');
|
||||
|
||||
You can use any operator you want. Examples include `IN`, `BETWEEN`, `>`, `=<`, `!=`, etc. Use an array for operators that require more than one value.
|
||||
|
||||
$query = DB::select()->from('users')->where('logins', '<=', 1);
|
||||
|
||||
$query = DB::select()->from('users')->where('logins', '>', 50);
|
||||
|
||||
$query = DB::select()->from('users')->where('username', 'IN', array('john','mark','matt'));
|
||||
|
||||
$query = DB::select()->from('users')->where('joindate', 'BETWEEN', array($then, $now));
|
||||
|
||||
By default, [DB::select] will select all columns (`SELECT * ...`), but you can also specify which columns you want returned by passing parameters to [DB::select]:
|
||||
|
||||
$query = DB::select('username', 'password')->from('users')->where('username', '=', 'john');
|
||||
|
||||
Now take a minute to look at what this method chain is doing. First, we create a new selection object using the [DB::select] method. Next, we set table(s) using the `from()` method. Last, we search for a specific records using the `where()` method. We can display the SQL that will be executed by casting the query to a string:
|
||||
|
||||
echo Kohana::debug((string) $query);
|
||||
// Should display:
|
||||
// SELECT `username`, `password` FROM `users` WHERE `username` = 'john'
|
||||
|
||||
Notice how the column and table names are automatically escaped, as well as the values? This is one of the key benefits of using the query builder.
|
||||
|
||||
### Select - AS (column aliases)
|
||||
|
||||
It is also possible to create `AS` aliases when selecting, by passing an array as each parameter to [DB::select]:
|
||||
|
||||
$query = DB::select(array('username', 'u'), array('password', 'p'))->from('users');
|
||||
|
||||
This query would generate the following SQL:
|
||||
|
||||
SELECT `username` AS `u`, `password` AS `p` FROM `users`
|
||||
|
||||
### Select - DISTINCT
|
||||
|
||||
Unique column values may be turned on or off (default) by passing TRUE or FALSE, respectively, to the `distinct()` method.
|
||||
|
||||
$query = DB::select('username')->distinct(TRUE)->from('posts');
|
||||
|
||||
This query would generate the following SQL:
|
||||
|
||||
SELECT DISTINCT `username` FROM `posts`
|
||||
|
||||
### Select - LIMIT & OFFSET
|
||||
|
||||
When querying large sets of data, it is often better to limit the results and page through the data one chunk at a time. This is done using the `limit()` and `offset()` methods.
|
||||
|
||||
$query = DB::select()->from(`posts`)->limit(10)->offset(30);
|
||||
|
||||
This query would generate the following SQL:
|
||||
|
||||
SELECT * FROM `posts` LIMIT 10 OFFSET 30
|
||||
|
||||
### Select - ORDER BY
|
||||
|
||||
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`);
|
||||
|
||||
This query would generate the following SQL:
|
||||
|
||||
SELECT * FROM `posts` ORDER BY `published` DESC
|
||||
|
||||
[!!] For a complete list of methods available while building a select query see [Database_Query_Builder_Select].
|
||||
|
||||
## Insert
|
||||
|
||||
To create records into the database, use [DB::insert] to create an INSERT query, using `values()` to pass in the data:
|
||||
|
||||
$query = DB::insert('users', array('username', 'password'))->values(array('fred', 'p@5sW0Rd'));
|
||||
|
||||
This query would generate the following SQL:
|
||||
|
||||
INSERT INTO `users` (`username`, `password`) VALUES ('fred', 'p@5sW0Rd')
|
||||
|
||||
[!!] For a complete list of methods available while building an insert query see [Database_Query_Builder_Insert].
|
||||
|
||||
## Update
|
||||
|
||||
To modify an existing record, use [DB::update] to create an UPDATE query:
|
||||
|
||||
$query = DB::update('users')->set(array('username' => 'jane'))->where('username', '=', 'john');
|
||||
|
||||
This query would generate the following SQL:
|
||||
|
||||
UPDATE `users` SET `username` = 'jane' WHERE `username` = 'john'
|
||||
|
||||
[!!] For a complete list of methods available while building an update query see [Database_Query_Builder_Update].
|
||||
|
||||
## Delete
|
||||
|
||||
To remove an existing record, use [DB::delete] to create a DELETE query:
|
||||
|
||||
$query = DB::delete('users')->where('username', 'IN', array('john', 'jane'));
|
||||
|
||||
This query would generate the following SQL:
|
||||
|
||||
DELETE FROM `users` WHERE `username` IN ('john', 'jane')
|
||||
|
||||
[!!] For a complete list of methods available while building a delete query see [Database_Query_Builder_Delete].
|
||||
|
||||
## Advanced Queries
|
||||
|
||||
### Joins
|
||||
|
||||
Multiple tables can be joined using the `join()` and `on()` methods. The `join()` method takes two parameters. The first is either a table name, an array containing the table and alias, or an object (subquery or expression). The second parameter is the join type: LEFT, RIGHT, INNER, etc.
|
||||
|
||||
The `on()` method sets the conditions for the previous `join()` method and is very similar to the `where()` method in that it takes three parameters; left column (name or object), an operator, and the right column (name or object). Multiple `on()` methods may be used to supply multiple conditions and they will be appended with an 'AND' operator.
|
||||
|
||||
// This query will find all the posts related to "smith" with JOIN
|
||||
$query = DB::select('authors.name', 'posts.content')->from('authors')->join('posts')->on('authors.id', '=', 'posts.author_id')->where('authors.name', '=', 'smith');
|
||||
|
||||
This query would generate the following SQL:
|
||||
|
||||
SELECT `authors`.`name`, `posts`.`content` FROM `authors` JOIN `posts` ON (`authors`.`id` = `posts`.`author_id`) WHERE `authors`.`name` = 'smith'
|
||||
|
||||
If you want to do a LEFT, RIGHT or INNER JOIN you would do it like this `join('colum_name', 'type_of_join')`:
|
||||
|
||||
// This query will find all the posts related to "smith" with LEFT JOIN
|
||||
$query = DB::select()->from('authors')->join('posts', 'LEFT')->on('authors.id', '=', 'posts.author_id')->where('authors.name', '=', 'smith');
|
||||
|
||||
This query would generate the following SQL:
|
||||
|
||||
SELECT `authors`.`name`, `posts`.`content` FROM `authors` LEFT JOIN `posts` ON (`authors`.`id` = `posts`.`author_id`) WHERE `authors`.`name` = 'smith'
|
||||
|
||||
[!!] When joining multiple tables with similar column names, it's best to prefix the columns with the table name or table alias to avoid errors. Ambiguous column names should also be aliased so that they can be referenced easier.
|
||||
|
||||
### Database Functions
|
||||
|
||||
Eventually you will probably run into a situation where you need to call `COUNT` or some other database function within your query. The query builder supports these functions in two ways. The first is by using quotes within aliases:
|
||||
|
||||
$query = DB::select(array('COUNT("username")', 'total_users'))->from('users');
|
||||
|
||||
This looks almost exactly the same as a standard `AS` alias, but note how the column name is wrapped in double quotes. Any time a double-quoted value appears inside of a column name, **only** the part inside the double quotes will be escaped. This query would generate the following SQL:
|
||||
|
||||
SELECT COUNT(`username`) AS `total_users` FROM `users`
|
||||
|
||||
[!!] When building complex queries and you need to get a count of the total rows that will be returned, build the expression with an empty column list first. Then clone the query and add the COUNT function to one copy and the columns list to the other. This will cut down on the total lines of code and make updating the query easier.
|
||||
|
||||
$query = DB::select()->from('users')
|
||||
->join('posts')->on('posts.username', '=', 'users.username')
|
||||
->where('users.active', '=', TRUE)
|
||||
->where('posts.created', '>=', $yesterday);
|
||||
|
||||
$total = clone $query;
|
||||
$total->select(array('COUNT( DISTINCT "username")', 'unique_users'));
|
||||
$query->select('posts.username')->distinct();
|
||||
|
||||
### Aggregate Functions
|
||||
|
||||
Aggregate functions like `COUNT()`, `SUM()`, `AVG()`, etc. will most likely be used with the `group_by()` and possibly the `having()` methods in order to group and filter the results on a set of columns.
|
||||
|
||||
$query = DB::select('username', array('COUNT("id")', 'total_posts')
|
||||
->from('posts')->group_by('username')->having('total_posts', '>=', 10);
|
||||
|
||||
This will generate the following query:
|
||||
|
||||
SELECT `username`, COUNT(`id`) AS `total_posts` FROM `posts` GROUP BY `username` HAVING `total_posts` >= 10
|
||||
|
||||
### Subqueries
|
||||
|
||||
Query Builder objects can be passed as parameters to many of the methods to create subqueries. Let's take the previous example query and pass it to a new query.
|
||||
|
||||
$sub = DB::select('username', array('COUNT("id")', 'total_posts')
|
||||
->from('posts')->group_by('username')->having('total_posts', '>=', 10);
|
||||
|
||||
$query = DB::select('profiles.*', 'posts.total_posts')->from('profiles')
|
||||
->join(array($sub, 'posts'), 'INNER')->on('profiles.username', '=', 'posts.username');
|
||||
|
||||
This will generate the following query:
|
||||
|
||||
SELECT `profiles`.*, `posts`.`total_posts` FROM `profiles` INNER JOIN
|
||||
( SELECT `username`, COUNT(`id`) AS `total_posts` FROM `posts` GROUP BY `username` HAVING `total_posts` >= 10 ) AS posts
|
||||
ON `profiles`.`username` = `posts`.`username`
|
||||
|
||||
Insert queries can also use a select query for the input values
|
||||
|
||||
$sub = DB::select('username', array('COUNT("id")', 'total_posts')
|
||||
->from('posts')->group_by('username')->having('total_posts', '>=', 10);
|
||||
|
||||
$query = DB::insert('post_totals', array('username', 'posts'))->select($sub);
|
||||
|
||||
This will generate the following query:
|
||||
|
||||
INSERT INTO `post_totals` (`username`, `posts`)
|
||||
SELECT `username`, COUNT(`id`) AS `total_posts` FROM `posts` GROUP BY `username` HAVING `total_posts` >= 10
|
||||
|
||||
### Boolean Operators and Nested Clauses
|
||||
|
||||
Multiple Where and Having clauses are added to the query with Boolean operators connecting each expression. The default operator for both methods is AND which is the same as the and_ prefixed method. The OR operator can be specified by prefixing the methods with or_. Where and Having clauses can be nested or grouped by post fixing either method with _open and then followed by a method with a _close.
|
||||
|
||||
$query = DB::select()->from('users')
|
||||
->where_open()
|
||||
->or_where('id', 'IN', $expired)
|
||||
->and_where_open()
|
||||
->where('last_login', '<=', $last_month)
|
||||
->or_where('last_login', 'IS', NULL)
|
||||
->and_where_close()
|
||||
->where_close()
|
||||
->and_where('removed','IS', NULL);
|
||||
|
||||
This will generate the following query:
|
||||
|
||||
SELECT * FROM `users` WHERE ( `id` IN (1, 2, 3, 5) OR ( `last_login` <= 1276020805 OR `last_login` IS NULL ) ) AND `removed` IS NULL
|
||||
|
||||
### Database Expressions
|
||||
|
||||
There are cases were you need a complex expression or other database functions, which you don't want the Query Builder to try and escape. In these cases, you will need to use a database expression created with [DB::expr]. **A database expression is taken as direct input and no escaping is performed.**
|
||||
|
||||
$query = DB::update('users')->set(array('login_count' => DB::expr('login_count + 1')))->where('id', '=', $id);
|
||||
|
||||
This will generate the following query, assuming `$id = 45`:
|
||||
|
||||
UPDATE `users` SET `login_count` = `login_count` + 1 WHERE `id` = 45
|
||||
|
||||
Another example to calculate the distance of two geographical points:
|
||||
|
||||
$query = DB::select(array(DB::expr('degrees(acos(sin(radians('.$lat.')) * sin(radians(`latitude`)) + cos(radians('.$lat.')) * cos(radians(`latitude`)) * cos(radians(abs('.$lng.' - `longitude`))))) * 69.172'), 'distance'))->from('locations');
|
||||
|
||||
[!!] You must validate or escape any user input inside of DB::expr as it will obviously not be escaped it for you.
|
||||
|
||||
## Executing
|
||||
|
||||
Once you are done building, you can execute the query using `execute()` and use [the results](results).
|
||||
|
||||
$result = $query->execute();
|
||||
|
||||
To use a different database [config group](config) pass either the name or the config object to `execute()`.
|
||||
|
||||
$result = $query->execute('config_name')
|
@@ -0,0 +1,67 @@
|
||||
# Prepared Statements
|
||||
|
||||
Using prepared statements allows you to write SQL queries manually while still escaping the query values automatically to prevent [SQL injection](http://wikipedia.org/wiki/SQL_Injection). Creating a query is simple:
|
||||
|
||||
$query = DB::query(Database::SELECT, 'SELECT * FROM users WHERE username = :user');
|
||||
|
||||
The [DB::query] method is just a shortcut that creates a new [Database_Query] class for us, to allow method chaining. The query contains a `:user` parameter, which we will get to in a second.
|
||||
|
||||
The first parameter of [DB::query] is the type of query. It should be `Database::SELECT`, `Database::INSERT`, `Database::UPDATE`, or `Database::DELETE`. This is done for compatibility reasons for drivers, and to easily determine what `execute()` should return.
|
||||
|
||||
The second parameter is the query itself. Rather than trying to concatenate your query and variables together, you should make use of [Database_Query::param]. This will make your queries much easier to mantain, and will escape the values to prevent [SQL injection](http://wikipedia.org/wiki/SQL_Injection).
|
||||
|
||||
## Parameters
|
||||
|
||||
Our example query earlier contains a `:user` parameter, which we can assign to a value using [Database_Query::param] like so:
|
||||
|
||||
$query->param(':user', 'john');
|
||||
|
||||
[!!] Parameter names can be any unique string, as they are replaced using [strtr](http://php.net/strtr). It is highly recommended to **not** use dollars signs as parameter names to prevent confusion. Colons are commonly used.
|
||||
|
||||
You can also update the `:user` parameter by calling [Database_Query::param] again:
|
||||
|
||||
$query->param(':user', $_GET['search']);
|
||||
|
||||
If you want to set multiple parameters at once, you can use [Database_Query::parameters].
|
||||
|
||||
$query = DB::query(Database::SELECT, 'SELECT * FROM users WHERE username = :user AND status = :status');
|
||||
|
||||
$query->parameters(array(
|
||||
':user' => 'john',
|
||||
':status' => 'active',
|
||||
));
|
||||
|
||||
It is also possible to bind a parameter to a variable, using a [variable reference]((http://php.net/language.references.whatdo)). This can be extremely useful when running the same query many times:
|
||||
|
||||
$query = DB::query(Database::INSERT, 'INSERT INTO users (username, password) VALUES (:user, :pass)')
|
||||
->bind(':user', $username)
|
||||
->bind(':pass', $password);
|
||||
|
||||
foreach ($new_users as $username => $password)
|
||||
{
|
||||
$query->execute();
|
||||
}
|
||||
|
||||
In the above example, the variables `$username` and `$password` are changed for every loop of the `foreach` statement. When the parameter changes, it effectively changes the `:user` and `:pass` query parameters. Careful parameter binding can save a lot of code when it is used properly.
|
||||
|
||||
The only difference between `param()` and `bind()` is that `bind()` passes the variable by reference rather than by assignment (copied), so future changes to the variable can be "seen" by the query.
|
||||
|
||||
[!!] Although all parameters are escaped to prevent SQL injection, it is still a good idea to validate/sanitize your input.
|
||||
|
||||
## Display the raw query
|
||||
|
||||
If you want to display the SQL that will be executed, simply cast the object to a string:
|
||||
|
||||
echo Kohana::debug((string) $query);
|
||||
// Should display:
|
||||
// SELECT * FROM users WHERE username = 'john'
|
||||
|
||||
## Executing
|
||||
|
||||
Once you have assigned something to each of the parameters, you can execute the query using `execute()` and use [the results](results).
|
||||
|
||||
$result = $query->execute();
|
||||
|
||||
To use a different database [config group](config) pass either the name or the config object to `execute()`.
|
||||
|
||||
$result = $query->execute('config_name')
|
105
includes/kohana/modules/database/guide/database/results.md
Normal file
105
includes/kohana/modules/database/guide/database/results.md
Normal file
@@ -0,0 +1,105 @@
|
||||
# Results
|
||||
|
||||
## Execute
|
||||
|
||||
Once you have a query object built, either through a prepared statement or through the builder, you must then `execute()` the query and retrieve the results. Depending on the query type used, the results returned will vary.
|
||||
|
||||
## Select
|
||||
|
||||
[DB::select] will return a [Database_Result] object which you can then iterate over. This example shows how you can iterate through the [Database_Result] using a foreach.
|
||||
|
||||
$results = DB::select()->from('users')->where('verified', '=', 0)->execute();
|
||||
foreach($results as $user)
|
||||
{
|
||||
// Send reminder email to $user['email']
|
||||
echo $user['email']." needs to verify his/her account\n";
|
||||
}
|
||||
|
||||
### Select - `as_object()` and `as_assoc()`
|
||||
|
||||
When iterating over a result set, the default type will be an associative array with the column names or aliases as the keys. As an option, before calling `execute()`, you can specify to return the result rows as an object by using the `as_object()` method. The `as_object()` method takes one parameter, the name of the class of your choice, but will default to TRUE which uses the `stdClass`. Here is the example again using `stdClass`.
|
||||
|
||||
$results = DB::select()->from('users')->where('verified', '=', 0)->as_object()->execute();
|
||||
foreach($results as $user)
|
||||
{
|
||||
// Send reminder email to $user->email
|
||||
echo $user->email." needs to verify his/her account\n";
|
||||
}
|
||||
|
||||
[!!] The method `as_assoc()` will remove the object name and return the results set back to an associative array. Since this is the default, this method is seldom required.
|
||||
|
||||
### Select - `as_array()`
|
||||
|
||||
Sometimes you will require the results as a pure array rather than as an object. The `Database_Result` method `as_array()` will return an array of all rows.
|
||||
|
||||
$results = DB::select('id', 'email')->from('users')->execute();
|
||||
$users = $results->as_array();
|
||||
foreach($users as $user)
|
||||
{
|
||||
echo 'User ID: '.$user['id'];
|
||||
echo 'User Email: '.$user['email'];
|
||||
}
|
||||
|
||||
It also accepts two parameters that can be very helpful: `$key` and `$value`. When passing a value to `$key` you will index the resulting array by the column specified.
|
||||
|
||||
$results = DB::select('id', 'email')->from('users')->execute();
|
||||
$users = $results->as_array('id');
|
||||
foreach($users as $id => $user)
|
||||
{
|
||||
echo 'User ID: '.$id;
|
||||
echo 'User Email: '.$user['email'];
|
||||
}
|
||||
|
||||
The second parameter, `$value`, will reference the column specified and return that value rather than the whole row. This is particularly useful when making `<select>` dropdowns.
|
||||
|
||||
$results = DB::select('id', 'name')->from('users')->execute();
|
||||
$users = $results->as_array('id','name');
|
||||
// Show a dropdown with all users in it.
|
||||
echo Form::select('author', $users)
|
||||
|
||||
To return a non-associative array, leave `$key` as NULL and just pass a `$value`.
|
||||
|
||||
$results = DB::select('email')->from('users')->execute();
|
||||
$users = $results->as_array(NULL, 'email');
|
||||
foreach($users as $email)
|
||||
{
|
||||
echo 'User Email: '.$email;
|
||||
}
|
||||
|
||||
### Select - `get()`
|
||||
|
||||
Sometime you only want a single value from a query. The `get()` method returns the value of the named column from the current row. The second parameter, `$default`, is used to supply a default value when the result is NULL.
|
||||
|
||||
$total_users = DB::select(array('COUNT("username")', 'total_users'))->from('users')->execute()->get('total_users', 0);
|
||||
|
||||
### Select - `cached()`
|
||||
|
||||
The mysql database driver returns a `Database_Result` that works with a MySQL Resource data type. Since this resource lives outside of PHP environment, it can't be serialized which means it also can't be cached. To get around this the `Database_Result` object has the `cached()` method that returns a `Database_Result_Cached` object of the result set. The `Database_Result_Cached` can be serialized and cached, but can take up more memory.
|
||||
|
||||
[!!] NOTE: Currently, the PDO diver always returns a class of `Database_Result_Cached`, so `cached()` just returns itself.
|
||||
|
||||
The `cached()` function doesn't actually do any caching, it simply returns the result in a way that can be serialized and cached. You will need to use the [Cache Module](../cache) or some other caching method.
|
||||
|
||||
### Select - `count()`
|
||||
|
||||
The `Database_Result` object implements the `Countable` Interface. The method `count()` returns the total row count in the result set.
|
||||
|
||||
[!!] NOTE: This is the count of the current result set, not a count of how many records are in the database. This is important to point out especially when using `limit()` and `offset()` in your query.
|
||||
|
||||
[!!] For a complete list of methods available when working with a result set see [Database_Result].
|
||||
|
||||
## Insert
|
||||
|
||||
[DB::insert] returns an array of two values: the last insert id and the number of affected rows.
|
||||
|
||||
$insert = DB::insert('tools')
|
||||
->columns(array('name', 'model', 'description'))
|
||||
->values(array('Skil 3400 10" Table Saw', '3400', 'Powerful 15 amp motor; weighs just 54-pounds'));
|
||||
|
||||
list($insert_id, $affected_rows) = $insert->execute();
|
||||
|
||||
## Update & Delete
|
||||
|
||||
[DB::update] and [DB::delete] both return the number of affected rows as an integer.
|
||||
|
||||
$rows_deleted = DB::delete('tools')->where('model', 'like', '3400')->execute();
|
Reference in New Issue
Block a user