Модель Laravel с ТОЧКОЙ/ПОЛИГОНОМ и т.д. с использованием выражений DB::raw


У меня есть несколько моделей, которые используют геопространственные поля, такие как POINT, POLYGON или MULTIPOLYGON. Я хотел бы сказать своей модели, чтобы она обрабатывала эти атрибуты особым образом, чтобы я мог получить желаемый набор атрибутов модели.

Пример: Каждый обычный Model::find() или другой красноречивый метод должен применять некоторый пользовательский код перед сохранением или после извлечения значения базы данных.

$area->surface является полем POLYGON в MySQL, но в моем классе моделей я хотел бы обрабатывать $area->surfare как массив очки.

В SELECT Поэтому я хотел бы 1) получить значение, используя необработанное выражение, чтобы получить текстовое представление значения, и 2) выполнить некоторый пользовательский PHP-код для преобразования строки WKT в массив.

На INSERT/UPDATE Я хотел бы взять значение атрибута (массив) и 1) преобразовать его в строку WKT, после чего 2) оно записывается в базу данных с использованием инструкции DB raw, которая хранит значение.

Я бы хотел установить это на основе поля, а не как специальный get/set функции для каждого поля, а не в контроллерах - потому что у меня много геопространственных полей.

Есть ли способ добиться этого в Laravel?

( Более абстрактная версия того же вопроса заключается в том, как я могу создать код, который манипулирует значениями атрибутов для реальных запросов SQL, а не просто некоторыми манипуляциями на основе значений с помощью мутаторов и средств доступа)

ОБНОВЛЕНИЕ: Заглянув глубже в документ Laravel и API, я обнаружил, что, возможно, Eloquent::newQuery() метод - это то, чем мне нужно манипулировать? Будет ли это использоваться для любого запроса, независимо от того, если SELECT, INSERT или UPDATE?

Author: preyz, 2014-03-12

3 answers

Теперь мы решили эту проблему в общем для всех моделей, расширив нашу базовую модель следующим функционалом:

  • Мы определяем массив атрибутов, содержащих геометрические данные.
  • Мы решаем на основе каждой модели, хотим ли мы, чтобы это автоматически загружалось в виде текста.
  • Мы меняем конструктор запросов по умолчанию, чтобы выбрать атрибуты геометрии в виде текста из базы данных.

Вот выдержка из базовой модели, которую мы сейчас используем:

/**
 * 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);
}
 8
Author: preyz, 2014-10-06 16:21:39

Если мутаторы и средства доступа не соответствуют вашим потребностям, вы можете манипулировать этими атрибутами с помощью событий модели .

Затем вы можете выполнить код, когда будут запущены некоторые из красноречивых событий: создание, создание, обновление, обновление, сохранение, сохранение, удаление, удаление, восстановление, восстановление.

 0
Author: marcanuy, 2014-03-12 20:01:22

Я думаю, что нет ничего плохого в использовании средств доступа/мутаторов.

Вы можете обратиться к моему ответу здесь о том, как я сделал это для средства доступа.

Если вам нужен код для мутатора (сеттера), я мог бы добавить его здесь.

 -1
Author: arcsum, 2017-05-23 12:02:08