Phalcon 使用 Oracle 视图
Phalcon use Oracle views
在一个 Phalcon 项目中,我在 Oracle 中有多个数据库,mySQL 有多个表和视图。为相应的表和视图创建模型。但无法访问视图。我在下面的模型中初始化:
public function initialize()
{
$this->setConnectionService('dbBznes');
$this->setSchema('POLICY');
$this->setSource("BUSINESS_ALL");
}
根据评论,这显然是一个元数据问题,默认的元数据策略是内省并试图检查 table 是否存在。您可以像这样设置自己的元数据策略:
$di['modelsMetadata'] = function()
{
$metadata = new \Phalcon\Mvc\Model\MetaData\Memory();
$metadata->setStrategy(
new MyIntrospectionStrategy()
);
return $metadata;
};
"Memory" 在这种情况下意味着不使用任何类型的元数据缓存。这会进入另一个切线,因为您可以通过多种方式缓存以提高生产速度等。
至于上面的MyIntrospectionStrategy
class,它代表你自己的class基于Phalcon的Introspection策略,该策略试图分析数据库以找出涉及的字段及其类型table.
我相信我已将 Phalcon\Mvc\Model\MetaData\Strategy\Introspection 从 Zephir 正确转换为 PHP,如下所示:
class MyIntrospectionStrategy implements \Phalcon\Mvc\Model\MetaData\StrategyInterface
{
public final function getMetaData(\Phalcon\Mvc\ModelInterface $model, \Phalcon\DiInterface $dependencyInjector)
{
$schema = $model->getSchema();
$table = $model->getSource();
$readConnection = $model->getReadConnection();
if( !$readConnection->tableExists($table, $schema) )
{
if($schema)
{
$completeTable = $schema . "'.'" . $table;
} else {
$completeTable = $table;
}
throw new \Phalcon\Mvc\Model\Exception(
"Table '" . $completeTable . "' doesn't exist in database when dumping meta-data for " . get_class($model)
);
}
$columns = $readConnection->describeColumns($table, $schema);
if( !count($columns) )
{
if($schema)
{
$completeTable = $schema . "'.'" . $table;
} else {
$completeTable = $table;
}
/**
* The table not exists
*/
throw new \Phalcon\Mvc\Model\Exception(
"Cannot obtain table columns for the mapped source '" . completeTable . "' used in model " . get_class(model)
);
}
$attributes = [];
$primaryKeys = [];
$nonPrimaryKeys = [];
$numericTyped = [];
$notNull = [];
$fieldTypes = [];
$fieldBindTypes = [];
$automaticDefault = [];
$identityField = false;
$defaultValues = [];
$emptyStringValues = [];
foreach($columns as $column)
{
$fieldName = $column->getName();
$attributes[] = $fieldName;
if ($column->isPrimary() === true)
{
$primaryKeys[] = $fieldName;
} else {
$nonPrimaryKeys[] = $fieldName;
}
if ($column->isNumeric() === true)
{
$numericTyped[$fieldName] = true;
}
if ($column->isNotNull() === true)
{
$notNull[] = $fieldName;
}
if ($column->isAutoIncrement() === true)
{
$identityField = $fieldName;
}
$fieldTypes[$fieldName] = $column->getType();
$fieldBindTypes[$fieldName] = $column->getBindType();
$defaultValue = $column->getDefault();
if ($defaultValue !== null || $column->isNotNull() === false)
{
if ( !$column->isAutoIncrement() )
{
$defaultValues[$fieldName] = $defaultValue;
}
}
}
return [
\Phalcon\Mvc\Model\MetaData::MODELS_ATTRIBUTES => $attributes,
\Phalcon\Mvc\Model\MetaData::MODELS_PRIMARY_KEY => $primaryKeys,
\Phalcon\Mvc\Model\MetaData::MODELS_NON_PRIMARY_KEY => $nonPrimaryKeys,
\Phalcon\Mvc\Model\MetaData::MODELS_NOT_NULL => $notNull,
\Phalcon\Mvc\Model\MetaData::MODELS_DATA_TYPES => $fieldTypes,
\Phalcon\Mvc\Model\MetaData::MODELS_DATA_TYPES_NUMERIC => $numericTyped,
\Phalcon\Mvc\Model\MetaData::MODELS_IDENTITY_COLUMN => $identityField,
\Phalcon\Mvc\Model\MetaData::MODELS_DATA_TYPES_BIND => $fieldBindTypes,
\Phalcon\Mvc\Model\MetaData::MODELS_AUTOMATIC_DEFAULT_INSERT => $automaticDefault,
\Phalcon\Mvc\Model\MetaData::MODELS_AUTOMATIC_DEFAULT_UPDATE => $automaticDefault,
\Phalcon\Mvc\Model\MetaData::MODELS_DEFAULT_VALUES => $defaultValues,
\Phalcon\Mvc\Model\MetaData::MODELS_EMPTY_STRING_VALUES => $emptyStringValues
];
}
public final function getColumnMaps(\Phalcon\Mvc\ModelInterface $model, \Phalcon\DiInterface $dependencyInjector)
{
$orderedColumnMap = null;
$reversedColumnMap = null;
if (method_exists($model, 'columnMap'))
{
$userColumnMap = $model->columnMap();
if ( gettype($userColumnMap) != 'array')
{
// Bad grammer directly in cphalcon :sadface:
throw new \Phalcon\Mvc\Model\Exception('columnMap() not returned an array');
}
$reversedColumnMap = [];
$orderedColumnMap = $userColumnMap;
foreach($userColumnMap as $name => $userName)
{
$reversedColumnMap[$userName] = $name;
}
}
return [$orderedColumnMap, $reversedColumnMap];
}
}
我还没有测试过这个。
至于添加对像 tables 一样对待的视图的支持,更改可能很简单:
之前:
if( !$readConnection->tableExists($table, $schema) )
之后:
if( !$readConnection->tableExists($table, $schema) && !$readConnection->viewExists($table, $schema) )
如果由于 describeColumns 的逻辑阻塞而无法正常工作,您可能需要编写一些特定的内容来处理 Oracle 中针对此方言的视图。
就其他解决方案而言,您可以直接在模型上指定自己的metaData
方法,从而直接在模型上提供自己的元数据方法。
另一种解决方案是使用注释而不是对元数据进行内省。
然后您将您的元数据作为注释放在代码中供 Phalcon 解析。
如果您继续 运行 数据库视图的问题,只需 运行 原始 SQL 而不是尝试使用 ORM 来完成。您可以简单地在模型上定义一个新方法来 运行 原始 SQL.
在一个 Phalcon 项目中,我在 Oracle 中有多个数据库,mySQL 有多个表和视图。为相应的表和视图创建模型。但无法访问视图。我在下面的模型中初始化:
public function initialize()
{
$this->setConnectionService('dbBznes');
$this->setSchema('POLICY');
$this->setSource("BUSINESS_ALL");
}
根据评论,这显然是一个元数据问题,默认的元数据策略是内省并试图检查 table 是否存在。您可以像这样设置自己的元数据策略:
$di['modelsMetadata'] = function()
{
$metadata = new \Phalcon\Mvc\Model\MetaData\Memory();
$metadata->setStrategy(
new MyIntrospectionStrategy()
);
return $metadata;
};
"Memory" 在这种情况下意味着不使用任何类型的元数据缓存。这会进入另一个切线,因为您可以通过多种方式缓存以提高生产速度等。
至于上面的MyIntrospectionStrategy
class,它代表你自己的class基于Phalcon的Introspection策略,该策略试图分析数据库以找出涉及的字段及其类型table.
我相信我已将 Phalcon\Mvc\Model\MetaData\Strategy\Introspection 从 Zephir 正确转换为 PHP,如下所示:
class MyIntrospectionStrategy implements \Phalcon\Mvc\Model\MetaData\StrategyInterface
{
public final function getMetaData(\Phalcon\Mvc\ModelInterface $model, \Phalcon\DiInterface $dependencyInjector)
{
$schema = $model->getSchema();
$table = $model->getSource();
$readConnection = $model->getReadConnection();
if( !$readConnection->tableExists($table, $schema) )
{
if($schema)
{
$completeTable = $schema . "'.'" . $table;
} else {
$completeTable = $table;
}
throw new \Phalcon\Mvc\Model\Exception(
"Table '" . $completeTable . "' doesn't exist in database when dumping meta-data for " . get_class($model)
);
}
$columns = $readConnection->describeColumns($table, $schema);
if( !count($columns) )
{
if($schema)
{
$completeTable = $schema . "'.'" . $table;
} else {
$completeTable = $table;
}
/**
* The table not exists
*/
throw new \Phalcon\Mvc\Model\Exception(
"Cannot obtain table columns for the mapped source '" . completeTable . "' used in model " . get_class(model)
);
}
$attributes = [];
$primaryKeys = [];
$nonPrimaryKeys = [];
$numericTyped = [];
$notNull = [];
$fieldTypes = [];
$fieldBindTypes = [];
$automaticDefault = [];
$identityField = false;
$defaultValues = [];
$emptyStringValues = [];
foreach($columns as $column)
{
$fieldName = $column->getName();
$attributes[] = $fieldName;
if ($column->isPrimary() === true)
{
$primaryKeys[] = $fieldName;
} else {
$nonPrimaryKeys[] = $fieldName;
}
if ($column->isNumeric() === true)
{
$numericTyped[$fieldName] = true;
}
if ($column->isNotNull() === true)
{
$notNull[] = $fieldName;
}
if ($column->isAutoIncrement() === true)
{
$identityField = $fieldName;
}
$fieldTypes[$fieldName] = $column->getType();
$fieldBindTypes[$fieldName] = $column->getBindType();
$defaultValue = $column->getDefault();
if ($defaultValue !== null || $column->isNotNull() === false)
{
if ( !$column->isAutoIncrement() )
{
$defaultValues[$fieldName] = $defaultValue;
}
}
}
return [
\Phalcon\Mvc\Model\MetaData::MODELS_ATTRIBUTES => $attributes,
\Phalcon\Mvc\Model\MetaData::MODELS_PRIMARY_KEY => $primaryKeys,
\Phalcon\Mvc\Model\MetaData::MODELS_NON_PRIMARY_KEY => $nonPrimaryKeys,
\Phalcon\Mvc\Model\MetaData::MODELS_NOT_NULL => $notNull,
\Phalcon\Mvc\Model\MetaData::MODELS_DATA_TYPES => $fieldTypes,
\Phalcon\Mvc\Model\MetaData::MODELS_DATA_TYPES_NUMERIC => $numericTyped,
\Phalcon\Mvc\Model\MetaData::MODELS_IDENTITY_COLUMN => $identityField,
\Phalcon\Mvc\Model\MetaData::MODELS_DATA_TYPES_BIND => $fieldBindTypes,
\Phalcon\Mvc\Model\MetaData::MODELS_AUTOMATIC_DEFAULT_INSERT => $automaticDefault,
\Phalcon\Mvc\Model\MetaData::MODELS_AUTOMATIC_DEFAULT_UPDATE => $automaticDefault,
\Phalcon\Mvc\Model\MetaData::MODELS_DEFAULT_VALUES => $defaultValues,
\Phalcon\Mvc\Model\MetaData::MODELS_EMPTY_STRING_VALUES => $emptyStringValues
];
}
public final function getColumnMaps(\Phalcon\Mvc\ModelInterface $model, \Phalcon\DiInterface $dependencyInjector)
{
$orderedColumnMap = null;
$reversedColumnMap = null;
if (method_exists($model, 'columnMap'))
{
$userColumnMap = $model->columnMap();
if ( gettype($userColumnMap) != 'array')
{
// Bad grammer directly in cphalcon :sadface:
throw new \Phalcon\Mvc\Model\Exception('columnMap() not returned an array');
}
$reversedColumnMap = [];
$orderedColumnMap = $userColumnMap;
foreach($userColumnMap as $name => $userName)
{
$reversedColumnMap[$userName] = $name;
}
}
return [$orderedColumnMap, $reversedColumnMap];
}
}
我还没有测试过这个。
至于添加对像 tables 一样对待的视图的支持,更改可能很简单:
之前:
if( !$readConnection->tableExists($table, $schema) )
之后:
if( !$readConnection->tableExists($table, $schema) && !$readConnection->viewExists($table, $schema) )
如果由于 describeColumns 的逻辑阻塞而无法正常工作,您可能需要编写一些特定的内容来处理 Oracle 中针对此方言的视图。
就其他解决方案而言,您可以直接在模型上指定自己的metaData
方法,从而直接在模型上提供自己的元数据方法。
另一种解决方案是使用注释而不是对元数据进行内省。 然后您将您的元数据作为注释放在代码中供 Phalcon 解析。
如果您继续 运行 数据库视图的问题,只需 运行 原始 SQL 而不是尝试使用 ORM 来完成。您可以简单地在模型上定义一个新方法来 运行 原始 SQL.