[TOC]
# 數據庫抽象層
`Phalcon\Db`是 `Phalcon\Mvc\Model` 背后的組件,它為框架中的模型層提供支持。它由一個完全用C語言編寫的數據庫系統的獨立高級抽象層組成。
與使用傳統模型相比,此組件允許更低級別的數據庫操作。
## 數據庫適配器
此組件使用適配器來封裝特定的數據庫系統詳細信息。Phalcon使用PDO連接數據庫。支持以下數據庫引擎:
| 類 | 描述 |
| --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `Phalcon\Db\Adapter\Pdo\Mysql` | 是世界上使用最多的關系數據庫管理系統(RDBMS),它作為服務器運行,提供對多個數據庫的多用戶訪問。 |
| `Phalcon\Db\Adapter\Pdo\Postgresql` | PostgreSQL是一個功能強大的開源關系數據庫系統。它擁有超過15年的積極開發經驗和經過驗證的架構,在可靠性,數據完整性和正確性方面贏得了良好的聲譽。 |
| `Phalcon\Db\Adapter\Pdo\Sqlite` | SQLite是一個軟件庫,它實現了一個獨立的,無服務器,零配置的事務SQL數據庫引擎。 |
### 工廠
使用`適配器`選項加載PDO適配器類。例如:
```php
<?php
use Phalcon\Db\Adapter\Pdo\Factory;
$options = [
'host' => 'localhost',
'dbname' => 'blog',
'port' => 3306,
'username' => 'sigma',
'password' => 'secret',
'adapter' => 'mysql',
];
$db = Factory::load($options);
```
### 實現自己的適配器
必須實現`Phalcon\Db\AdapterInterface`接口才能創建自己的數據庫適配器或擴展現有數據庫適配器。
## 數據庫方言
Phalcon用方言封裝了每個數據庫引擎的具體細節。它們為適配器提供了通用功能和SQL生成器。
| 類 | 描述 |
| ---------------------------------- | --------------------------------------------------- |
| `Phalcon\Db\Dialect\Mysql` | MySQL數據庫系統的SQL特定方言 |
| `Phalcon\Db\Dialect\Postgresql` | PostgreSQL數據庫系統的SQL特定方言 |
| `Phalcon\Db\Dialect\Sqlite` | SQLite數據庫系統的SQL特定方言 |
### 實現自己的方言
必須實現`Phalcon\Db\DialectInterface`接口才能創建自己的數據庫方言或擴展現有數據庫方言。
## 連接到數據庫
要創建連接,必須實例化適配器類。它只需要一個帶有連接參數的數組。下面的示例顯示了如何創建傳遞必需參數和可選參數的連接:
```php
<?php
// 必須
$config = [
'host' => '127.0.0.1',
'username' => 'mike',
'password' => 'sigma',
'dbname' => 'test_db',
];
// 可選
$config['persistent'] = false;
// 創建連接
$connection = new \Phalcon\Db\Adapter\Pdo\Mysql($config);
```
```php
<?php
// 必須
$config = [
'host' => 'localhost',
'username' => 'postgres',
'password' => 'secret1',
'dbname' => 'template',
];
// 可選
$config['schema'] = 'public';
// 創建連接
$connection = new \Phalcon\Db\Adapter\Pdo\Postgresql($config);
```
```php
<?php
// 必須
$config = [
'dbname' => '/path/to/database.db',
];
// 創建連接
$connection = new \Phalcon\Db\Adapter\Pdo\Sqlite($config);
```
## 設置其他PDO選項
您可以通過傳遞參數選項在連接時設置PDO選項:
```php
<?php
// 使用PDO選項創建連接
$connection = new \Phalcon\Db\Adapter\Pdo\Mysql(
[
'host' => 'localhost',
'username' => 'root',
'password' => 'sigma',
'dbname' => 'test_db',
'options' => [
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'UTF8'",
PDO::ATTR_CASE => PDO::CASE_LOWER,
]
]
);
```
## 使用工廠連接
您還可以使用簡單的`ini`文件來配置/連接`db`服務。
```ini
[database]
host = TEST_DB_MYSQL_HOST
username = TEST_DB_MYSQL_USER
password = TEST_DB_MYSQL_PASSWD
dbname = TEST_DB_MYSQL_NAME
port = TEST_DB_MYSQL_PORT
charset = TEST_DB_MYSQL_CHARSET
adapter = mysql
```
```php
<?php
use Phalcon\Config\Adapter\Ini;
use Phalcon\Di;
use Phalcon\Db\Adapter\Pdo\Factory;
$di = new Di();
$config = new Ini('config.ini');
$di->set('config', $config);
$di->set(
'db',
function () {
return Factory::load($this->config->database);
}
);
```
以上將返回正確的數據庫實例,并且還具有以下優點:您可以更改連接憑據甚至數據庫適配器,而無需更改應用程序中的單行代碼。
## 查找行
`Phalcon\Db` 提供了幾種從表中查詢行的方法。在這種情況下,需要目標數據庫引擎的特定SQL語法:
```php
<?php
$sql = 'SELECT id, name FROM robots ORDER BY name';
// 將SQL語句發送到數據庫系統
$result = $connection->query($sql);
// 打印每個 robot name
while ($robot = $result->fetch()) {
echo $robot['name'];
}
// 獲取數組中的所有行
$robots = $connection->fetchAll($sql);
foreach ($robots as $robot) {
echo $robot['name'];
}
// 只獲得第一行
$robot = $connection->fetchOne($sql);
```
默認情況下,這些調用會創建具有關聯索引和數字索引的數組。您可以使用`Phalcon\Db\Result::setFetchMode()`更改此行為。此方法接收常量,定義需要哪種索引。
| 常量 | 描述 |
| -------------------------- | --------------------------------------------------------- |
| `Phalcon\Db::FETCH_NUM` | 返回帶有數字索引的數組 |
| `Phalcon\Db::FETCH_ASSOC` | 返回帶關聯索引的數組 |
| `Phalcon\Db::FETCH_BOTH` | 返回包含關聯索引和數字索引的數組 |
| `Phalcon\Db::FETCH_OBJ` | 返回一個對象而不是一個數組 |
```php
<?php
$sql = 'SELECT id, name FROM robots ORDER BY name';
$result = $connection->query($sql);
$result->setFetchMode(Phalcon\Db::FETCH_NUM);
while ($robot = $result->fetch()) {
echo $robot[0];
}
```
`Phalcon\Db::query()`返回`Phalcon\Db\Result\Pdo`的實例。這些對象封裝了與返回的結果集相關的所有功能,即遍歷,尋找特定記錄,計數等。
```php
<?php
$sql = 'SELECT id, name FROM robots';
$result = $connection->query($sql);
// 遍歷結果集
while ($robot = $result->fetch()) {
echo $robot['name'];
}
// 尋找第三排
$result->seek(2);
$robot = $result->fetch();
// 計算結果集
echo $result->numRows();
```
## 綁定參數
`Phalcon\Db`也支持綁定參數。雖然使用綁定參數對性能影響最小,但建議您使用此方法,以消除代碼受SQL注入攻擊的可能性。支持字符串和位置占位符。綁定參數可以簡單地實現如下:
```php
<?php
// 使用數字占位符綁定
$sql = 'SELECT * FROM robots WHERE name = ? ORDER BY name';
$result = $connection->query(
$sql,
[
'Wall-E',
]
);
// 與命名占位符綁定
$sql = 'INSERT INTO `robots`(name`, year) VALUES (:name, :year)';
$success = $connection->query(
$sql,
[
'name' => 'Astro Boy',
'year' => 1952,
]
);
```
使用數字占位符時,您需要將它們定義為整數,即1或2.在這種情況下,“1”或“2”被視為字符串而不是數字,因此無法成功替換占位符。任何適配器數據都會使用[PDO Quote](http://www.php.net/manual/en/pdo.quote.php)自動轉義。
此函數考慮了連接字符集,因此建議在連接參數或數據庫服務器配置中定義正確的字符集,因為錯誤的字符集在存儲或檢索數據時會產生不良影響。
此外,您可以將參數直接傳遞給`execute`或`query`方法。在這種情況下,綁定參數直接傳遞給PDO:
```php
<?php
// 與PDO占位符綁定
$sql = 'SELECT * FROM robots WHERE name = ? ORDER BY name';
$result = $connection->query(
$sql,
[
1 => 'Wall-E',
]
);
```
## 類型占位符
占位符允許您綁定參數以避免SQL注入:
```php
<?php
$phql = "SELECT * FROM Store\Robots WHERE id > :id:";
$robots = $this->modelsManager->executeQuery($phql, ['id' => 100]);
```
但是,某些數據庫系統在使用占位符時需要執行其他操作,例如指定綁定參數的類型:
```php
<?php
use Phalcon\Db\Column;
// ...
$phql = "SELECT * FROM Store\Robots LIMIT :number:";
$robots = $this->modelsManager->executeQuery(
$phql,
['number' => 10],
Column::BIND_PARAM_INT
);
```
您可以在參數中使用類型化占位符,而不是在`executeQuery()`中指定綁定類型:
```php
<?php
$phql = "SELECT * FROM Store\Robots LIMIT {number:int}";
$robots = $this->modelsManager->executeQuery(
$phql,
['number' => 10]
);
$phql = "SELECT * FROM Store\Robots WHERE name <> {name:str}";
$robots = $this->modelsManager->executeQuery(
$phql,
['name' => $name]
);
```
如果您不需要指定它,也可以省略該類型:
```php
<?php
$phql = "SELECT * FROM Store\Robots WHERE name <> {name}";
$robots = $this->modelsManager->executeQuery(
$phql,
['name' => $name]
);
```
類型占位符也更強大,因為我們現在可以綁定靜態數組,而不必將每個元素作為占位符獨立傳遞:
```php
<?php
$phql = "SELECT * FROM Store\Robots WHERE id IN ({ids:array})";
$robots = $this->modelsManager->executeQuery(
$phql,
['ids' => [1, 2, 3, 4]]
);
```
可以使用以下類型:
| 綁定類型 | 綁定類型常量 | 示例 |
| --------- | --------------------------------- | ------------------- |
| str | `Column::BIND_PARAM_STR` | `{name:str}` |
| int | `Column::BIND_PARAM_INT` | `{number:int}` |
| double | `Column::BIND_PARAM_DECIMAL` | `{price:double}` |
| bool | `Column::BIND_PARAM_BOOL` | `{enabled:bool}` |
| blob | `Column::BIND_PARAM_BLOB` | `{image:blob}` |
| null | `Column::BIND_PARAM_NULL` | `{exists:null}` |
| array | Array of `Column::BIND_PARAM_STR` | `{codes:array}` |
| array-str | Array of `Column::BIND_PARAM_STR` | `{names:array-str}` |
| array-int | Array of `Column::BIND_PARAM_INT` | `{flags:array-int}` |
## 強制綁定參數值
默認情況下,綁定參數不會在PHP用戶空間中轉換為指定的綁定類型,此選項允許您在將它們與PDO綁定之前制定Phalcon轉換值。此問題引發的典型情況是在`LIMIT`/`OFFSET`占位符中傳遞一個字符串:
```php
<?php
$number = '100';
$robots = $modelsManager->executeQuery(
'SELECT * FROM Some\Robots LIMIT {number:int}',
['number' => $number]
);
```
這會導致以下異常:
Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[42000]:
Syntax error or access violation: 1064 You have an error in your SQL syntax;
check the manual that corresponds to your MySQL server version for the right
syntax to use near ''100'' at line 1' in /Users/scott/demo.php:78
這是因為100是一個字符串變量。可以通過先將值轉換為整數來輕松修復:
```php
<?php
$number = '100';
$robots = $modelsManager->executeQuery(
'SELECT * FROM Some\Robots LIMIT {number:int}',
['number' => (int) $number]
);
```
但是,此解決方案要求開發人員特別關注如何傳遞綁定參數及其類型。為了簡化此任務并避免意外異常,您可以指示Phalcon為您執行此轉換:
```php
<?php
\Phalcon\Db::setup(['forceCasting' => true]);
```
根據指定的綁定類型執行以下操作:
| 綁定類型 | 動作 |
| ---------------------------- | -------------------------------------- |
| Column::BIND_PARAM_STR | 將值轉換為原生PHP字符串 |
| Column::BIND_PARAM_INT | 將值轉換為原生PHP整型 |
| Column::BIND_PARAM_BOOL | 將值轉換為原生PHP布爾值 |
| Column::BIND_PARAM_DECIMAL | 將值轉換為原生PHP變量 |
## 混合轉換
無論值是屬于數值列還是布爾類型列,數據庫系統返回的值始終由PDO表示為字符串值。發生這種情況是因為某些列類型由于其大小限制而無法使用其對應的PHP原生類型表示。例如,MySQL中的`BIGINT`
可以存儲在PHP中不能表示為32位整數的大整數。因此,默認情況下,PDO和ORM做出安全決定,將所有值保留為字符串。
您可以設置ORM以自動將那些被認為安全的類型轉換為相應的PHP原生類型:
```php
<?php
\Phalcon\Mvc\Model::setup(['castOnHydrate' => true]);
```
這樣,您可以使用嚴格運算符或對變量類型進行假設:
```php
<?php
$robot = Robots::findFirst();
if (11 === $robot->id) {
echo $robot->name;
}
```
## 插入/更新/刪除行
要插入,更新或刪除行,您可以使用原始SQL或使用類提供的預設函數:
```php
<?php
// 使用原始SQL語句插入數據
$sql = 'INSERT INTO `robots`(`name`, `year`) VALUES ('Astro Boy', 1952)';
$success = $connection->execute($sql);
// 占位符
$sql = 'INSERT INTO `robots`(`name`, `year`) VALUES (?, ?)';
$success = $connection->execute(
$sql,
[
'Astro Boy',
1952,
]
);
// 動態生成必要的SQL
$success = $connection->insert(
'robots',
[
'Astro Boy',
1952,
],
[
'name',
'year',
],
);
// 動態生成必要的SQL(另一種語法)
$success = $connection->insertAsDict(
'robots',
[
'name' => 'Astro Boy',
'year' => 1952,
]
);
// 使用原始SQL語句更新數據
$sql = 'UPDATE `robots` SET `name` = 'Astro boy' WHERE `id` = 101';
$success = $connection->execute($sql);
// 占位符
$sql = 'UPDATE `robots` SET `name` = ? WHERE `id` = ?';
$success = $connection->execute(
$sql,
[
'Astro Boy',
101,
]
);
// 動態生成必要的SQL
$success = $connection->update(
'robots',
[
'name',
],
[
'New Astro Boy',
],
'id = 101' // 警告!在這種情況下,值不會被轉義
);
// 動態生成必要的SQL(另一種語法)
$success = $connection->updateAsDict(
'robots',
[
'name' => 'New Astro Boy',
],
'id = 101' // 警告!在這種情況下,值不會被轉義
);
// 轉義條件
$success = $connection->update(
'robots',
[
'name',
],
[
'New Astro Boy',
],
[
'conditions' => 'id = ?',
'bind' => [101],
'bindTypes' => [PDO::PARAM_INT], // 可選參數
]
);
$success = $connection->updateAsDict(
'robots',
[
'name' => 'New Astro Boy',
],
[
'conditions' => 'id = ?',
'bind' => [101],
'bindTypes' => [PDO::PARAM_INT], // Optional parameter
]
);
// 使用原始SQL語句刪除數據
$sql = 'DELETE `robots` WHERE `id` = 101';
$success = $connection->execute($sql);
// 占位符
$sql = 'DELETE `robots` WHERE `id` = ?';
$success = $connection->execute($sql, [101]);
// 動態生成必要的SQL
$success = $connection->delete(
'robots',
'id = ?',
[
101,
]
);
```
## 事務和嵌套事務
PDO支持使用事務處理。在事務內執行數據操作通常可以提高大多數數據庫系統的性能:
```php
<?php
try {
// 開始事務
$connection->begin();
// 執行一些SQL語句
$connection->execute('DELETE `robots` WHERE `id` = 101');
$connection->execute('DELETE `robots` WHERE `id` = 102');
$connection->execute('DELETE `robots` WHERE `id` = 103');
// 如果一切順利,commit
$connection->commit();
} catch (Exception $e) {
// 發生了異常回滾事務
$connection->rollback();
}
```
除標準事務外,`Phalcon\Db` 還為[嵌套事務](http://en.wikipedia.org/wiki/Nested_transaction)提供內置支持(如果使用的數據庫系統支持它們)。當您第二次調用begin()時,會創建一個嵌套事務:
```php
<?php
try {
// 開始事務
$connection->begin();
// 執行一些SQL語句
$connection->execute('DELETE `robots` WHERE `id` = 101');
try {
// 開始嵌套事務
$connection->begin();
// 將這些SQL語句執行到嵌套事務中
$connection->execute('DELETE `robots` WHERE `id` = 102');
$connection->execute('DELETE `robots` WHERE `id` = 103');
// 創建一個保存點
$connection->commit();
} catch (Exception $e) {
// 發生錯誤,釋放嵌套事務
$connection->rollback();
}
// 繼續,執行更多SQL語句
$connection->execute('DELETE `robots` WHERE `id` = 104');
// 如果一切順利,commit
$connection->commit();
} catch (Exception $e) {
// 發生了異常回滾事務
$connection->rollback();
}
```
## 數據庫事件
`Phalcon\Db` 能夠將事件發送到EventsManager(如果它存在)。返回布爾值false時的某些事件可能會停止活動操作。支持以下事件:
| 事件名稱 | Triggered | Can stop operation? |
| --------------------- | ---------------------------------------------------- |:-------------------:|
| `afterConnect` | 成功連接到數據庫系統后 | No |
| `beforeQuery` | 在將SQL語句發送到數據庫執行之前 | Yes |
| `afterQuery` | 將SQL語句發送到數據庫執行后 | No |
| `beforeDisconnect` | 在關閉臨時數據??庫連接之前 | No |
| `beginTransaction` | 在開始事務之前 | No |
| `rollbackTransaction` | 在事務被回滾之前 | No |
| `commitTransaction` | 在提交事務之前 | No |
將EventsManager綁定到連接很簡單,`Phalcon\Db`將使用`db`類型觸發事件:
```php
<?php
use Phalcon\Events\Manager as EventsManager;
use Phalcon\Db\Adapter\Pdo\Mysql as Connection;
$eventsManager = new EventsManager();
// 監聽所有數據庫事件
$eventsManager->attach('db', $dbListener);
$connection = new Connection(
[
'host' => 'localhost',
'username' => 'root',
'password' => 'secret',
'dbname' => 'invo',
]
);
// 將eventsManager分配給db adapter實例
$connection->setEventsManager($eventsManager);
```
如果您想要實現一些最后資源SQL注入器檢查器,則停止SQL操作非常有用:
```php
<?php
use Phalcon\Events\Event;
$eventsManager->attach(
'db:beforeQuery',
function (Event $event, $connection) {
$sql = $connection->getSQLStatement();
// 檢查SQL語句中的惡意詞
if (preg_match('/DROP|ALTER/i', $sql)) {
// 應用程序中不允許DROP / ALTER操作,
// 這必須是SQL注入!
return false;
}
// It's OK
return true;
}
);
```
## 分析SQL語句
`Phalcon\Db`包含一個名為 `Phalcon\Db\Profiler` 的分析組件,用于分析數據庫操作的性能,以便診斷性能問題并發現瓶頸。
使用`Phalcon\Db\Profiler`,數據庫分析非常簡單:
```php
<?php
use Phalcon\Events\Event;
use Phalcon\Events\Manager as EventsManager;
use Phalcon\Db\Profiler as DbProfiler;
$eventsManager = new EventsManager();
$profiler = new DbProfiler();
// 監聽所有數據庫事件
$eventsManager->attach(
'db',
function (Event $event, $connection) use ($profiler) {
if ($event->getType() === 'beforeQuery') {
$sql = $connection->getSQLStatement();
// 開始分析
$profiler->startProfile($sql);
}
if ($event->getType() === 'afterQuery') {
// 停止分析
$profiler->stopProfile();
}
}
);
// 將事件管理器分配給連接
$connection->setEventsManager($eventsManager);
$sql = 'SELECT buyer_name, quantity, product_name '
. 'FROM buyers '
. 'LEFT JOIN products ON buyers.pid = products.id';
// 執行SQL語句
$connection->query($sql);
// 獲取分析器中的最后一個分析SQL語句
$profile = $profiler->getLastProfile();
echo 'SQL Statement: ', $profile->getSQLStatement(), "\n";
echo 'Start Time: ', $profile->getInitialTime(), "\n";
echo 'Final Time: ', $profile->getFinalTime(), "\n";
echo 'Total Elapsed Time: ', $profile->getTotalElapsedSeconds(), "\n";
```
您還可以基于`Phalcon\Db\Profiler`創建自己的分析類,以記錄發送到數據庫系統的語句的實時統計信息:
```php
<?php
use Phalcon\Events\Manager as EventsManager;
use Phalcon\Db\Profiler as Profiler;
use Phalcon\Db\Profiler\Item as Item;
class DbProfiler extends Profiler
{
/**
* 在SQL語句發送到數據庫服務器之前執行
*/
public function beforeStartProfile(Item $profile)
{
echo $profile->getSQLStatement();
}
/**
* 在SQL語句發送到數據庫服務器之后執行
*/
public function afterEndProfile(Item $profile)
{
echo $profile->getTotalElapsedSeconds();
}
}
// 創建事件管理器
$eventsManager = new EventsManager();
// 創建監聽器
$dbProfiler = new DbProfiler();
// 附加監聽器監聽所有數據庫事件
$eventsManager->attach('db', $dbProfiler);
```
## 記錄SQL語句
使用`Phalcon\Db`等高級抽象組件來訪問數據庫,很難理解哪些語句被發送到數據庫系統。`Phalcon\Logger`與`Phalcon\Db`交互,在數據庫抽象層上提供日志記錄功能。
```php
<?php
use Phalcon\Logger;
use Phalcon\Events\Event;
use Phalcon\Events\Manager as EventsManager;
use Phalcon\Logger\Adapter\File as FileLogger;
$eventsManager = new EventsManager();
$logger = new FileLogger('app/logs/db.log');
$eventsManager->attach(
'db:beforeQuery',
function (Event $event, $connection) use ($logger) {
$sql = $connection->getSQLStatement();
$logger->log($sql, Logger::INFO);
}
);
// 將eventsManager分配給db adapter實例
$connection->setEventsManager($eventsManager);
// 執行一些SQL語句
$connection->insert(
'products',
[
'Hot pepper',
3.50,
],
[
'name',
'price',
]
);
```
如上所述,文件`app/logs/db.log`將包含以下內容:
```bash
[Sun, 29 Apr 12 22:35:26 -0500][DEBUG][Resource Id #77] INSERT INTO products
(name, price) VALUES ('Hot pepper', 3.50)
```
## 實現自己的Logger
您可以通過創建一個實現名為`log`的單個方法的類來為數據庫查詢實現自己的記錄器類。該方法需要接受一個`字符串`作為第一個參數。然后,您可以將您的日志記錄對象傳遞給`Phalcon\Db::setLogger()`,然后在執行的任何SQL語句中都會調用該方法來記錄結果。
## 描述表/視圖
`Phalcon\Db` 還提供了檢索有關表和視圖的詳細信息的方法:
```php
<?php
// 獲取test_db數據庫上的表
$tables = $connection->listTables('test_db');
// 數據庫中是否有表'robots'?
$exists = $connection->tableExists('robots');
// 獲取'robots'字段的名稱,數據類型和特殊功能
$fields = $connection->describeColumns('robots');
foreach ($fields as $field) {
echo 'Column Type: ', $field['Type'];
}
// 獲取'robots'表上的索引
$indexes = $connection->describeIndexes('robots');
foreach ($indexes as $index) {
print_r(
$index->getColumns()
);
}
// 在'robots'表上獲取外鍵
$references = $connection->describeReferences('robots');
foreach ($references as $reference) {
// 打印外鍵列
print_r(
$reference->getReferencedColumns()
);
}
```
表描述與MySQL `DESCRIBE`命令非常相似,它包含以下信息:
| 字段 | 類型 | Key | Null |
| ------------ | ----------- | -------------------------------------------------- | ---------------------------------- |
| 字段名 | 列類型 | 列的一部分是主鍵還是索引?| 該列是否允許空值?|
還為每個受支持的數據庫系統實現了獲取有關視圖的信息的方法:
```php
<?php
// 獲取有關test_db數據庫的視圖
$tables = $connection->listViews('test_db');
// 數據庫中是否有'robots' 視圖?
$exists = $connection->viewExists('robots');
```
## 創建/更改/刪除表
不同的數據庫系統(MySQL,Postgresql等)提供了使用`CREATE`,`ALTER`或`DROP`等命令創建,更改或刪除表的功能。SQL語法因使用的數據庫系統而異。`Phalcon\Db`提供了一個統一的界面來更改表,而無需區分基于目標存儲系統的SQL語法。
### 創建表
以下示例顯示如何創建表:
```php
<?php
use \Phalcon\Db\Column as Column;
$connection->createTable(
'robots',
null,
[
'columns' => [
new Column(
'id',
[
'type' => Column::TYPE_INTEGER,
'size' => 10,
'notNull' => true,
'autoIncrement' => true,
'primary' => true,
]
),
new Column(
'name',
[
'type' => Column::TYPE_VARCHAR,
'size' => 70,
'notNull' => true,
]
),
new Column(
'year',
[
'type' => Column::TYPE_INTEGER,
'size' => 11,
'notNull' => true,
]
),
]
]
);
```
`Phalcon\Db::createTable()`接受描述該表的關聯數組。列使用`Phalcon\Db\Column`類定義。下表顯示了可用于定義列的選項:
| 選項 | 描述 | 是否可選 |
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |:--------:|
| `type` | 列類型。必須是`Phalcon\Db\Column` 常量(請參閱下面的列表) | No |
| `primary` | 如果列是表的主鍵的一部分,則為True | Yes |
| `size` | 某些類型的列(如`VARCHAR`或`INTEGER`)可能具有特定大小 | Yes |
| `scale` | `DECIMAL` 或 `NUMBER`列可以有一個比例來指定應存儲多少小數 | Yes |
| `unsigned` | `INTEGER` 列可以是有符號或無符號的。此選項不適用于其他類型的列 | Yes |
| `notNull` | 列可以存儲null值嗎? | Yes |
| `default` | 默認值(與`'notNull' => true`一起使用時)。 | Yes |
| `autoIncrement` | 使用此屬性列將自動填充自動增量整數。表中只有一列可以具有此屬性。 | Yes |
| `bind` | 其中一個`BIND_TYPE_*`常量,用于說明在保存列之前必須如何綁定列 | Yes |
| `first` | 列必須按列順序放置在第一個位置 | Yes |
| `after` | 必須在指定的列之后放置 | Yes |
`Phalcon\Db` 支持以下數據庫列類型:
* `Phalcon\Db\Column::TYPE_INTEGER`
* `Phalcon\Db\Column::TYPE_DATE`
* `Phalcon\Db\Column::TYPE_VARCHAR`
* `Phalcon\Db\Column::TYPE_DECIMAL`
* `Phalcon\Db\Column::TYPE_DATETIME`
* `Phalcon\Db\Column::TYPE_CHAR`
* `Phalcon\Db\Column::TYPE_TEXT`
在 `Phalcon\Db::createTable()` 中傳遞的關聯數組可以具有可能的key:
| Index | 描述 | 是否可選 |
| ------------ | -------------------------------------------------------------------------------------------------------------------------------------- |:--------:|
| `columns` | 具有一組使用 `Phalcon\Db\Column`定義的表列的數組 | No |
| `indexes` | 具有一組使用 `Phalcon\Db\Index` 定義的表索引的數組 | Yes |
| `references` | 帶有一組使用 `Phalcon\Db\Reference` 定義的表引用(外鍵)的數組 | Yes |
| `options` | 包含一組表創建選項的數組。這些選項通常與生成遷移的數據庫系統有關。| Yes |
### 修改表
隨著應用程序的增長,您可能需要更改數據庫,作為重構或添加新功能的一部分。并非所有數據庫系統都允許修改現有列或在兩個現有列之間添加列。`Phalcon\Db`受這些限制的限制。
```php
<?php
use Phalcon\Db\Column as Column;
// 增加新列
$connection->addColumn(
'robots',
null,
new Column(
'robot_type',
[
'type' => Column::TYPE_VARCHAR,
'size' => 32,
'notNull' => true,
'after' => 'name',
]
)
);
// 修改現有列
$connection->modifyColumn(
'robots',
null,
new Column(
'name',
[
'type' => Column::TYPE_VARCHAR,
'size' => 40,
'notNull' => true,
]
)
);
// 刪除列 'name'
$connection->dropColumn(
'robots',
null,
'name'
);
```
### 刪除表
要從當前數據庫中刪除現有表,請使用 `dropTable`方法。要從自定義數據庫中刪除表,請使用第二個參數描述數據庫名稱。刪除表的示例:
```php
<?php
// 從活動數據庫中刪除表'robots'
$connection->dropTable('robots');
// 從數據庫'machines'中刪除表'robots'
$connection->dropTable('robots', 'machines');
```
- 常規
- Welcome
- 貢獻
- 生成回溯
- 測試重現
- 單元測試
- 入門
- 安裝
- Web服務器設置
- WAMP
- XAMPP
- 教程
- 基礎教程
- 教程:創建一個簡單的REST API
- 教程:V?kuró
- 提升性能
- 教程:INVO
- 開發環境
- Phalcon Compose (Docker)
- Nanobox
- Phalcon Box (Vagrant)
- 開發工具
- Phalcon開發者工具的安裝
- Phalcon開發者工具的使用
- 調試應用程序
- 核心
- MVC應用
- 微應用
- 創建命令行(CLI)應用程序
- 依賴注入與服務定位
- MVC架構
- 服務
- 使用緩存提高性能
- 讀取配置
- 上下文轉義
- 類加載器
- 使用命名空間
- 日志
- 隊列
- 數據庫
- 數據庫抽象層
- Phalcon查詢語言(PHQL)
- ODM(對象文檔映射器)
- 使用模型
- 模型行為
- ORM緩存
- 模型事件
- 模型元數據
- 模型關系
- 模型事務
- 驗證模型
- 數據庫遷移
- 分頁
- 前端
- Assets管理
- 閃存消息
- 表單
- 圖像
- 視圖助手(標簽)
- 使用視圖
- Volt:模板引擎
- 業務邏輯
- 訪問控制列表(ACL)
- 注解解析器
- 控制器
- 調度控制器
- 事件管理器
- 過濾與清理
- 路由
- 在session中存儲數據
- 生成URL和路徑
- 驗證
- HTTP
- Cookies管理
- 請求環境
- 返回響應
- 安全
- 加密/解密
- 安全
- 國際化
- 國際化
- 多語言支持