在 Drupal 8 中以编程方式保存地理域

Save geofield programmatically in Drupal 8

我已经阅读了很多资源,我在尝试以编程方式在 Drupal 中保存坐标时应该使用 geofield_compute_values() 函数。

但是它对我不起作用,我正在使用的 Drupal 8.5.2 中未定义该函数。

我已经使用 composer 安装了 geofield,我可以在管理区像往常一样使用它,在那里保存没有问题。

这是我试过的一些例子,第一个例子给了我 undefined function geofield_compute_values() :

$geofield_data = geofield_compute_values([
    'lat' => $lat,
    'lon' => $lon,
], GEOFIELD_INPUT_LAT_LON);

$cbisProduct->set('field_koordinater', $geofield_data);

我也试过了,没有成功,也没有错误:

$geofield = [
    'geom' => "POINT (" . $lon . " " . $lat . ")",
    'geo_type' => 'point',
    'lat' => $lat,
    'lon' => $lon,
    'left' => $lon,
    'top' => $lat,
    'right' => $lon,
    'bottom' => $lat,
];

$cbisProduct->set('field_koordinater', $geofield);

您似乎在尝试使用 7.x 版本中可用的 geofield_compute_values() 函数,但 8.x

中不可用

您应该查看 wkt_generator 服务。即

<?php $wktGenerator = \Drupal::service('geofield.wkt_generator'); ?>

我还没有尝试过,但是像这样的东西应该可以工作:

<?php

$point = [
  'lat' => $request->get('lat'), 
  'lon' => $request->get('lon'),
];
$value = \Drupal::service('geofield.wkt_generator')->WktBuildPoint($point);

$node->field_koordinater->setValue($value);

此外,WktGeneratorTest.php and GeofieldItemTest.php 文件可能是了解如何在您的实施中使用该服务的良好开端。

此功能在 Drupal 8 中不可用。您必须依赖扩展 FieldItemBase 的基本 GeofieldItem class。另外,正如阿曼所提到的,您可以使用 WktGenerator 轻松构建点、多边形等。

这是一个工作示例。假设您有一个实体 $cbisProduct 和一个多值地理字段 field_koordinater,并且您想要使用任意 lat/lon 坐标设置第一个项目:

// Get geofield item
$geofield = $cbisProduct->get('field_koordinater')->get(0);

// Generate a point [lat, lon]
$coord = ['45.909621', '6.127147'];
$point = \Drupal::service('geofield.wkt_generator')->WktBuildPoint($coord);

// Calling this function will compute values AND assign geodata to the field instance
$geofield->setValue($point);

// You can read the computed geodata from the field
$geodata = $geofield->getValue();
//dpm($geodata);

// Explicitly set field data (needed if $geofield is not a reference)
$cbisProduct->set('field_koordinater', [$geodata]);

// Save entity
$cbisProduct->save();

在幕后,GeofieldItem::setValue 调用另一个负责将计算值直接分配给字段实例的方法:

# \Drupal\geofield\Plugin\Field\FieldType\GeofieldItem
protected function populateComputedValues() {
  /* @var \Geometry $geom */
  $geom = \Drupal::service('geofield.geophp')->load($this->value);

  if (!empty($geom)) {
    /* @var \Point $centroid */
    $centroid = $geom->getCentroid();
    $bounding = $geom->getBBox();

    $this->geo_type = $geom->geometryType();
    $this->lon = $centroid->getX();
    $this->lat = $centroid->getY();
    $this->left = $bounding['minx'];
    $this->top = $bounding['maxy'];
    $this->right = $bounding['maxx'];
    $this->bottom = $bounding['miny'];
    $this->geohash = substr($geom->out('geohash'), 0, GEOFIELD_GEOHASH_LENGTH);
    $this->latlon = $centroid->getY() . ',' . $centroid->getX();
  }
}

注意:您不一定需要 WktGenerator 来构建点,只要您知道地理字段类型以及 geophp 应该如何处理它。例如,以下 2 个语句是等价的:

$point = \Drupal::service('geofield.wkt_generator')->WktBuildPoint($coord);
// is equivalent to 
$point = GEOFIELD_TYPE_POINT . '(' . implode(' ', $coord) . ')');

但是依赖 WktGenerator 更安全,尤其是对于更复杂的数据类型。