各DBMS間,最明顯、最常見的差異就在于所支持、實現的數據類型不同。Yii的一個重要任務,就是消 除這些區別,提供一個統一的開發界面供開發者使用。所以,我們先來看看Yii是怎么克服這一攔路虎 ,實現天下的大一統的。
## 抽象數據類型[](http://www.digpage.com/db_datatype.html#id2 "Permalink to this headline")
在使用Yii進行數據庫開發時,涉及到2個方面的數據類型:PHP自身的數據類型,DBMS的數據類型。 其中,PHP數據類型比較好整,反正就那么幾個,跟平臺、環境的關系也比較清楚。 復雜的地方在于DBMS的數據類型,龍生九子,各有不同。
因此,Yii不但需要搞定各DBMS間數據類型的差異,還需要搞定PHP與DBMS間數據類 類型的差異。因此,Yii引入了一個邏輯層面的數據類型,來統一PHP與DBMS,以及各DBMS之間數據類型 的差異。這里我們把這個邏輯層面的數據類型稱為抽象類型,在?yii\db\Schema?中進行定義:
~~~
abstract class Schema extends Object
{
// 預定義16種抽象字段類型
const TYPE_PK = 'pk';
const TYPE_BIGPK = 'bigpk';
const TYPE_STRING = 'string';
const TYPE_TEXT = 'text';
const TYPE_SMALLINT = 'smallint';
const TYPE_INTEGER = 'integer';
const TYPE_BIGINT = 'bigint';
const TYPE_FLOAT = 'float';
const TYPE_DECIMAL = 'decimal';
const TYPE_DATETIME = 'datetime';
const TYPE_TIMESTAMP = 'timestamp';
const TYPE_TIME = 'time';
const TYPE_DATE = 'date';
const TYPE_BINARY = 'binary';
const TYPE_BOOLEAN = 'boolean';
const TYPE_MONEY = 'money';
// ... ...
}
~~~
yii\db\Schema?一上來就先針對各DBMS間差異最明顯的字段數據類型進行統一,提供了16種抽象的 字段類型。這16種類型與DBMS無關,在具體到特定的DBMS時,Yii會自動轉換成合適的數據庫字段類型 。我們在編程中,若需要指定字段類型,比如創建數據庫之類,就使用這16種抽象類型。這樣的話, 就不用考慮使用的類型具體的DBMS是否支持的問題了,可以使我們更加專注于開發。
這16種類型看著就知道是什么意思,我們就不展開講了。只是有一點,這個數據類型是抽象的,也就是 說,只是一個邏輯意義上的數據類型,不涉及到具體實現。比如上面的?Schema::TYPE_BIGINT?所 要表示的是一個大數,但具體實現上,可能是用一個字符串來表示。
## 數據類型轉換[](http://www.digpage.com/db_datatype.html#id3 "Permalink to this headline")
既然Yii使用抽象數據類型來一統江山,那么無可避免的,涉及到PHP數據類型和DBMS數據類型與抽象類 型的轉換問題。
### 抽象類型轉數據庫類型[](http://www.digpage.com/db_datatype.html#id4 "Permalink to this headline")
前面提到過,在Yii開發中,我們使用16種抽象數據類型,而不使用具體的DBMS的數據類型。那么,在 我們要創建一個數據庫時,Yii是怎么為我們所定義的字段指定合適的數據類型的呢?
首先來看看一個基類?yii\db\QueryBuilder
~~~
class QueryBuilder extends \yii\base\Object
{
// $typeMap用于定義抽象數據類型到DBMS數據類型的映射關系,
// 具體由各QueryBuilder子類實現。
public $typeMap = [];
// 將抽象數據類型轉換成合適的DBMS數據類型
public function getColumnType($type)
{
// 映射表中已經有的,直接使用映射的類型
if (isset($this->typeMap[$type])) {
return $this->typeMap[$type];
// 映射表中沒有的類型,看看是不是形如 "Schema::TYPE_INT(11) DEFAULT 0" 之類的
} elseif (preg_match('/^(\w+)\((.+?)\)(.*)$/', $type, $matches)) {
if (isset($this->typeMap[$matches[1]])) {
return preg_replace('/\(.+\)/', '(' . $matches[2] . ')', $this->typeMap[$matches[1]]) . $matches[3];
}
// 看看是不是形如 "Schema::TYPE_INT NOT NULL" 之類的,
// 注意這一分支在第二分支之后
} elseif (preg_match('/^(\w+)\s+/', $type, $matches)) {
if (isset($this->typeMap[$matches[1]])) {
return preg_replace('/^\w+/', $this->typeMap[$matches[1]], $type);
}
}
// 實在匹配不上映射表中的類型,那就原封不動返回吧
return $type;
}
// ... ...
}
~~~
上面的代碼只列出了?yii\db\QueryBuilder?的部分內容。特別是其中的?$typeMap[]?是由子 類來具體實現的。比如,對于MySQL數據庫,?yii\db\mysql\QueryBuilder?中:
~~~
namespace yii\db\mysql;
class QueryBuilder extends \yii\db\QueryBuilder
{
public $typeMap = [
Schema::TYPE_PK => 'int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY',
Schema::TYPE_BIGPK => 'bigint(20) NOT NULL AUTO_INCREMENT PRIMARY KEY',
Schema::TYPE_STRING => 'varchar(255)',
Schema::TYPE_TEXT => 'text',
Schema::TYPE_SMALLINT => 'smallint(6)',
Schema::TYPE_INTEGER => 'int(11)',
Schema::TYPE_BIGINT => 'bigint(20)',
Schema::TYPE_FLOAT => 'float',
Schema::TYPE_DECIMAL => 'decimal(10,0)',
Schema::TYPE_DATETIME => 'datetime',
Schema::TYPE_TIMESTAMP => 'timestamp',
Schema::TYPE_TIME => 'time',
Schema::TYPE_DATE => 'date',
Schema::TYPE_BINARY => 'blob',
Schema::TYPE_BOOLEAN => 'tinyint(1)',
Schema::TYPE_MONEY => 'decimal(19,4)',
];
// ... ...
}
~~~
因此,對于16種抽象數據類型而言,都可以轉換成MySQL的特定數據類型。這里我們看到,TYPE_MONEY?本來是MySQL所沒有的數據類型,但通過將其映射成了?decimal(19,4)?,使得 MySQL也可以支持?TYPE_MONEY?類型了。
同樣的,在?yii\db\pgsql\QueryBuilder?yii\db\mssql\QueryBuilder?等QueryBuilder子類 中,也有相同的數據類型映射表?$typeMap[]?,以實現從抽象數據類型到具體數據庫數據類型的映 射。
對于抽象數據類型的具體定義,我們選一個自己比較熟悉的DBMS的Schema進行記憶就可以了。如果實在 吃不準,比如?TYPE_STRING?是定長還是變長,保留不保留空格等,可以看看Schema中的定義。建 議讀者朋友們還是熟記這16個基本類型,起碼仔細過一遍,在具體開發時,能省時不少。
yii\db\QueryBuilder::getColumnType()?實現了抽象數據類型到具體DBMS數據類型的轉換。 在具體的轉換過程中,如果指定一個字段為?Schema::TYPE_STRING?之類的,那么就會被轉換成?varchar(255)?。有的讀者朋友可能會問,那要是想指定成?varchar(64)?該怎么做呢?
那就直接使用?Schema::TYPE_STRING(64)?。?yii\db\QueryBuilder::getColumnType()?會識 別出來Schema::TYPE_STRING?,并將原來的?varchar(255)?轉換成?varchar(64)?。 這點適用于其他數據類型。當然,其本身要支持。指定一個?Schema::TYPE_BOOLEAN(2)?又有什么 意義呢?
我們還可以在16種抽象類型后面使用?NOT?NULL?,?DEFAULT?等。yii\db\QueryBuilder::getColumnType()?也是能夠識別出來并加以處理的。
### 數據庫類型轉抽象類型[](http://www.digpage.com/db_datatype.html#id5 "Permalink to this headline")
所謂來而不往非禮也,說完了抽象類型轉DBMS數據類型,就該說說反過來數據庫的數據類型, 怎么轉換成抽象數據類型了。仍然以MySQL數據庫為例,具體代碼在?yii\db\mysql\Schema?中:
~~~
class Schema extends \yii\db\Schema
{
// 定義從數據庫數據類型到16個抽象數據類型間的映射關系
public $typeMap = [
'tinyint' => self::TYPE_SMALLINT,
'bit' => self::TYPE_INTEGER,
'smallint' => self::TYPE_SMALLINT,
'mediumint' => self::TYPE_INTEGER,
'int' => self::TYPE_INTEGER,
'integer' => self::TYPE_INTEGER,
'bigint' => self::TYPE_BIGINT,
'float' => self::TYPE_FLOAT,
'double' => self::TYPE_FLOAT,
'real' => self::TYPE_FLOAT,
'decimal' => self::TYPE_DECIMAL,
'numeric' => self::TYPE_DECIMAL,
'tinytext' => self::TYPE_TEXT,
'mediumtext' => self::TYPE_TEXT,
'longtext' => self::TYPE_TEXT,
'longblob' => self::TYPE_BINARY,
'blob' => self::TYPE_BINARY,
'text' => self::TYPE_TEXT,
'varchar' => self::TYPE_STRING,
'string' => self::TYPE_STRING,
'char' => self::TYPE_STRING,
'datetime' => self::TYPE_DATETIME,
'year' => self::TYPE_DATE,
'date' => self::TYPE_DATE,
'time' => self::TYPE_TIME,
'timestamp' => self::TYPE_TIMESTAMP,
'enum' => self::TYPE_STRING,
];
// ... ...
}
~~~
在?yii\db\mysql\Schema::$typeMap?中,定義了MySQL數據類型與16種抽象數據類型的映射關系。 當然,由于抽象數據類型只有16種,所以,有一些MySQL數據類型被映射成同一種抽象類型。比如year?date?都被映射成了?self::TYPE_DATE?了。
同樣的,你可以在?yii\db\mssql\Schema?和?yii\db\pgsql\Schema?中找到類似的映射代碼。 在各Schema子類中,Yii針對不同的DBMS,實現了數據庫數據類型到抽象數據類型間的映射關系。
從數據庫類型到抽象類型的映射關系,只要掌握前面16種抽象類型與數據庫數據類型的映射關系, 那么,其逆向映射就幾乎不用刻意去記憶了。額外的,凡是沒有合適的抽象類型的,就用?TYPE_STRING來表示。
上面只是一個映射表,具體轉換過程在生成字段信息?yii\db\ColumnSchema?時進行。yii\db\ColumnSchema?保存了一個字段的各種相關信息,包括字段類型等。
字段信息的獲取和填充,又發生在?yii\db\Schema::loadTableSchema()?中。 該函數用于加載數據表信息?yii\db\TableSchema?,這是一個抽象函數,具體由各子類實現。
字段信息和表信息我們后面再講,這里大致知道就是用于保存字段和數據表的各種信息就可以了。而且 在獲取表信息時,必然會調用到獲取字段信息的相關代碼。字段信息和表信息的獲取,都由Schema子類 來具體實現。
對于MySQL數據庫而言,字段信息的獲取在?yii\db\mysql\Schema::loadColumnSchema()?中,也是 他實現了從數據庫類型到抽象類型的轉換:
~~~
// $info數組 由 SQL 語句 "SHOW FULL COLUMNS FROM ..." 而來,形式如下:
// Field: id
// Type: int(11)
// Collation: NULL
// Null: NO
// Key: PRI
// Default: NULL
// Extra: auto_increment
// Privileges: select,insert,update,references
// Comment:
protected function loadColumnSchema($info)
{
$column = $this->createColumnSchema();
// 字段名
$column->name = $info['Field'];
// 是否允許為NULL
$column->allowNull = $info['Null'] === 'YES';
// 是否是主鍵
$column->isPrimaryKey = strpos($info['Key'], 'PRI') !== false;
// 是否 auto_increment
$column->autoIncrement = stripos($info['Extra'], 'auto_increment') !== false;
// 獲取字段注釋
$column->comment = $info['Comment'];
// 重點是這里,獲取數據庫字段類型,如上面的 int(11)
$column->dbType = $info['Type'];
// 是否是 unsigned
$column->unsigned = stripos($column->dbType, 'unsigned') !== false;
// 以下將把數據庫類型,轉換成對應的抽象類型,默認為 TYPE_STRING
$column->type = self::TYPE_STRING;
if (preg_match('/^(\w+)(?:\(([^\)]+)\))?/', $column->dbType, $matches)) {
// 獲取 int(11) 的 "int" 部分
$type = strtolower($matches[1]);
// 如果映射表里有,那就直接映射成抽象類型
if (isset($this->typeMap[$type])) {
$column->type = $this->typeMap[$type];
}
// 形如int(11) 的括號中的內容
if (!empty($matches[2])) {
// 枚舉類型,還需要將所有枚舉值寫入 $column->enumValues
if ($type === 'enum') {
$values = explode(',', $matches[2]);
foreach ($values as $i => $value) {
$values[$i] = trim($value, "'");
}
$column->enumValues = $values;
// 如果不是枚舉類型,那么括號中的內容就是精度了,如 decimal(19,4)
} else {
$values = explode(',', $matches[2]);
$column->size = $column->precision = (int) $values[0];
if (isset($values[1])) {
$column->scale = (int) $values[1];
}
// bit(1) 類型的,轉換成 boolean
if ($column->size === 1 && $type === 'bit') {
$column->type = 'boolean';
} elseif ($type === 'bit') {
// 由于bit最多64位,如果超過 32 位,那么用一個 bigint 足以。
if ($column->size > 32) {
$column->type = 'bigint';
// 如果正好32位,那么用一個 interger 來表示。
} elseif ($column->size === 32) {
$column->type = 'integer';
}
}
}
}
}
// 獲取PHP數據類型
$column->phpType = $this->getColumnPhpType($column);
// 處理默認值
if (!$column->isPrimaryKey) {
// timestamp 的話,要實際獲取當前時間戳,而不能是字符串 'CURRENT_TIMESTAMP'
if ($column->type === 'timestamp' && $info['Default'] === 'CURRENT_TIMESTAMP') {
$column->defaultValue = new Expression('CURRENT_TIMESTAMP');
// bit 的話,要截取對應的內容,并進行進制轉換
} elseif (isset($type) && $type === 'bit') {
$column->defaultValue = bindec(trim($info['Default'],'b\''));
// 其余類型的,直接轉換成PHP類型的值
} else {
$column->defaultValue = $column->phpTypecast($info['Default']);
}
}
return $column;
}
~~~
上面的代碼是完整獲取字段信息的過程,這里重點要看的,是獲取數據類型部分的代碼。結合映射表和 上面的代碼,我們能夠得出:
* 通過?SHOW?FULL?COLUMNS?FROM?SQL語句獲取字段信息,并存儲在?$info?數組中。
* 根據?$info['Type']?獲取字段類型信息。
* 如果映射表里已經有映射關系的,直接通過映射表,獲取相應的抽象類型。
* 如果映射表沒有的,默認地視字段的抽象類型為?TYPE_STRING?。
* 對于枚舉類型,除了轉換成?TYPE_STRING?外,還要獲取其枚舉值,否則,類型信息不完整 。
* 對于bit類型,在32位及32位以下時,使用?TYPE_INTEGER?抽象類型,在32位以上(bit最大為64 位)時,使用?TYPE_BIGINT?類型。
至于其他字段信息的獲取,如是否允許為 NULL 之類,上面的代碼中注釋已經交待清楚了,大家這么聰 明,相信難不倒你們。需要稍稍注意的,就是默認值的處理,特別是?timestamp?類型默認值的處 理。
### 抽象類型轉PHP類型[](http://www.digpage.com/db_datatype.html#php "Permalink to this headline")
前面講數據庫類型轉抽象類型時,在?yii\db\mysql\Schema::loadColumnSchema()?中,有一個語 句$column->phpType?=?$this->getColumnPhpType($column);?我們只是簡單地說是轉換成 PHP 類型,就一筆帶來了。其實,他就是把抽像類型轉換成PHP類型的關鍵,讓我們來看看這個yii\db\Schema::getColumnPhpType()
~~~
protected function getColumnPhpType($column)
{
// 定義從抽象類型到PHP類型的映射
static $typeMap = [
'smallint' => 'integer',
'integer' => 'integer',
'bigint' => 'integer',
'boolean' => 'boolean',
'float' => 'double',
'binary' => 'resource',
];
// 除了上面的映射關系外,還有幾個特殊情況:
// 1\. bigint字段,在64位環境下,且為singed時,使用integer來表示,否則string
// 2\. integer字段,在32位環境下,且為unsinged時,使用string表示,否則integer
// 3\. 映射中不存在的字段類型均使用string
if (isset($typeMap[$column->type])) {
if ($column->type === 'bigint') {
return PHP_INT_SIZE == 8 && !$column->unsigned ? 'integer' : 'string';
} elseif ($column->type === 'integer') {
return PHP_INT_SIZE == 4 && $column->unsigned ? 'string' : 'integer';
} else {
return $typeMap[$column->type];
}
} else {
return 'string';
}
}
~~~
首先不要驚訝于為什么這個方法不像數據庫類與抽象類型轉換時,放在MySQL子類Schema中實現。這是 由于我們現在討論的是抽象類型到PHP類型的轉換。我們說過,抽象類型是與數據庫無關的,PHP類型更 是與數據庫沒有半毛錢關系,所以,放在基類?yii\db\Schema?中是合理的。這也是我們在平時在 編程時經常采用的劃分基類與子類的一個常用準則。
雖然,我們說抽象數據類型有16種,但是到了PHP范疇,有的類型是沒有意義的。在PHP中,數據庫的字 段類型,都可以歸結了?integer?boolean?double?resourece?string?5種。
* TYPE_PK?和?TYPE_BIGPK?表示主鍵,Yii使用?yii\db\ColumnSchema::isPrimaryKey?屬性來表示,不存在將其轉換成何種數據類型的問題。
* TYPE_SMALLINT?TYPE_INTEGER?TYPE_BIGINT?等字段一般都轉換成PHP的?integer?類型。特別是TYPE_SMALLINT?,PHP的?integer?完全可以滿足要求。
* TYPE_BIGINT?字段,如果是在64位環境下,且該字段并非為?unsigned?時,PHP的?integer?足夠存儲。但是,在32位環境下,PHP的?integer?只有4個字節,不夠存儲8個字節的TYPE_BIGINT?。而如果字段是?unsigned?的,由于PHP并沒有?unsigned?一說,就算是 64位環境,也少了1 bit。在不夠存儲時,就只能選用PHP的?string?類型了。
* TYPE_INTEGER?字段,在32位環境下,如果是?unsigned?的,那也會少1 bit來存儲。而如 果是64位環境,或者并非是?unsigned?的,PHP的?integer?都是夠用的。同樣,不夠存儲時 ,就使用字符串類型了。
* TYPE_FLOAT?字段,注意是轉換成PHP的?double?而非?float?,?float?精度不夠。
* TYPE_BOOLEAN?字段,順理成章對應PHP的?boolean?類型。
* TYPE_BINARY?字段,理所當然對應PHP的?resource?類型。
* TYPE_STRING?和?TYPE_TEXT?字段,顯而易見對應 PHP的?string?類型。
* TYPE_DECIMAL?和?TYPE_MONEY?字段由于PHP的數值類型精度都不夠,所以, 只能使用?string類型來表示。
* 對于日期、時間等字段,盡管PHP提供了豐富的日期、時間函數,但事實上,PHP中并沒有專門的表示 日期、時間的數據類型。因此,對于這類字段,又只能求助于萬能的?string?類型了。
### 字段內容轉PHP變量[](http://www.digpage.com/db_datatype.html#id6 "Permalink to this headline")
前面我們有了數據庫類型轉抽象類型,抽象類型轉PHP類型,那么,我們就可以完成數據庫類型到PHP類 型的轉換,也就是說,能夠將數據庫中的內容讀取到PHP中供我們編程時使用啦。
假設有如下的MySQL數據表:
~~~
CREATE TABLE `tbl_news` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`userid` int(10) unsigned NOT NULL DEFAULT '0',
`status` enum('Draft','Publish','Archive','Unpublish') NOT NULL DEFAULT 'Draft',
`title` varchar(256) NOT NULL DEFAULT '',
`tags` varchar(256) NOT NULL DEFAULT '',
`createtime` int(10) unsigned NOT NULL DEFAULT '0',
`publishtime` int(10) unsigned NOT NULL DEFAULT '0',
`abstract` varchar(512) NOT NULL DEFAULT '',
`content` text,
`lastupdate` int(10) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=8 DEFAULT CHARSET=utf8
~~~
那么,通過PDO獲取其中一個記錄,DUMP出來后,各字段的類型為:
~~~
array(10) {
["id"]=>
string(1) "7"
["userid"]=>
string(1) "1"
["status"]=>
string(5) "Draft"
["title"]=>
string(6) "teste2"
["tags"]=>
string(4) "test"
["createtime"]=>
string(10) "1382152003"
["publishtime"]=>
string(10) "1381161600"
["abstract"]=>
string(3) "abs"
["content"]=>
string(12) "<p>cont</p>"
["lastupdate"]=>
string(10) "1382152003"
}
~~~
你能看到,所有的字段通過PDO讀取后,再DUMP出來都是以?string?保存的。這就需要Yii根據 ColumnSchema中字段信息,去把各字段以合適的PHP類型表現出來。而這個過程, 就是yii\db\ColumnSchema::phpTypeCast()
~~~
// 該方法用于把 $value 轉換成 php 變量,其中 $value 是PDO從數據庫中讀取的內容
// 主要參考的是字段的抽象類型 $type 和 PHP類型 $phpType
public function phpTypecast($value)
{
// 內容為空時,若不是字符串或二進制抽象類型,則是NULL的意思。
if ($value === '' && $this->type !== Schema::TYPE_TEXT && $this->type !== Schema::TYPE_STRING && $this->type !== Schema::TYPE_BINARY) {
return null;
}
// 內容為null,或者 $value 的類型與PHP類型一致,或者 $value 是一個數據庫表達式,
// 那么可以直接返回
if ($value === null || gettype($value) === $this->phpType || $value instanceof Expression) {
return $value;
}
// 否則,需要根據PHP類型來完成類型轉換
switch ($this->phpType) {
case 'resource':
case 'string':
return is_resource($value) ? $value : (string) $value;
case 'integer':
return (int) $value;
case 'boolean':
return (bool) $value;
case 'double':
return (double) $value;
}
return $value;
}
~~~
在上面的轉換過程中,PHP類型信息已經在上一步的?yii\db\Schema::getColumnPhpType()?中獲 取了。這里就是把從數據庫中得到的數據,轉換成?phpType?所指定的PHP變量類型。
前面我們講過,16種抽象類型最終對應于PHP的5種數據類型。但是,從上面的?phpTypeCast()?來 看,還要多出2種類型來:
* 一是?null?,對于既不是文本類型,又不是二進制類型的字段,如果其內容為空,那么他的意思 其實是?NULL?。
* 二是?yii\db\Expression?數據庫表達式類型。如前面我們提到的?timestamp?的默認值是CURRENT_TIMESTAMP?時,就用到了一個?new?Expression('CURRENT_TIMESTAMP')?。
### PHP類型轉PDO類型[](http://www.digpage.com/db_datatype.html#phppdo "Permalink to this headline")
前面,我們已經實現了創建數據庫時,使用抽象類型來指定字段類型,也實現了從數據庫讀取數據到 PHP(數據庫類型-抽象類型-PHP類型)的轉換過程。
還有一個情景我們沒有涉及到,那就是PHP類型轉數據庫類型的問題。由于Yii通過PDO操作數據庫,因 此,這個問題就成為了PHP類型怎么轉換成PDO數據類型的問題,至于PDO轉數據庫字段類型,由PDO自己 實現,我們就不用操心了。
這里,比如說的SQL查詢參數綁定,?PDO::bindParam()?要求提供參數類型。Yii是能過PHP類型, 直接就轉換成PDO的類型了,具體的代碼在?yii\db\Schema::getPdoType()
~~~
// 將一個PHP數據類型轉換成PDO數據類型
public function getPdoType($data)
{
// 定義一個PHP類型到PDO類型的映射表
static $typeMap = [
'boolean' => \PDO::PARAM_BOOL,
'integer' => \PDO::PARAM_INT,
'string' => \PDO::PARAM_STR,
'resource' => \PDO::PARAM_LOB,
'NULL' => \PDO::PARAM_NULL,
];
$type = gettype($data);
// 在匹配不上映射表時,采用字符串類型
return isset($typeMap[$type]) ? $typeMap[$type] : \PDO::PARAM_STR;
}
~~~
前面我們一直在說,16種抽象數據類型,可以用來表示各種DBMS的各種字段類型。而這16種抽象類型, 具體到PHP數據類型時,逃不過?integer?boolean?resource?string?和?double?5種,再加上特殊的?null?一共是6種。
而在上面的?getPdoType()?中,與6種PHP數據類型對應的,PDO提供了5種,其中?double?類型 用PDO::PARAM_STR?來表示。
至此,PHP、Yii、DBMS、PDO間的數據類型轉換問題就完全解決了。
如果覺得《深入理解Yii2.0》對您有所幫助,也請[幫助《深入理解Yii2.0》](http://www.digpage.com/donate.html#donate)。 謝謝!
- 更新記錄
- 導讀
- Yii是什么
- Yii2.0的亮點
- 背景知識
- 如何閱讀本書
- Yii基礎
- 屬性(Property)
- 事件(Event)
- 行為(Behavior)
- Yii約定
- Yii應用的目錄結構和入口腳本
- 別名(Alias)
- Yii的類自動加載機制
- 環境和配置文件
- 配置項(Configuration)
- Yii模式
- MVC
- 依賴注入和依賴注入容器
- 服務定位器(Service Locator)
- 請求與響應(TBD)
- 路由(Route)
- Url管理
- 請求(Reqeust)
- Web應用Request
- Yii與數據庫(TBD)
- 數據類型
- 事務(Transaction)
- AcitveReocrd事件和關聯操作
- 樂觀鎖與悲觀鎖
- 《深入理解Yii2.0》視頻教程
- 第一講:基礎配置
- 第二講:用戶登錄
- 第三講:文章及評論的模型
- 附錄
- 附錄1:Yii2.0 對比 Yii1.1 的重大改進
- 附錄2:Yii的安裝
- 熱心讀者