数据映射器¶
注意
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()ANDaHAVING条件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()- 重置columnsresetFrom()- 重置fromresetWhere()- 重置whereresetGroupBy()- 重置group byresetHaving()- 重置havingresetOrderBy()- 重置order byresetLimit()- 重置limit和offsetresetFlags()- 重置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