数据映射器¶
注意
DataMapper 的完整实现尚未完成。但有一些组件可以在任何项目中使用,例如Connection
和Query/Select
概览¶
按照Martin Fowler的调用企业应用架构设计模式的表生成模型的最简单方法是:
注意
Mapper 层负责在数据库与对象之间移动数据,并保持它们相互独立,同时也不依赖于 Mapper 本身。
The Phalcon\DataMapper
命名空间包含用于访问数据源的组件,其中使用了数据映射器.
PDO¶
连接¶
此实现所需的一个组件是 PDO 连接器。Phalcon 提供了一个包装 PHP PDO 实现的类,Phalcon\DataMapper\Pdo\Connection使维护连接变得更加简单。
连接到一个数据源
连接到数据库需要 DSN 字符串以及具有访问权限账户的用户名和密码。
DSN 格式如下:
引擎 | DSN |
---|---|
MySQL | mysql:host=<host>;dbname=<database name>;charset=<charset>;port=<port> |
Postgresql | pgsql:host=<host>;dbname=<database name> |
Sqlite | sqlite:<file> |
只需要将<>
中的值替换为你的环境对应的实际值即可。对于charset
和port
是可选的参数。Mysql
对于Sqlite
可以使用memory
作为<file>
但此时数据库不会持久化存储。如果提供一个合适的文件路径,则会为Sqlite
.
<?php
use Phalcon\DataMapper\Pdo\Connection;
$host = '127.0.0.1';
$database = 'phalon_test';
$charset = 'utf8mb4';
$port = 3306;
$username = 'phalcon';
$password = 'secret';
$dsn = sprintf(
"mysql:host=%s;dbname=%s;charset=%s;port=%s",
$host,
$database,
$charset,
$port
);
$connection = new Connection($dsn, $username, $password);
$sql = '
SELECT
inv_id,
inv_title
FROM
co_invoices
WHERE
inv_cst_id = :cst_id
';
$bind = [
'cst_id' => 1
];
$result = $connection->fetchAll($statement, $bind);
方法¶
public function __construct(
string $dsn,
string $username = null,
string $password = null,
array $options = [],
array $queries = [],
ProfilerInterface $profiler = null
)
$dsn
, $username
和$password
用于连接数据源。$options
支持额外的PDO
参数设置。$queries
数组包含了一组当连接建立后要执行的查询。$profiler
是一个可选的对象,需实现ProfilerInterface
接口,用于对连接进行性能分析。 此方法的作用是隐藏堆栈跟踪中的敏感信息(如用户名、密码)。 开始一个事务。如果启用了性能分析器,操作将被记录。 提交当前事务。如果启用了性能分析器,操作将被记录。 连接到数据库。 从数据库断开连接。 获取最近的错误代码。 获取最近的错误信息。 执行一条 SQL 语句并返回受影响的行数。如果启用了性能分析器,操作将被记录。 执行一个语句并返回受影响的行数。 从数据库获取一连串的行;这些行以关联数组的形式返回。 从数据库中获取一个关联数组的行;这些行作为关联数组返回,并且行的数组以每行的第一个列为键。 如果多行具有相同的第一个列值,则具有该值的最后一行将覆盖之前的行。此方法资源消耗更大,应尽可能避免使用。
将一列数据作为顺序数组(默认为第一列)进行获取。public function fetchGroup(
string $statement,
array $values = [],
int $flags = \PDO::FETCH_ASSOC
): array
PDO::FETCH_ASSOC
| PDO::FETCH_GROUP
public function fetchObject(
string $statement,
array $values = [],
string $className = "stdClass",
array $arguments = []
): object
由于 PDO 在调用构造函数之前会注入属性值,因此如果你的对象构造函数中存在任何可能的默认初始化,将会覆盖由 PDO 注入的值。fetchObject
返回的默认对象是\stdClass
public function fetchObjects(
string $statement,
array $values = [],
string $className = "stdClass",
array $arguments = []
): array {
由于 PDO 在调用构造函数之前会注入属性值,因此如果你的对象构造函数中存在任何可能的默认初始化,将会覆盖由 PDO 注入的值。fetchObject
返回的默认对象是\stdClass
quote()
它们的相应占位符将在查询字符串中替换。如果启用了性能分析器,操作将被记录。 准备一个 SQL 语句用于执行。 查询数据库并返回一个 PDOStatement。如果启用了性能分析器,操作将被记录。 对一个值进行引用处理,以便用于 SQL 语句中。这与PDO::quote()
不同之处在于它会将数组转换为逗号分隔的带引用的字符串。默认类型为PDO::PARAM_STR
回滚当前事务,并恢复自动提交模式。如果启用了性能分析器,操作将被记录。 设置数据库连接属性。 设置 Profiler 实例。 protected function fetchData(
string $method,
array $arguments,
string $statement,
array $values = []
): array
PDO::PARAM_*
类型来绑定值。 连接 - 装饰模式¶
连接定位器¶
高流量的应用程序可能使用多个数据库服务器。例如,可以为主写操作配置高性能数据库服务器,而读取操作则使用基于内存的小型数据库服务器。
The Phalcon\DataMapper\ConnectionLocator允许你定义多个Phalcon\DataMapper\Pdo\Connection对象用于读取和写入。所有这些对象都是懒加载的,只有在必要时才会实例化。
实例化¶
创建Phalcon\DataMapper\ConnectionLocator最简单的方法是实例化它并传入一个Phalcon\DataMapper\Pdo\Connection对象。此外,构造函数还可以选择性地接收两个数组,一个用于写入连接,另一个用于读取连接。第一个连接始终是主连接。一旦master
容器消耗更多内存。
$host = '127.0.0.1';
$database = 'phalon_test';
$charset = 'utf8mb4';
$port = 3306;
$username = 'phalcon';
$password = 'secret';
$dsn = sprintf(
"mysql:host=%s;dbname=%s;charset=%s;port=%s",
$host,
$database,
$charset,
$port
);
$connection = new Connection($dsn, $username, $password);
$locator = new ConnectionLocator($connection);
方法¶
构造函数。 返回默认的连接对象。 按名称返回一个读连接;若未指定名称,则随机选取一个连接;若没有读连接,则返回默认连接。 按名称返回一个写连接;若未指定名称,则随机选取一个连接;若没有写连接,则返回默认连接。 设置默认连接工厂。 按名称设置一个读连接工厂。 按名称设置一个写连接工厂。 按名称返回一个连接。配置¶
上的同名属性Phalcon\DataMapper\ConnectionLocator创建完成,你可以添加任意多的读或写连接。可以在定位器创建期间或运行时添加。
运行时¶
首先,使用主连接创建Phalcon\DataMapper\ConnectionLocator对象。主连接是在没有定义读或写连接时使用的默认连接。
<?php
$locator = new ConnectionLocator(
function () use ($options) {
return new Connection(
'mysql:host=10.4.6.1;dbname=phalcon_db;charset=utf8mb4;port=3306',
'username',
'password'
);
}
);
现在你可以根据需求添加任意多个读服务器或写服务器。
<?php
// Write: master
$locator->addRead(
'master',
function () {
return new Connection(
'mysql:host=10.4.4.1;dbname=phalcon_db;charset=utf8mb4;port=3306',
'username',
'password'
);
}
);
// Read: slave01
$locator->addRead(
'slave01',
function () {
return new Connection(
'mysql:host=10.4.8.1;dbname=phalcon_db;charset=utf8mb4;port=3306',
'username',
'password'
);
}
);
// Read: slave02
$locator->addRead(
'slave02',
function () {
return new Connection(
'mysql:host=10.4.8.2;dbname=phalcon_db;charset=utf8mb4;port=3306',
'username',
'password'
);
}
);
// Read: slave03
$locator->addRead(
'slave03',
function () {
return new Connection(
'mysql:host=10.4.8.3;dbname=phalcon_db;charset=utf8mb4;port=3306',
'username',
'password'
);
}
);
构造时¶
也可以在定位器构造时就完成所有配置。这在将定位器设置为 DI 容器中的服务时特别有用。
<?php
// Set up write connections
$write = [
'master' => function () {
return new Connection(
'mysql:host=10.4.4.1;dbname=phalcon_db;charset=utf8mb4;port=3306',
'username',
'password'
);
}
];
// Set up read connections
$read = [
'slave01' => function () {
return new Connection(
'mysql:host=10.4.8.1;dbname=phalcon_db;charset=utf8mb4;port=3306',
'username',
'password'
);
},
'slave02' => function () {
return new Connection(
'mysql:host=10.4.8.2;dbname=phalcon_db;charset=utf8mb4;port=3306',
'username',
'password'
);
},
'slave03' => function () {
return new Connection(
'mysql:host=10.4.8.3;dbname=phalcon_db;charset=utf8mb4;port=3306',
'username',
'password'
);
}
];
$locator = new ConnectionLocator(
function () use ($options) {
return new Connection(
'mysql:host=10.4.6.1;dbname=phalcon_db;charset=utf8mb4;port=3306',
'username',
'password'
);
},
$read,
$write
);
获取连接¶
从定位器中获取连接时,如果尚未实例化,则会自动创建并返回。
getMaster()
将返回主/默认的Phalcon\DataMapper\Pdo\Connection.getRead()
将返回随机的读取用Phalcon\DataMapper\Pdo\Connection;第一次调用之后,getRead()
将总是返回同一个Phalcon\DataMapper\Pdo\Connection。(如果没有定义读连接,则返回默认连接。)getWrite()
将返回随机的写入用Phalcon\DataMapper\Pdo\Connection;第一次调用之后,getWrite()
将总是返回同一个Phalcon\DataMapper\Pdo\Connection。(如果没有定义写连接,则返回默认连接。)
你可以通过传递注册时使用的名称来获取特定的读或写连接。getRead()
或getWrite()
方法。
分析器¶
The Phalcon\DataMapper\Profiler\Profiler是一个允许你对数据库连接进行性能分析的组件。这意味着它可以记录哪些查询被执行过、来源于代码库的何处,以及其执行耗时是多少。Phalcon\DataMapper\Profiler\Profiler接收一个对象来将所有收集到的信息记录到文件中。默认情况下,Phalcon\Logger\Logger使用的是Phalcon\DataMapper\Profiler\MemoryLogger。
The Phalcon\DataMapper\Profiler\Profiler可以通过调用setActive()
方法激活。该方法接收一个布尔标志,同时也作为停用方法使用。只有在分析器处于活动状态时才会记录数据。
<?php
use Phalcon\DataMapper\Pdo\Connection;
use Phalcon\DataMapper\Profiler\MemoryLogger;
use Phalcon\DataMapper\Profiler\Profiler;
$host = '127.0.0.1';
$database = 'phalon_test';
$charset = 'utf8mb4';
$port = 3306;
$username = 'phalcon';
$password = 'secret';
$dsn = sprintf(
"mysql:host=%s;dbname=%s;charset=%s;port=%s",
$host,
$database,
$charset,
$port
);
$profiler = new Profiler(new MemoryLogger());
$connection = new Connection(
$dsn,
$username,
$password,
[
PDO::ATTR_EMULATE_PREPARES => true, // PDO options
],
[
'SET NAMES utf8mb4', // startup queries
],
$profiler
);
// Same profiler as the one we created above
$profiler = $connection->getProfiler();
$profiler->setActive(true)
消息默认按照以下模式进行记录:
您可以使用setLogFormat()
来自定义消息格式
分析器上的可用参数包括:
参数 | 描述 |
---|---|
{backtrace} | 查询执行位置的调用堆栈 |
{duration} | 查询的执行时间 |
{finish} | 分析结束时的微秒时间戳 |
{method} | 调用了连接的方法 |
{start} | 分析开始时的微秒时间戳 |
{statement} | 执行的查询 |
{values} | 传递给查询的任何值 |
注意
参数必须用花括号包裹起来{}
Query¶
工厂¶
The Phalcon\DataMapper\Query
命名空间提供了一个便捷的工厂类,这使得无论是生成select
, insert
, update
还是`delete语句都能快速简便地创建查询对象。该Phalcon\DataMapper\Query\QueryFactory的方法接收一个Phalcon\DataMapper\Pdo\Connection,将生成的对象与该连接绑定。
方法¶
QueryFactory 构造函数。还可以选择性接收一个可以在Select
语句中使用的类名。默认情况下,它使用的是Phalcon\DataMapper\Query\Select. 创建一个新的 Bind 对象 创建一个新的 Delete 对象 创建一个新的 Insert 对象 创建一个新的 Select 对象 创建一个新的 Update 对象 示例¶
<?php
use Phalcon\DataMapper\Pdo\Connection;
use Phalcon\DataMapper\Query\QueryFactory;
$host = '127.0.0.1';
$database = 'phalon_test';
$charset = 'utf8mb4';
$port = 3306;
$username = 'phalcon';
$password = 'secret';
$dsn = sprintf(
"mysql:host=%s;dbname=%s;charset=%s;port=%s",
$host,
$database,
$charset,
$port
);
$connection = new Connection($dsn, $username, $password);
$factory = new QueryFactory();
$select = $factory->newSelect($connection);
删除¶
方法¶
Delete 构造函数。 设置一个AND
的WHERE
条件 追加到最近的WHERE
子句 内联绑定一个值 绑定一个值 - 如有需要自动检测类型 绑定一组值 在查询中添加表 返回所有已绑定的值 @return 字符串 设置表单的LIMIT
子句 设置表单的OFFSET
子句 设置表单的ORDER BY
设置一个OR
的WHERE
条件 在连接中执行一条语句 引号标识符 重置内部数组 重置列 重置标志 重置 from 重置 group by 重置 having 重置 limit 和 offset 重置 order by 重置 where 添加RETURNING
子句 设置查询标志,例如 "DISTINCT" 设置一个WHERE
条件 sw protected function addCondition(
string $store,
string $andor,
string $condition,
mixed $value = null,
int $type = -1
): void
protected function appendCondition(
string $store,
string $condition,
mixed $value = null,
int $type = -1
): void
BY
列表 构造条件字符串 构造标志语句 构造早期的LIMIT
子句 - MS SQLServer 构造LIMIT
子句 构造LIMIT
子句(适用于所有驱动程序) 构造LIMIT
子句(适用于 MSSQLServer) 构造RETURNING
子句 缩进一个集合 处理一个值(数组或字符串)并将其与存储合并 激活¶
要实例化一个Phalcon\DataMapper\Query\Delete查询构造器,你可以使用Phalcon\DataMapper\Query\QueryFactory结合一个Phalcon\DataMapper\Pdo\Connection.
<?php
use Phalcon\DataMapper\Pdo\Connection;
use Phalcon\DataMapper\Query\QueryFactory;
$host = '127.0.0.1';
$database = 'phalon_test';
$charset = 'utf8mb4';
$port = 3306;
$username = 'phalcon';
$password = 'secret';
$dsn = sprintf(
"mysql:host=%s;dbname=%s;charset=%s;port=%s",
$host,
$database,
$charset,
$port
);
$connection = new Connection($dsn, $username, $password);
$factory = new QueryFactory();
$delete = $factory->newDelete($connection);
构建¶
The from()
方法用于指定要删除数据的表。
WHERE¶
The where()
方法用于为DELETE
语句指定条件。
$delete
->from('co_invoices')
->where('inv_cst_id = ', 1)
;
$delete->perform();
// DELETE
// FROM co_invoices
// WHERE inv_cst_id = 1
ORDER BY¶
某些数据库(尤其是MySQL)支持在删除操作中使用ORDER BY
。你可以使用orderBy()
方法来指定它。
$delete
->from('co_invoices')
->where('inv_cst_id = ', 1)
->orderBy('inv_id')
;
$delete->perform();
// DELETE
// FROM co_invoices
// WHERE inv_cst_id = 1
// ORDER BY inv_id
LIMIT/OFFSET¶
某些数据库(MySQL、SQLite)支持LIMIT
和/或OFFSET
子句。你可以使用limit()
和offset()
方法来指定它们。
$delete
->from('co_invoices')
->where('inv_cst_id = ', 1)
->orderBy('inv_id')
->limit(10)
->offset(40)
;
$delete->perform();
// DELETE
// FROM co_invoices
// WHERE inv_cst_id = 1
// ORDER BY inv_id
// LIMIT 10 OFFSET 40
RETURNING¶
一些数据库(尤其是PostgreSQL)支持RETURNING
子句。你可以使用returning()
方法来指定它。
$delete
->from('co_invoices')
->where('inv_cst_id = ', 1)
->orderBy('inv_id')
->limit(10)
->offset(40)
->returning(['inv_id', 'inv_cst_id'])
;
$delete->perform();
// DELETE
// FROM co_invoices
// WHERE inv_cst_id = 1
// ORDER BY inv_id
// LIMIT 10 OFFSET 40
// RETURNING inv_id, inv_cst_id
标志¶
你可以使用setFlag()
方法设置你的数据库服务器识别的标志。例如,你可以设置一个MySQLLOW_PRIORITY
标志,如下所示:
$delete
->from('co_invoices')
->where('inv_cst_id = ', 1)
->orderBy('inv_id')
->limit(10)
->offset(40)
->returning(['inv_id', 'inv_cst_id'])
->setFlag('LOW_PRIORITY')
;
$delete->perform();
// DELETE LOW_PRIORITY
// FROM co_invoices
// WHERE inv_cst_id = 1
// ORDER BY inv_id
// LIMIT 10 OFFSET 40
// RETURNING inv_id, inv_cst_id
插入¶
方法¶
Insert 构造函数。 内联绑定一个值 绑定一个值 - 如有需要自动检测类型 绑定一组值 设置一个列用于INSERT
查询 批量设置列和值用于INSERT
返回所有已绑定的值 返回最后一次插入记录的 ID 返回生成的语句 在查询中添加表 在连接中执行一条语句 引号标识符 重置内部数组 重置...columns
重置...flags
重置...from
重置...group by
重置...having
重置...limit
和offset
重置...order by
重置...where
添加RETURNING
子句 设置一个column = value
条件 设置查询的标志位,比如DISTINCT
构造标志语句 构造RETURNING
子句 缩进一个集合 激活¶
要实例化一个Phalcon\DataMapper\Query\Insert查询构造器,你可以使用Phalcon\DataMapper\Query\QueryFactory结合一个Phalcon\DataMapper\Pdo\Connection.
<?php
use Phalcon\DataMapper\Pdo\Connection;
use Phalcon\DataMapper\Query\QueryFactory;
$host = '127.0.0.1';
$database = 'phalon_test';
$charset = 'utf8mb4';
$port = 3306;
$username = 'phalcon';
$password = 'secret';
$dsn = sprintf(
"mysql:host=%s;dbname=%s;charset=%s;port=%s",
$host,
$database,
$charset,
$port
);
$connection = new Connection($dsn, $username, $password);
$factory = new QueryFactory();
$insert = $factory->newInsert($connection);
构建¶
The into()
方法用于指定要插入数据的表。
列¶
您可以使用column()
方法用于指定列及其绑定的值。最后一个可选参数是由PDO
使用的绑定类型。对于string
, integer
, float
和null
值此会自动设定。
$insert
->into('co_invoices')
->column('inv_total', 100.12)
;
$insert->perform();
// INSERT INTO co_invoices (inv_total) VALUES (:inv_total)
The columns()
方法返回对象本身,从而提供了流畅接口:
$insert
->into('co_invoices')
->column('inv_cst_id', 2)
->column('inv_total', 100.12);
->column('inv_status_flag', 0, PDO::PARAM_BOOL)
;
$insert->perform();
// INSERT INTO co_invoices (
// inv_cst_id,
// inv_total,
// inv_status_flag
// ) VALUES (
// :inv_cst_id,
// :inv_total,
// :inv_status_flag
// )
您还可以使用columns()
方法,它接收一个元素数组。如果键是一个字符串,则将其视为字段名,其值将作为字段的值。或者,对于具有数字键的数组元素,该元素的值将成为字段名。string
it is considered the field name, and its value will be the value of the field. Alternatively, for an array element with a numeric key, the value of that element will be the field name.
$insert
->into('co_invoices')
->columns(
[
'inv_cst_id' => 2,
'inv_total' => 100.12
]
)
;
$insert->perform();
// INSERT INTO co_invoices (
// inv_cst_id,
// inv_total
// ) VALUES (
// :inv_cst_id,
// :inv_total
// )
注意
使用columns()
方法时,不能定义每个字段/值对的PDO
类型。
变量¶
绑定值会自动被加上引号并进行转义。然而,有些情况下我们需要为字段设置特定值而不希望它被转义。一个常见的例子是利用赋值给日期字段的关键字NOW()
。为此我们可以使用set()
方法设置容器。
$insert
->into('co_invoices')
->column('inv_total', 100.12)
->set('inv_created_date', 'NOW()')
;
$insert->perform();
// INSERT INTO co_invoices (
// inv_total,
// inv_created_date
// ) VALUES (
// :inv_total,
// NOW()
// )
语句¶
对象可以通过调用getStatement()
方法设置容器。
$insert
->into('co_invoices')
->column('inv_total', 100.12)
->set('inv_created_date', 'NOW()')
;
echo $insert->getStatement();
// INSERT INTO co_invoices (
// inv_total,
// inv_created_date
// ) VALUES (
// :inv_total,
// NOW()
// )
返回¶
一些数据库(特别是PostgreSQL)支持RETURNING
子句。你可以使用returning()
方法来实现此功能,传递一个包含需要返回字段的数组。
$insert
->into('co_invoices')
->columns(
[
'inv_cst_id',
'inv_total' => 100.12
]
)
->set('inv_id', null)
->set('inv_status_flag', 1)
->set('inv_created_date', 'NOW()')
->columns(
[
'inv_cst_id' => 1
]
)
->returning(
[
'inv_id',
'inv_cst_id'
]
)
->returning(
[
'inv_total'
]
)
->set('inv_created_date', 'NOW()')
;
$insert->perform();
// INSERT INTO co_invoices (
// inv_cst_id,
// inv_total,
// inv_id,
// inv_status_flag,
// inv_created_date
// ) VALUES (
// :inv_cst_id,
// :inv_total,
// NULL,
// 1,
// NOW()
// )
// RETURNING inv_id, inv_cst_id, inv_total
标志¶
你可以使用setFlag()
方法设置你的数据库服务器识别的标志。例如,你可以设置一个MySQLLOW_PRIORITY
标志,如下所示:
$insert
->into('co_invoices')
->column('inv_total', 100.12)
->set('inv_created_date', 'NOW()')
->setFlag('LOW_PRIORITY')
;
$insert->perform();
// INSERT LOW_PRIORITY INTO co_invoices (
// inv_total,
// inv_created_date
// ) VALUES (
// :inv_total,
// NOW()
// )
Select¶
激活¶
要实例化一个Phalcon\DataMapper\Query\Select查询构造器,你可以使用Phalcon\DataMapper\Query\QueryFactory结合一个Phalcon\DataMapper\Pdo\Connection.
<?php
use Phalcon\DataMapper\Pdo\Connection;
use Phalcon\DataMapper\Query\QueryFactory;
$host = '127.0.0.1';
$database = 'phalon_test';
$charset = 'utf8mb4';
$port = 3306;
$username = 'phalcon';
$password = 'secret';
$dsn = sprintf(
"mysql:host=%s;dbname=%s;charset=%s;port=%s",
$host,
$database,
$charset,
$port
);
$connection = new Connection($dsn, $username, $password);
$factory = new QueryFactory();
$select = $factory->newSelect($connection);
执行¶
The Phalcon\DataMapper\Query\Select构建器充当了Phalcon\DataMapper\Pdo\Connection对象的代理。因此,在构建查询之后,下列方法将会可用:
fetchAffected()
fetchAll()
fetchAssoc()
fetchCol()
fetchGroup()
fetchObject()
fetchObjects()
fetchOne()
fetchPairs()
fetchValue()
$records = $select
->from('co_invoices')
->columns(['inv_id', 'inv_title'])
->where('inv_cst_id = 1')
->fetchAssoc()
;
var_dump($records);
// [
// ['inv_id' => 1, 'inv_title' => 'Invoice 1'],
// ['inv_id' => 2, 'inv_title' => 'Invoice 2'],
// ]
构建¶
列¶
要向Select中添加列,请使用columns()
方法并将列作为数组传入。如果一个键定义为了字符串,它将作为列的别名使用。
列名(Column Names)
<?php
$columns = [
'inv_id',
'inv_cst_id',
'inv_status_flag',
'inv_title',
'inv_total',
'inv_created_at',
];
$select->columns($columns);
// SELECT
// inv_id,
// inv_cst_id,
// inv_status_flag,
// inv_title,
// inv_total,
// inv_created_at
别名
<?php
$columns = [
'id' => 'inv_id',
'customerId' => 'inv_cst_id',
'status' => 'inv_status_flag',
'title' => 'inv_title',
'total' => 'inv_total',
'createdAt' => 'inv_created_at',
];
$select->columns($columns);
// SELECT
// id,
// customerId,
// status,
// title,
// total,
// createdAt
计数
<?php
$columns = [
'customerId' => 'inv_cst_id',
'totalCount' => 'COUNT(inv_total)'
];
$select->columns($columns);
// SELECT
// customerId,
// COUNT(inv_total) AS totalCount
FROM
¶
添加一个FROM子句,请使用from()
方法:
直接输出
别名
JOIN
¶
方法。
LEFT
<?php
$select
->from('co_invoices')
->join($select::JOIN_LEFT, 'co_customers', 'inv_cst_id = cst_id')
;
// SELECT * FROM co_invoices
// LEFT JOIN co_customers ON inv_cst_id = cst_id
RIGHT
<?php
$select
->from('co_invoices')
->join($select::JOIN_RIGHT, 'co_customers', 'inv_cst_id = cst_id')
;
// SELECT * FROM co_invoices
// RIGHT JOIN co_customers ON inv_cst_id = cst_id
INNER
<?php
$select
->from('co_invoices')
->join($select::JOIN_INNER, 'co_customers', 'inv_cst_id = cst_id')
;
// SELECT * FROM co_invoices
// INNER JOIN co_customers ON inv_cst_id = cst_id
NATURAL
<?php
$select
->from('co_invoices AS i')
->join($select::JOIN_NATURAL, 'co_customers', 'inv_cst_id = cst_id')
;
// SELECT * FROM co_invoices
// NATURAL JOIN co_customers ON inv_cst_id = cst_id
With Bind
<?php
$status = 1;
$select
->from('co_invoices')
->join(
$select::JOIN_LEFT,
'co_customers',
'inv_cst_id = cst_id AND cst_status_flag = ',
$status
)
->appendJoin(' AND cst_name LIKE ', '%john%')
;
// SELECT * FROM co_invoices
// LEFT JOIN co_customers ON inv_cst_id = cst_id
// AND cst_status_flag = :__1__
// AND cst_name LIKE :__2__
WHERE¶
添加WHERE条件,请使用where()方法。后续对where()
的调用会隐式地AND
连接后续的条件。
单个(Single)
<?php
$invoiceId = 1;
$select
->from('co_invoices')
->where('inv_id > ', $invoiceId)
;
// SELECT * FROM co_invoices
// WHERE inv_id > :__1__
andWhere
<?php
$customerIds = [1, 2, 3];
$status = 1;
$totalValue = 100;
$select
->from('co_invoices')
->where('inv_id > 1')
->andWhere('inv_total > :total')
->andWhere('inv_cst_id IN ', $customerIds)
->appendWhere(' AND inv_status_flag = ' . $select->bindInline($status))
->bindValue('total', $totalValue)
;
// SELECT * FROM co_invoices
// WHERE inv_id > 1
// AND inv_total > :total
// AND inv_cst_id IN (:__1__, :__2__, :__3__)
// AND inv_status_flag = :__4__
orWhere
<?php
$status = 1;
$totalValue = 100;
$select
->from('co_invoices')
->appendWhere('inv_total > ', $totalValue)
->orWhere("inv_status_flag = :status")
->bindValue('status', $status)
;
// SELECT * FROM co_invoices
// WHERE inv_total > :__1__ "
// OR inv_status_flag = :status
whereEquals
还有额外的whereEquals()
快捷方法可以根据一组键值对为您添加一系列相等条件:AND
equality conditions for you based on an array of key-value pairs:
- 给定数组值,条件将是
IN ()
. - 如果给定空数组,条件将是
FALSE
(这意味着查询不会返回任何结果)。 - 给定一个
null
值,条件将是IS NULL
. - 对于所有其他值,条件将是
=
. - 如果您传递了一个没有值的键,该键将作为原始未转义的条件使用。
<?php
$invoiceIds = [1, 2, 3];
$select
->from('co_invoices')
->whereEquals(
[
'inv_id' => $invoiceIds,
'inv_cst_id' => null,
'inv_title' => 'ACME',
'inv_created_at = NOW()',
]
)
;
// SELECT * FROM co_invoices
// WHERE inv_id IN (:__1__, :__2__, :__3__)
// AND inv_cst_id IS NULL
// AND inv_title = :__4__
// AND inv_created_at = NOW()
GROUP BY
¶
添加GROUP BY
表达式,使用groupBy()
方法并将每个表达式作为可变参数传入。
<?php
$select
->from('co_invoices')
->groupBy('inv_cst_id')
->groupBy('inv_status_flag')
;
// SELECT * FROM co_invoices
// GROUP BY inv_cst_id, inv_status_flag
HAVING
¶
The HAVING
方法与它们对应的WHERE
方法:
having()
和andHaving()
AND
aHAVING
条件orHaving()
OR
的HAVING
条件appendHaving()
将追加到最近的HAVING
条件
ORDER BY
¶
添加ORDER BY
表达式,使用orderBy()
方法并将每个表达式作为数组中的一个元素传入。
<?php
$select
->from('co_invoices')
->orderBy(
[
'inv_cst_id',
'UPPER(inv_title) DESC',
]
)
;
// SELECT * FROM co_invoices
// ORDER BY inv_cst_id, UPPER(inv_title) DESC
LIMIT
, OFFSET
,分页(Pagination)¶
设置一个LIMIT
和OFFSET
,请使用limit()
和offset()
方法。
<?php
$select
->from('co_invoices')
->limit(10)
;
// SELECT * FROM co_invoices
// LIMIT 10
$select
->from('co_invoices')
->limit(10)
->offset(50)
;
// SELECT * FROM co_invoices
// LIMIT 10 OFFSET 50
分页
方法。或者,您可以使用page()
和perPage()
方法:
<?php
$select
->from('co_invoices')
->page(5)
->perPage(10)
;
// SELECT * FROM co_invoices
// LIMIT 10 OFFSET 5
DISTINCT
¶
你可以设置DISTINCT
子句如下:
<?php
$select
->distinct()
->from('co_invoices')
->columns(
[
'inv_id',
'inc_cst_id'
]
)
;
// SELECT DISTINCT inv_id, inc_cst_id
// FROM co_invoices
注意
该方法接受一个可选的布尔参数,用于启用(true
) 或禁用(false
)该标志。
FOR UPDATE
¶
你可以设置FOR UPDATE
子句如下:
<?php
$select
->from('co_invoices')
->forUpdate()
;
// SELECT * FROM co_invoices FOR UPDATE
$select
->from('co_invoices')
->forUpdate()
->forUpdate(false)
;
// SELECT * FROM co_invoices
注意
该方法接受一个可选的布尔参数,用于启用(true
) 或禁用(false
)该标志。
标志¶
你可以使用setFlag()
方法设置你的数据库服务器识别的标志。例如,你可以设置一个MySQLHIGH_PRIORITY
标志,如下所示:
<?php
$select
->from('co_invoices')
->setFlag('HIGH_PRIORITY')
;
// SELECT HIGH_PRIORITY * FROM co_invoices
UNION
¶
要UNION
或UNION ALL
当前Select
使用后续语句进行查询时,调用以下任意一个union*()
方法:
<?php
$select
->from('co_invoices')
->where('inv_id = 1')
->union()
->from('co_invoices')
->where('inv_id = 2')
->union()
->from('co_invoices')
->where('inv_id = 3')
;
// SELECT * FROM co_invoices WHERE inv_id = 1
// UNION
// SELECT * FROM co_invoices WHERE inv_id = 2
// UNION
// SELECT * FROM co_invoices WHERE inv_id = 3
$select
->from('co_invoices')
->where('inv_id = 1')
->unionAll()
->from('co_invoices')
->where('inv_id = 2')
;
// SELECT * FROM co_invoices WHERE inv_id = 1
// UNION ALL
// SELECT * FROM co_invoices WHERE inv_id = 2
重置¶
The Select
类提供了reset()
方法,它允许你将对象重置为其原始状态并重新使用它(例如:重新发送一条语句以获取COUNT(*)
不带LIMIT
的情况下,计算分页总行数)。
另外,下列方法允许你重置查询中的特定部分:
resetColumns()
- 重置columns
resetFrom()
- 重置from
resetWhere()
- 重置where
resetGroupBy()
- 重置group by
resetHaving()
- 重置having
resetOrderBy()
- 重置order by
resetLimit()
- 重置limit
和offset
resetFlags()
- 重置flags
子查询对象¶
如果你想创建一个子查询,请调用subSelect()
方法。当你完成子查询构建后,使用asAlias()
方法为其赋予一个别名;该对象本身可以在所需的条件或表达式中使用。当在FROM
条件中使用时,你需要调用getStatement()
方法,以返回正确的SQL语句给Select
对象中的相关方法手动
<?php
$select
->from(
$select
->subSelect()
->columns("inv_id")
->from('co_invoices')
->asAlias('inv')
->getStatement()
)
;
// SELECT *
// FROM (SELECT inv_id FROM co_invoices) AS inv
当我们需要传递参数时,可以直接将它们添加到子查询中。
<?php
$invoiceId = 1;
$maxInvoice = 100;
$select
->from(
$select
->subSelect()
->columns('inv_id')
->from('co_invoices')
->where('inv_id > ', $invoiceId)
->asAlias('inv')
->getStatement()
)
->where('inv_id <', $maxInvoice)
;
// SELECT *
// FROM (SELECT inv_id FROM co_invoices WHERE inv_id > __1__) AS inv
// WHERE inv_id < __2__
子查询也可以在JOIN
和WHERE
条件中使用,如下所示:
<?php
$select
->from('co_invoices')
->join(
'LEFT'
$select
->subSelect()
...
->asAlias('subAlias')
->getStatement()
)
;
对于WHERE
特别是,你不需要使用getStatement()
<?php
$customerId = 1;
$total = 100.0
$select
->columns(
[
'inv_id',
'inv_total'
]
)
->from('co_invoices')
->where(
'inv_id IN '
$select
->subSelect()
->columns(
[
'cst_inv_id',
]
)
->from('co_customers')
->where('inv_total > ', $total)
)
;
// SELECT inv_id, inv_total
// FROM co_invoices
// WHERE inv_id IN (SELECT cst_inv_id FROM co_customers WHERE inv_total > __1__)
更新¶
方法¶
设置一个AND
的WHERE
条件
追加到最近的WHERE
子句
内联绑定一个值
绑定一个值 - 如有需要自动检测类型
绑定一组值
设置一个列用于UPDATE
查询
批量设置列和值用于UPDATE
向查询中添加一张表
返回所有已绑定的值
返回SQL语句
查询是否有列
设置表单的LIMIT
子句
设置表单的OFFSET
子句
设置表单的ORDER BY
设置一个OR
的WHERE
条件
在连接中执行一条语句
引号标识符
添加RETURNING
子句
重置内部存储
重置列
重置标志
重置 from
重置 group by
重置 having
重置 limit 和 offset
重置 order by
重置 where
设置列 = 值条件
设置查询标志,例如 "DISTINCT"
设置一个WHERE
条件
设置一个WHERE
等值条件
protected function addCondition(
string $store,
string $andor,
string $condition,
mixed $value = null,
int $type = -1
): void
追加一个条件
protected function appendCondition(
string $store,
string $condition,
mixed $value = null,
int $type = -1
): void
连接一个条件
构造一个BY
列表
构造条件字符串
构造标志语句
构造早期的LIMIT
子句 - MS SQLServer
构造LIMIT
子句
构造LIMIT
子句(适用于所有驱动程序)
构造LIMIT
子句(适用于 MSSQLServer)
构造RETURNING
子句
缩进一个集合
处理一个值(数组或字符串)并将其与存储合并
激活¶
要实例化一个Phalcon\DataMapper\Query\Update查询构造器,你可以使用Phalcon\DataMapper\Query\QueryFactory结合一个Phalcon\DataMapper\Pdo\Connection.
<?php
use Phalcon\DataMapper\Pdo\Connection;
use Phalcon\DataMapper\Query\QueryFactory;
$host = '127.0.0.1';
$database = 'phalon_test';
$charset = 'utf8mb4';
$port = 3306;
$username = 'phalcon';
$password = 'secret';
$dsn = sprintf(
"mysql:host=%s;dbname=%s;charset=%s;port=%s",
$host,
$database,
$charset,
$port
);
$connection = new Connection($dsn, $username, $password);
$factory = new QueryFactory();
$insert = $factory->newUpdate($connection);
构建¶
The table()
方法用于指定要插入数据的表。
列¶
您可以使用column()
方法用于设置特定列的新值。
$update
->table('co_invoices');
->column('inv_cst_id', 2)
->column('inv_total', 100.12);
->column('inv_status_flag', 0, PDO::PARAM_BOOL)
;
$update->perform();
// UPDATE co_invoices
// SET inv_cst_id = :inv_cst_id,
// inv_total = :inv_total,
// inv_status_flag = :inv_status_flag
注意
PDO参数类型将会自动为strings
, integers
, floats
和nulls
设置。你可以使用column()
的第三个参数来设置所需类型。
除了多次调用column()
方法之外,你始终可以调用columns()
并传入一个数组,其中数组键是字段名,数组值是你想要更新的对应值。
$update
->table('co_invoices');
->columns(
[
'inv_cst_id' => 2,
'inv_total' => 100.12,
'inv_status_flag' => 0,
]
)
;
$update->perform();
// UPDATE co_invoices
// SET inv_cst_id = :inv_cst_id,
// inv_total = :inv_total,
// inv_status_flag = :inv_status_flag
注意
使用columns()
方法时,你无法设置每个参数的类型。
WHERE¶
The WHERE
的方法与UPDATE
完全相同。Select
ORDER BY¶
某些数据库(尤其是MySQL)支持在删除操作中使用ORDER BY
。你可以使用orderBy()
方法来指定它。
$update
->table('co_invoices');
->columns(
[
'inv_cst_id' => 2,
'inv_total' => 100.12,
'inv_status_flag' => 0,
]
)
->where('inv_cst_id = ', 1)
->orderBy('inv_id')
;
$update->perform();
// UPDATE co_invoices
// SET inv_cst_id = :inv_cst_id,
// inv_total = :inv_total,
// inv_status_flag = :inv_status_flag
// WHERE inv_cst_id = 1
// ORDER BY inv_id
LIMIT/OFFSET¶
某些数据库(MySQL、SQLite)支持LIMIT
和/或OFFSET
子句。你可以使用limit()
和offset()
方法来指定它们。
$update
->table('co_invoices');
->columns(
[
'inv_cst_id' => 2,
'inv_total' => 100.12,
'inv_status_flag' => 0,
]
)
->where('inv_cst_id = ', 1)
->orderBy('inv_id')
->limit(10)
->offset(40)
;
$update->perform();
// UPDATE co_invoices
// SET inv_cst_id = :inv_cst_id,
// inv_total = :inv_total,
// inv_status_flag = :inv_status_flag
// WHERE inv_cst_id = 1
// ORDER BY inv_id
// LIMIT 10 OFFSET 40
RETURNING¶
一些数据库(特别是PostgreSQL)支持RETURNING
子句。你可以使用returning()
方法来实现此功能,传递一个包含需要返回字段的数组。
$update
->table('co_invoices');
->columns(
[
'inv_cst_id' => 2,
'inv_total' => 100.12,
'inv_status_flag' => 0,
]
)
->where('inv_cst_id = ', 1)
->orderBy('inv_id')
->limit(10)
->offset(40)
->returning(['inv_id', 'inv_cst_id'])
;
$update->perform();
// UPDATE co_invoices
// SET inv_cst_id = :inv_cst_id,
// inv_total = :inv_total,
// inv_status_flag = :inv_status_flag
// WHERE inv_cst_id = 1
// ORDER BY inv_id
// RETURNING inv_id, inv_cst_id
标志¶
你可以使用setFlag()
方法设置你的数据库服务器识别的标志。例如,你可以设置一个MySQLLOW_PRIORITY
标志,如下所示:
$update
->table('co_invoices');
->columns(
[
'inv_cst_id' => 2,
'inv_total' => 100.12,
'inv_status_flag' => 0,
]
)
->where('inv_cst_id = ', 1)
->orderBy('inv_id')
->limit(10)
->offset(40)
->returning(['inv_id', 'inv_cst_id'])
->setFlag('LOW_PRIORITY')
;
$update->perform();
// UPDATE LOW_PRIORITY co_invoices
// SET inv_cst_id = :inv_cst_id,
// inv_total = :inv_total,
// inv_status_flag = :inv_status_flag
// WHERE inv_cst_id = 1
// ORDER BY inv_id
// RETURNING inv_id, inv_cst_id