模型元数据¶
概览¶
当使用Phalcon\Mvc\Model类,这些类对应数据库中的实际表,Phalcon 需要知道有关这些表的基本信息,例如字段、数据类型、主键和外键以及关系。Phalcon\Mvc\Model\MetaData对象提供此功能,透明地查询数据库并从数据库模式生成必要的数据。然后可以将数据存储在数据存储(如 Redis、APCu 等)中,以确保每次执行查询时不会查询数据库的模式。
注意
在部署到生产环境时,请确保始终使 metaData 缓存失效,以便在部署期间传播的数据库更改可在应用程序中使用。metaData 缓存将重建所有必要的更改。
<?php
use MyApp\Models\Invoices;
use Phalcon\Mvc\Model\MetaData;
$invoice = new Invoices();
/** @var MetaData $metadata */
$metadata = $invoice->getModelsMetaData();
$attributes = $metadata->getAttributes($invoice);
print_r($attributes);
$dataTypes = $metadata->getDataTypes($invoice);
print_r($dataTypes);
上面的代码将打印字段名称以及字段到字段类型的数组。我们使用attributes
作为fields
.
[
[0] => inv_id
[1] => inv_cst_id
[2] => inv_status_flag
[3] => inv_title
[4] => inv_total
[5] => inv_created_at
[6] => inv_created_by
[7] => inv_updated_at
[8] => inv_updated_by
]
[
[inv_id] => 0,
[inv_cst_id] => 0,
[inv_status_flag] => 0,
[inv_title] => 2,
[inv_total] => 0,
[inv_created_at] => 4,
[inv_created_by] => 0,
[inv_updated_at] => 4,
[inv_updated_by] => 0,
]
常量¶
Phalcon\Mvc\Model\MetaData暴露了许多常量,可用于从内部集合中检索属性。
名称 | 描述 |
---|---|
MODELS_ATTRIBUTES | 映射表中的每个列 |
MODELS_AUTOMATIC_DEFAULT_INSERT | 必须忽略的字段INSERT SQL 语句 |
MODELS_AUTOMATIC_DEFAULT_UPDATE | 必须忽略的字段UPDATE SQL 语句 |
MODELS_COLUMN_MAP | 列映射(别名) |
MODELS_DATA_TYPES | 每个列及其数据类型 |
MODELS_DATA_TYPES_BIND | 每个列必须如何绑定/转换 |
MODELS_DATA_TYPES_NUMERIC | 具有数值数据类型的列 |
MODELS_DEFAULT_VALUES | 列的默认值 |
MODELS_EMPTY_STRING_VALUES | 允许空字符串的列 |
MODELS_IDENTITY_COLUMN | 标识列。false 如果模型没有标识列 |
MODELS_NON_PRIMARY_KEY | 不属于主键的每个列 |
MODELS_NOT_NULL | 不允许的每个列null 值 |
MODELS_PRIMARY_KEY | 属于主键的每个列 |
MODELS_REVERSE_COLUMN_MAP | 反向列映射(别名) |
方法¶
返回表属性名(字段) 返回必须忽略的属性INSERT
SQL 生成 返回必须忽略的属性UPDATE
SQL 生成 返回属性及其绑定数据类型 如果有的话返回列映射
返回具有默认值的属性及其默认值 返回属性及其数据类型 返回类型为数值的属性 返回允许空字符串的属性 如果存在,则返回标识字段的名称 返回不属于主键的字段数组 返回非空属性的数组 返回属于主键的字段数组 如果有的话返回反向列映射 返回获取元数据的策略 检查模型是否具有某个属性 检查内部元数据容器是否为空从适配器读取元数据
读取特定模型的有序/反向列映射 使用MODEL_*
常量读取特定模型的列映射信息 读取特定模型的完整元数据 读取特定模型的元数据 重置内部元数据以便重新生成它 设置必须从 INSERT SQL 生成中忽略的属性 设置必须从 UPDATE SQL 生成中忽略的属性 设置允许空字符串值的属性 设置元数据提取策略 将元数据写入适配器 使用 MODEL_* 常量为特定模型写入元数据 print_r(
$metaData->writeColumnMapIndex(
new Invoices(),
MetaData::MODELS_REVERSE_COLUMN_MAP,
[
"title" => "inv_title",
]
)
);
final protected function initialize(
ModelInterface $model,
mixed $key,
mixed $table,
mixed $schema
)
适配器¶
对于本地开发,
注意
For local development, the Phalcon\Mvc\Models\MetaData\Memory推荐使用适配器,以便对数据库的任何更改都可以立即反映出来。
适配器 | 描述 |
---|---|
Phalcon\Mvc\Models\MetaData\Apcu | 该适配器使用另选 PHP 缓存 (APC)存储表元数据。(生产环境) |
Phalcon\Mvc\Models\MetaData\Libmemcached | 该适配器使用Memcached 服务器存储表元数据。(生产环境) |
Phalcon\Mvc\Models\MetaData\Memory | 此适配器使用内存。元数据仅在请求期间缓存。(开发) |
Phalcon\Mvc\Models\MetaData\Redis | 此适配器使用Redis存储表元数据。(生产环境) |
Phalcon\Mvc\Models\MetaData\Stream | 此适配器使用普通文件存储元数据。(不适用于生产环境) |
APCu¶
该适配器使用另选 PHP 缓存 (APC)存储表元数据。为了使该元数据缓存工作,您的系统中必须存在扩展。如果服务器重启,数据将丢失。此适配器适合生产应用程序。
适配器接收一个Phalcon\Cache\AdapterFactory类以实例化相关的缓存对象。你也可以传递一个包含缓存操作额外选项的数组。
默认前缀是ph-mm-apcu-
生命周期是172,000
(48小时)。
<?php
use Phalcon\Cache\AdapterFactory;
use Phalcon\Di\FactoryDefault;
use Phalcon\Mvc\Model\MetaData\Apcu;
use Phalcon\Storage\SerializerFactory;
$container = new FactoryDefault();
$container->set(
'modelsMetadata',
function () {
$serializerFactory = new SerializerFactory();
$adapterFactory = new AdapterFactory($serializerFactory);
$options = [
'lifetime' => 86400,
'prefix' => 'my-prefix',
];
return new Apcu($adapterFactory, $options);
}
);
Libmemcached¶
该适配器使用Memcached 服务器来存储表元数据。你的系统中必须包含此扩展,元数据缓存才能正常工作。该适配器适用于生产环境应用。
适配器接收一个Phalcon\Cache\AdapterFactory类以实例化相关的缓存对象。你也可以传递一个包含缓存操作额外选项的数组。
默认前缀是ph-mm-memc-
生命周期是172,000
(48小时)。persistenId
预设为php-mm-mcid-
.
<?php
use Phalcon\Cache\AdapterFactory;
use Phalcon\Di\FactoryDefault;
use Phalcon\Mvc\Model\MetaData\Libmemcached;
use Phalcon\Storage\SerializerFactory;
$container = new FactoryDefault();
$container->set(
'modelsMetadata',
function () {
$serializerFactory = new SerializerFactory();
$adapterFactory = new AdapterFactory($serializerFactory);
$options = [
'servers' => [
0 => [
'host' => '127.0.0.1',
'port' => 11211,
'weight' => 1
],
],
'lifetime' => 86400,
'prefix' => 'my-prefix',
];
return new Libmemcached($adapterFactory, $options);
}
);
内存¶
此适配器使用服务器内存存储元数据缓存。缓存只在请求期间有效,之后缓存将丢失。此缓存更适合开发环境,因为它适应了开发期间数据库的频繁更改。
<?php
use Phalcon\Di\FactoryDefault;
use Phalcon\Mvc\Model\MetaData\Memory;
$container = new FactoryDefault();
$container->set(
'modelsMetadata',
function () {
return new Memory();
}
);
Redis¶
该适配器使用Redis来存储表元数据。你的系统中必须包含此扩展,元数据缓存才能正常工作。该适配器适用于生产环境应用。
适配器接收一个Phalcon\Cache\AdapterFactory类以实例化相关的缓存对象。你也可以传递一个包含缓存操作额外选项的数组。
默认前缀是ph-mm-reds-
生命周期是172,000
(48小时)。
<?php
use Phalcon\Cache\AdapterFactory;
use Phalcon\Di\FactoryDefault;
use Phalcon\Mvc\Model\MetaData\Redis;
use Phalcon\Storage\SerializerFactory;
$container = new FactoryDefault();
$container->set(
'modelsMetadata',
function () {
$serializerFactory = new SerializerFactory();
$adapterFactory = new AdapterFactory($serializerFactory);
$options = [
'host' => '127.0.0.1',
'port' => 6379,
'index' => 1,
'lifetime' => 86400,
'prefix' => 'my-prefix',
];
return new Redis($adapterFactory, $options);
}
);
流¶
该适配器使用文件系统来存储表元数据。该适配器适用于生产环境应用,但不推荐使用,因为它会增加I/O负载。
适配器可以接受一个metaDadaDir
选项,用于指定存放元数据的目录。默认目录为当前目录。
<?php
use Phalcon\Di\FactoryDefault;
use Phalcon\Mvc\Model\MetaData\Stream;
$container = new FactoryDefault();
$container->set(
'modelsMetadata',
function () {
$options = [
'metaDataDir' => '/app/storage/cache/metaData',
];
return new Stream($options);
}
);
您可以使用orm.exception_on_failed_metadata_save
选项在你的php.ini
文件中,用于强制组件在存储元数据出错或目标目录不可写时抛出异常。
策略¶
获取模型元数据的默认策略是数据库内省(introspection)。使用该策略时,通过信息模式(information schema)来识别表中的字段、主键、可为空的字段、数据类型等。
<?php
use Phalcon\Cache\AdapterFactory;
use Phalcon\Di\FactoryDefault;
use Phalcon\Mvc\Model\MetaData\Apcu;
use Phalcon\Mvc\Model\MetaData\Strategy\Introspection;
use Phalcon\Storage\SerializerFactory;
$container = new FactoryDefault();
$container->set(
'modelsMetadata',
function () {
$serializerFactory = new SerializerFactory();
$adapterFactory = new AdapterFactory($serializerFactory);
$options = [
'lifetime' => 86400,
'prefix' => 'my-prefix',
];
$metadata = new Apcu($adapterFactory, $options);
$metadata->setStrategy(new Introspection());
return $metadata;
}
);
内省¶
该策略不需要任何自定义,并且被所有元数据适配器隐式使用。
注解¶
该策略使用注解来描述模型中的列。
<?php
use Phalcon\Mvc\Model;
class Invoices extends Model
{
/**
* @Primary
* @Identity
* @Column(type='integer', nullable=false)
*/
public $inv_id;
/**
* @Column(type='integer', nullable=false)
*/
public $inv_cst_id;
/**
* @Column(type='string', length=70, nullable=false)
*/
public $inv_title;
/**
* @Column(type='double', nullable=false)
*/
public $inv_total;
}
注解必须放置在映射到源表列的属性上。没有@Column
注解的属性将被视为普通的类属性。
支持以下注解:
名称 | 描述 |
---|---|
@Primary | 将字段标记为表主键的一部分 |
@Identity | 该字段是自增(auto_increment)或序列(serial)列 |
@Column | 将属性标记为映射列 |
注解@Column
支持以下参数:
名称 | 描述 |
---|---|
column | 实际列名 |
type | 列的类型:char , biginteger , blob , boolean , date , datetime , decimal , integer , float , json , longblob , mediumblob , timestamp , tinyblob , text , varchar /string (默认) |
length | 列的长度(如存在) |
nullable | 设置列是否允许null 值 |
skip_on_insert | 在插入时跳过此列 |
skip_on_update | 在更新时跳过此列 |
allow_empty_string | 列允许空字符串 |
default | 默认值 |
注解策略可以如下设置:
<?php
use Phalcon\Cache\AdapterFactory;
use Phalcon\Di\FactoryDefault;
use Phalcon\Mvc\Model\MetaData\Apcu;
use Phalcon\Mvc\Model\MetaData\Strategy\Annotations;
use Phalcon\Storage\SerializerFactory;
$container = new FactoryDefault();
$container->set(
'modelsMetadata',
function () {
$serializerFactory = new SerializerFactory();
$adapterFactory = new AdapterFactory($serializerFactory);
$options = [
'lifetime' => 86400,
'prefix' => 'my-prefix',
];
$metadata = new Apcu($adapterFactory, $options);
$metadata->setStrategy(new Annotations());
return $metadata;
}
);
手动¶
使用上述介绍的内省策略,Phalcon 可以为每个模型自动获取元数据。但是,你可以选择手动定义元数据。该策略会覆盖元数据管理器中设置的任何其他策略。映射表中添加、修改或删除的列必须在模型中手动更新,一切才能正常运行。
要设置元数据,我们在模型中使用metaData
方法:
<?php
use Phalcon\Mvc\Model;
use Phalcon\Db\Column;
use Phalcon\Mvc\Model\MetaData;
class Invoices extends Model
{
public function metaData()
{
return array(
MetaData::MODELS_ATTRIBUTES => [
'inv_id',
'inv_cst_id',
'inv_status_flag',
'inv_title',
'inv_total',
'inv_created_at',
'inv_created_by',
'inv_updated_at',
'inv_updated_by',
],
MetaData::MODELS_PRIMARY_KEY => [
'inv_id',
],
MetaData::MODELS_NON_PRIMARY_KEY => [
'inv_cst_id',
'inv_status_flag',
'inv_title',
'inv_total',
'inv_created_at',
'inv_created_by',
'inv_updated_at',
'inv_updated_by',
],
MetaData::MODELS_NOT_NULL => [
'inv_id',
'inv_cst_id',
'inv_status_flag',
'inv_title',
'inv_total',
'inv_created_at',
'inv_created_by',
'inv_updated_at',
'inv_updated_by',
MetaData::MODELS_DATA_TYPES => [
'inv_id' => Column::TYPE_INTEGER,
'inv_cst_id' => Column::TYPE_INTEGER,
'inv_status_flag' => Column::TYPE_INTEGER,
'inv_title' => Column::TYPE_VARCHAR,
'inv_total' => Column::TYPE_FLOAT,
'inv_created_at' => Column::TYPE_DATETIME,
'inv_created_by' => Column::TYPE_INTEGER,
'inv_updated_at' => Column::TYPE_DATETIME,
'inv_updated_by' => Column::TYPE_INTEGER,
],
MetaData::MODELS_DATA_TYPES_NUMERIC => [
'inv_id' => true,
'inv_cst_id' => true,
'inv_status_flag' => true,
'inv_total' => true,
'inv_created_by' => true,
'inv_updated_by' => true,
],
MetaData::MODELS_IDENTITY_COLUMN => 'inv_id',
MetaData::MODELS_DATA_TYPES_BIND => [
'inv_id' => Column::BIND_PARAM_INT,
'inv_cst_id' => Column::BIND_PARAM_INT,
'inv_status_flag' => Column::BIND_PARAM_INT,
'inv_title' => Column::BIND_PARAM_INT,
'inv_total' => Column::BIND_PARAM_DECIMAL,
'inv_created_at' => Column::BIND_PARAM_STR,
'inv_created_by' => Column::BIND_PARAM_INT,
'inv_updated_at' => Column::BIND_PARAM_STR,
'inv_updated_by' => Column::BIND_PARAM_INT,
],
MetaData::MODELS_AUTOMATIC_DEFAULT_INSERT => [
'inv_created_at' => true,
'inv_created_by' => true,
'inv_updated_at' => true,
'inv_updated_by' => true,
],
MetaData::MODELS_AUTOMATIC_DEFAULT_UPDATE => [
'inv_created_at' => true,
'inv_created_by' => true,
'inv_updated_at' => true,
'inv_updated_by' => true,
],
MetaData::MODELS_DEFAULT_VALUES => [
'inv_status_flag' => 0,
],
MetaData::MODELS_EMPTY_STRING_VALUES => [
'inv_created_at' => true,
'inv_updated_at' => true,
],
);
}
}
自定义¶
Phalcon 提供了Phalcon\Mvc\Model\MetaData\Strategy\StrategyInterface接口,允许你创建自己的策略类。
<?php
namespace MyApp\Components\Strategy;
use Phalcon\Mvc\ModelInterface;
use Phalcon\Di\DiInterface;
class MyStrategy StrategyInterface
{
public function getColumnMaps(
ModelInterface $model,
DiInterface $container
): array;
public function getMetaData(
ModelInterface $model,
DiInterface $container
): array;
}