2014-03-12 8 views
7

Ich habe einige Modelle, die geospatial Felder wie POINT, POLYGON oder MULTIPOLYGON verwenden. Ich möchte meinem Modell sagen, dass ich diese Attribute in einer speziellen Weise verarbeiten soll, damit ich die gewünschten Modellattribute einstellen kann.Laravel-Modell mit POINT/POLYGON usw. mit DB :: rohe Ausdrücke

Beispiel: Jede reguläre Model::find() oder andere Eloquent-Methode sollte vor dem Speichern oder nach dem Abrufen eines Datenbankwerts einen benutzerdefinierten Code anwenden.

$area->surface ist ein POLYGON Feld in MySQL, aber in meiner Modellklasse würde ich gerne $area->surfare als ein Array von Punkten behandeln.

Unter SELECT möchte ich daher 1) den Wert mit einem Raw-Ausdruck abrufen, um eine Textdarstellung des Werts zu erhalten, und 2) durch einige benutzerdefinierte PHP-Code, um die WKT-Zeichenfolge in ein Array zu konvertieren.

Auf INSERT/UPDATE möchte ich den Attributwert (ein Array) und 1) in eine WKT-Zeichenfolge konvertieren, wonach 2) es in die Datenbank mit einer DB-Anweisung geschrieben wird, die den Wert speichert.

Ich möchte dies auf einer Feld-Basis einstellen, nicht als spezielle Get/Set-Funktionen für jedes Feld, und nicht in den Controllern - weil ich viele geospatial Felder habe.

Gibt es einen Weg, dies in Laravel zu erreichen?

(eine abstraktere Version derselben Frage ist, wie ich Code erstellen kann, die Attributwerte für die tatsächlichen SQL-Abfragen manipuliert, anstatt nur einige wertbasierte Manipulation über Mutatoren & Accessoren)

UPDATE: Wenn Sie tiefer in Laravel Doc und API schauen, habe ich festgestellt, dass vielleicht die Eloquent::newQuery() Methode ist, was ich manipulieren muss? Würde das für irgendeine Abfrage verwendet werden, egal ob SELECT, INSERT oder UPDATE?

Antwort

7

Wir haben nun diese generisch für alle Modelle durch Erweiterung unserer Basismodell mit der folgenden functionaly gelöst:

  • Wir definieren eine Reihe von Attributen, die geometrischen Daten enthalten.
  • Wir entscheiden uns auf einer Modell-Basis, wenn wir möchten, dass dies automatisch als Text geladen wird.
  • Wir ändern den Standard-Abfrage-Generator, um die Geometrieattribute als Text aus der Datenbank auszuwählen. Hier

ist ein Auszug aus dem Basismodell, das wir jetzt nutzen:

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

Ich habe es gerade versucht und es funktionierte fast wie erwartet bei der Auswahl der Spalte (Rückgabe POLYGON ((98,07 30,12, -98,07 30,53, etc))). Würde es Ihnen etwas ausmachen, wie Sie ein PHP-Array als Eingabe behandelt haben? – daraul

0

Wenn Mutatoren und Accessor nicht Ihren Anforderungen entsprechen, können Sie diese Attribute mit Model Events bearbeiten.

Dann können Sie Code ausführen, wenn einige der Eloquent-Ereignisse ausgelöst werden: Erstellen, Erstellen, Aktualisieren, Aktualisieren, Speichern, Speichern, Löschen, Löschen, Wiederherstellen, Wiederherstellen.

+0

So wie ich Beobachter zu verstehen, ist, dass ich die Modellinstanz bekommen übergeben, die nicht wirklich das, was ich suche. Ich möchte einen Weg finden, um in die SQL zu injizieren, die auf SELECT, INSERT & UPDATE ausgeführt wird, um die Art zu manipulieren, in der ein bestimmtes Feld gelesen oder geschrieben wird. Z.B. Für ein Polygon möchte ich, dass jedes SELECT immer 'DB :: raw ('AsText (Polygon) als Polygon')' in jeder SELECT-Operation verwendet, die über das Model ausgelöst wird. – preyz

-1

Ich denke, es ist nichts falsch mit der Verwendung der Accessoren/Mutatoren.

können Sie auf meine Antwort here beziehen, wie ich es für den Accessor tat.

Wenn Sie den Code für den Mutator benötigen, (Setter,) könnte ich es hier hinzufügen.