Laravel 模型与 POINT/POLYGON 等使用 DB::raw 表达式

Posted

技术标签:

【中文标题】Laravel 模型与 POINT/POLYGON 等使用 DB::raw 表达式【英文标题】:Laravel model with POINT/POLYGON etc. using DB::raw expressions 【发布时间】:2014-04-17 03:29:10 【问题描述】:

我有一些使用地理空间字段的模型,例如 POINTPOLYGONMULTIPOLYGON。我想告诉我的模型以一种特殊的方式处理这些属性,以便我获得所需的模型属性集。

示例: 每个常规的 Model::find() 或其他 Eloquent 方法都应该在存储或检索数据库值之前应用一些自定义代码。

$area->surfacemysql 中的 POLYGON 字段,但在我的模型类中,我想将 $area->surfare 处理为点数组。

SELECT 上,因此我想 1) 使用原始表达式获取值以获取该值的文本表示形式,以及 2) 通过一些自定义 php 代码将 WKT 字符串转换为数组。

INSERT/UPDATE 上,我想获取属性值(一个数组)并 1)将其转换为 WKT 字符串,然后 2)使用存储该值的 DB 原始语句将其写入数据库。

我想在字段的基础上进行设置,而不是作为每个字段的特殊获取/设置函数,而不是在控制器中 - 因为我有很多地理字段。

有没有办法在 Laravel 中实现这一点?

(同一个问题的一个更抽象的版本,是我如何创建代码来操作实际 SQL 查询的属性值,而不仅仅是通过修改器和访问器进行一些基于值的操作)

更新: 深入研究 Laravel Doc 和 API,我发现 Eloquent::newQuery() 方法可能是我需要操作的?无论是SELECTINSERT 还是UPDATE,它都会用于任何查询吗?

【问题讨论】:

【参考方案1】:

我们现在通过使用以下功能扩展我们的基本模型,为所有模型解决了这个问题:

我们定义了一个包含几何数据的属性数组。 如果我们希望将其作为文本自动加载,我们会根据每个模型来决定。 我们更改了默认查询构建器以从数据库中选择几何属性作为文本。

这是我们现在使用的基本模型的摘录:

/**
 * The attributes that hold geometrical data.
 *
 * @var array
 */
protected $geometry = array();

/**
 * Select geometrical attributes as text from database.
 *
 * @var bool
 */
protected $geometryAsText = false;

/**
 * Get a new query builder for the model's table.
 * Manipulate in case we need to convert geometrical fields to text.
 *
 * @param  bool  $excludeDeleted
 * @return \Illuminate\Database\Eloquent\Builder
 */
public function newQuery($excludeDeleted = true)

    if (!empty($this->geometry) && $this->geometryAsText === true)
    
        $raw = '';
        foreach ($this->geometry as $column)
        
            $raw .= 'AsText(`' . $this->table . '`.`' . $column . '`) as `' . $column . '`, ';
        
        $raw = substr($raw, 0, -2);
        return parent::newQuery($excludeDeleted)->addSelect('*', DB::raw($raw));
    
    return parent::newQuery($excludeDeleted);

【讨论】:

我刚试过这个,它在选择列时几乎按预期工作(返回 POLYGON((98.07 30.12,-98.07 30.53, etc)))。你介意分享一下你是如何处理一个 PHP 数组作为输入的吗?【参考方案2】:

如果修改器和访问器不符合您的需求,您可以使用Model Events 操作这些属性。

然后您可以在某些 Eloquent 事件被触发时执行代码:创建、创建、更新、更新、保存、保存、删除、删除、恢复、恢复。

【讨论】:

我理解观察者的方式是让模型实例通过,这并不是我真正想要的。我想要一种注入在 SELECT、INSERT 和 UPDATE 上执行的 SQL 的方法,以操纵某个字段的读取或写入方式。例如。对于多边形,我希望任何 SELECT 在通过模型触发的任何 SELECT 操作中始终使用 DB::raw('AsText(polygon) as polygon')【参考方案3】:

所有使用postgres数据库的人,laravel-postgis可以用于几何数据

【讨论】:

以上是关于Laravel 模型与 POINT/POLYGON 等使用 DB::raw 表达式的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 与 Symfony |模型属性

laravel 与用户模型的关联问题

Laravel 负载与模型条件的关系

如何在 Laravel 中为模型命名,以免与现有类发生冲突?

将 Laravel 模型与外部 API 数据源同步的正确方法是啥?

Laravel 模型关联建立与查询