使用 DB::raw 表达式的带有 POINT/POLYGON 等的 Laravel 模型

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22360969/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 09:10:31  来源:igfitidea点击:

Laravel model with POINT/POLYGON etc. using DB::raw expressions

phpmysqllaravellaravel-4spatial

提问by preyz

I have some models that use geospatial fields like POINT, POLYGONor MULTIPOLYGON. I would like to tell my model to process these attributes in a special way, for me to get the desired model attributes set.

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

Example: Every regular Model::find()or other Eloquent method should apply some custom code before storing or after retrieving a database value.

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

$area->surfaceis a POLYGONfield in MySQL, but in my model class I would like to handle $area->surfareas an array of points.

$area->surfacePOLYGONMySQL 中的一个字段,但在我的模型类中,我想$area->surfare作为点数组处理。

On SELECTI would therefore like to 1) fetch the value using a raw expression to get a text representation of the value, and 2) go through some custom PHP code to convert the WKT string into an array.

SELECT因此,我要像1)使用原始表达式来获取值的文本表示获取值,和2)通过一些自定义的PHP代码到WKT字符串转换成一个数组。

On INSERT/UPDATEI would like to take the attribute value (an array) and 1) convert it into a WKT string, whereafter 2) it's written to the databse using a DB raw statement that stores the value.

INSERT/UPDATE我想借属性值(阵列)和1)将其转换为WKT字符串,此后2)它采用了一块DB原始声明店该值的写入DATABSE。

I'd like to set this on a field-basis, not as special get/set functions for each field, and not in the controllers - because I have many geosptial fields.

我想在现场设置它,而不是为每个字段设置特殊的获取/设置功能,而不是在控制器中 - 因为我有很多地理空间字段。

Is there a way to achieve this in Laravel?

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

(A more abstract version of the same question, is how I can create code that manipulates attribute values for the actual SQL queries, rather than just some value-based manipulation via mutators & accessors)

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

UPDATE:Looking deeper into the Laravel Doc and API, I found that maybe the Eloquent::newQuery()method is what I need to manipulate? Would that be used for any query regardless if SELECT, INSERTor UPDATE?

更新:深入了解 Laravel Doc 和 API,我发现也许该Eloquent::newQuery()方法是我需要操作的?无论 if SELECT,INSERT还是UPDATE?

回答by preyz

We have now solved this generically for all models by extending our base model with the following functionaly:

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

  • We define an array of attributes that hold geometric data.
  • We decide on a per-model-basis if we want this to be auto-loaded as text.
  • We change the default query builder to select the geometry attributes as text from the database.
  • 我们定义了一组保存几何数据的属性。
  • 如果我们希望将其作为文本自动加载,我们会根据每个模型来决定。
  • 我们更改默认查询构建器以从数据库中选择几何属性作为文本。

Here is an excerpt from the base model we now use:

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

/**
 * 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);
}

回答by marcanuy

If mutators and accessor does not fit your needs, you can manipulate those attributes with Model Events.

如果 mutator 和 accessor 不符合您的需求,您可以使用Model Events操作这些属性。

Then you can execute code when some of the Eloquent events are fired: creating, created, updating, updated, saving, saved, deleting, deleted, restoring, restored.

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

回答by Cyber

For all who use postgres database, laravel-postgiscan be use for geometric data

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