CakePHP 3.5 始终将 asText() MySQL 函数应用于空间字段
CakePHP 3.5 Always apply asText() MySQL function to Spatial field
我有一个自定义 PolygonType
,它表示 MySQL table 中的 POLYGON()
字段。
class PolygonType extends BaseType implements ExpressionTypeInterface
{
public function toPHP($value, Driver $d)
{
// $value is binary, requires unpack()
}
}
我可以在每个 查找上使用$query->func()->astext()
,但我想知道是否可以始终 应用MySQL 的 AsText()
函数,而不是选择此字段时(类似于插入数据时可以使用 toExpression()
的方式)。
AFAIK 没有这样的功能,类型 classes 和 select 子句内容永远不会接触。
如果您想将此应用于所有发现,那么您可以使用 Model.beforeFind()
事件,遍历 select
子句并将字段转换为表达式。这是一个简单粗暴的示例,其中 field
是 POLYGON
类型列的名称:
// in the respective table class
use Cake\Event\Event;
use Cake\ORM\Query;
// ...
public function beforeFind(Event $event, Query $query, \ArrayObject $options, $primary)
{
$query->traverse(
function (&$value) use ($query) {
if (empty($value)) {
$value = $query->aliasFields($this->getSchema()->columns());
}
foreach ($value as $key => $field) {
if (is_string($field) &&
$this->aliasField($field) === $this->aliasField('field')
) {
unset($value[$key]);
$value[key($query->aliasField($field))] = $query->func()->AsText([
$this->aliasField('field') => 'identifier'
]);
}
}
},
['select']
);
}
您可能还需要将 $field
考虑为表达式,以防该字段可能在其中使用并且也需要在那里进行转换。
另一种方法是在类型 class' toPHP()
方法中转换 PHP 级别的数据,如您的代码示例中所示。
另见
基于 ndp's ,可以通过 $query->getDefaultTypes()
检查字段类型并根据需要应用 SQL 函数。但是,如果最初没有声明任何字段,$value
为空(例如,当使用 Table::get()
时,因此也会对此进行检查。
public function beforeFind(Event $event, Query $query, ArrayObject $options, $primary)
{
$query->traverse(
function (&$value) use ($query) {
if (is_array($value) && empty($value)) {
$query->all();
}
$defaultTypes = $query->getDefaultTypes();
foreach ($value as $key => $field) {
if (in_array($defaultTypes[$field], ['point', 'polygon'])) {
$value[$key] = $query->func()->astext([
$this->aliasField($field) => 'identifier'
]);
}
}
$query->select($value);
},
['select']
);
}
我有一个自定义 PolygonType
,它表示 MySQL table 中的 POLYGON()
字段。
class PolygonType extends BaseType implements ExpressionTypeInterface
{
public function toPHP($value, Driver $d)
{
// $value is binary, requires unpack()
}
}
我可以在每个 查找上使用$query->func()->astext()
,但我想知道是否可以始终 应用MySQL 的 AsText()
函数,而不是选择此字段时(类似于插入数据时可以使用 toExpression()
的方式)。
AFAIK 没有这样的功能,类型 classes 和 select 子句内容永远不会接触。
如果您想将此应用于所有发现,那么您可以使用 Model.beforeFind()
事件,遍历 select
子句并将字段转换为表达式。这是一个简单粗暴的示例,其中 field
是 POLYGON
类型列的名称:
// in the respective table class
use Cake\Event\Event;
use Cake\ORM\Query;
// ...
public function beforeFind(Event $event, Query $query, \ArrayObject $options, $primary)
{
$query->traverse(
function (&$value) use ($query) {
if (empty($value)) {
$value = $query->aliasFields($this->getSchema()->columns());
}
foreach ($value as $key => $field) {
if (is_string($field) &&
$this->aliasField($field) === $this->aliasField('field')
) {
unset($value[$key]);
$value[key($query->aliasField($field))] = $query->func()->AsText([
$this->aliasField('field') => 'identifier'
]);
}
}
},
['select']
);
}
您可能还需要将 $field
考虑为表达式,以防该字段可能在其中使用并且也需要在那里进行转换。
另一种方法是在类型 class' toPHP()
方法中转换 PHP 级别的数据,如您的代码示例中所示。
另见
基于 ndp's $query->getDefaultTypes()
检查字段类型并根据需要应用 SQL 函数。但是,如果最初没有声明任何字段,$value
为空(例如,当使用 Table::get()
时,因此也会对此进行检查。
public function beforeFind(Event $event, Query $query, ArrayObject $options, $primary)
{
$query->traverse(
function (&$value) use ($query) {
if (is_array($value) && empty($value)) {
$query->all();
}
$defaultTypes = $query->getDefaultTypes();
foreach ($value as $key => $field) {
if (in_array($defaultTypes[$field], ['point', 'polygon'])) {
$value[$key] = $query->func()->astext([
$this->aliasField($field) => 'identifier'
]);
}
}
$query->select($value);
},
['select']
);
}