Objekt-Presenter

Der Objekt-Presenter \Alvine\Application\Web\Presenter\Data\Object ist von \Alvine\Application\Web\Presenter\Data abgeleitet und stellt Methoden für die bearbeitung von DELETE, GET, HEAD, PUT und PATCH Anfragen bereit. Für die POST Methode ist ein eigener Add-Presenter verantwortlich.

Die Steuerung, welcher View zur Anwendung kommt, erfolgt über den vom Client mitgesendeten Accept-Header. Hier ist entweder application/json oder text/html möglich. Für die HTML-Ausgabe ist der Standardview des Presenters - wenn keiner über die Konfiguration angegeben wird - die von der Methode Object::getDefaultViewClass() zurückgegebene Klasse.

Der View kann auch über die Konfiguration in der Route definiert werden.

Hinweis

Sie müssen sicherstellen das Ihr View das Interface \Alvine\Application\Web\View\InstanceFromContainer implementiert.

Die Datenpresenter arbeiten normalerweise mit einem Suchindex (Solr, EleasticSearch) und einem Objektstorage (MongoDB, Riak, ...) zusammen. Der Presenter kann aber auch für die Verwendung mit SQL-Server konfiguriert werden. Hierzu muss neben der Konfiguration des Storage-Managers auch das Query-Modell angepasst werden. Im Query wird unter anderem der Aufbau des Suchsyntaxes definiert.

Hierzu kann in der Routenkonfiguration ein Tag mit der entsprechenden Klasse gesetzt werden.

<configuration>
    <query>  <!-- Klassenname des Query -->
        <class>MyQuery</class>    
    </query>
</configuration>

Für die Verwendung von relationalen Datenbanken kann die Klasse Alvine\Persistence\Provider\MySQL\Query verwendet werden. Alternativ kann der Presenter auch abgeleitet und die Methode Data::createQueryInstance() überschrieben werden.

Objekt holen

Über die GET Anfrage können ein oder mehrere Objekte abgefragt werden. Die Einschränkung erfolgt über die definierten Parameter. Hier können die gewünschten Feldnamen über name=value eingeschränkt werden. Je nach View wird die Ausgabe als HTML-Datei oder Json zurückgegeben.

Über folgende Parameter lassen sich weitere Einstellungen vornehmen:

Parmater Beschreibung
count Ergebnisse pro Anfrage
name Name des zu ändernden Feldes
offset Offset der zurückgegeben werden soll
orderby Feldnamen nach denen Sortiert werden soll
page Seiten die zurückgegeben werden soll

Im folgenden Beispiel werden maximal 10 Objekte, beginnend auf Seite 2 und nach dem Feld name sortiert zurückgegeben.

curl --request GET \
  --url 'http://example.com/api/myobject?count=10&page=2&orderby=name' \
  --header 'accept: application/json'

Konfiguration der Route

<route id="ROUTE-ID-GET">
    <method>GET</method>
    <presenter>MyPresenter</presenter>
    <pattern><![CDATA[^\/api\/object$]]></pattern>
    <template><![CDATA[/api/object]]></template>
    <configuration>
        <model>  <!-- Klassenname des Models -->
            <class>MyModel</class>    
        </model>

        <query>  <!-- Klassenname des Query -->
            <class>MyQuery</class>    
        </query>

        <!-- erlaubte Mimetypes für die Antwort: Möglichkeiten: json, html -->
        <mimetypes>
            <allowed>text/html</allowed>    
            <allowed>application/json</allowed>  
        </mimetypes>

        <view>  <!-- Klassenname des Views für HTML und JSON -->
            <class type="texyt/html">\Alvine\Application\Web\View\Data\Object</class>   
            <class type="application/json">\Alvine\Application\Web\View\Json\Dataset</class>    
        </view>
    </configuration>
</route>

Objekte ändern

Über die PUT Anfrage können ein oder mehrere Objekte geändert werden. Als Ergebnis wird entweder der Status 204 No Content oder wenn JSON unterstützt wird ein Array mit dem Ergebnis zurück gegeben. Über den Parameter whatif kann die Anfrage simuliert werden.

Parmater Beschreibung
whatif Anfrage nur flüchtig, ohne echte Aktion durchführen

Wird in der Route eine Redirect-URL definiert, so wird diese bei der Änderung eines Datensatzes per Location Header an den Client übergeben. Bei der Rückgabe von JSON oder mehreren Änderungen ist die Location in der Antwort enthalten.

In dem folgenden Beispiel werden die zwei Datensätze mit der ID 2 und 5 geändert.

curl --request PUT \
  --url 'http://example.com/api/object' \
  --header 'accept: application/json' \
  --header 'content-type: application/json' \
  --data '{
    "dataset": [
        {
            "id": 2,
            "name": "Neuer Name",
        },
        {
            "id": 5,
            "flag":2,
        }
    ]
}'

Im Erfolgsfall ist das Ergebnis folgendes JSON

{
  "dataset": [
    {
      "dataset": {
        "id": 2,
        "name": "Neuer Name",
        "flag": 5,
      },
      "sys": {
        "updated": "2017-10-21T16:15:35",
        "message": "200 OK",
        "code": 200,
        "location": ""
      }
    },
    {
      "dataset": {
        "id": 5,
        "name": "Alter Name",
        "flag": 2,
      },
      "sys": {
        "updated": "2017-10-21T16:15:35",
        "message": "200 OK",
        "code": 200,
        "location": ""
      }
    }
  ]
}

In diesem Beispiel wurde ein Datensatz geändert und beim zweiten Datensatz ist ein Fehler aufgetreten (die angegebene ID gibt es nicht; 404).

{
    "dataset": [
        {
            "dataset": {
              "id": 5,
              "name": "Alter Name",
              "flag": 2,
            },
            "sys": {
                "updated": "2017-10-21T16:30:31",
                "message": "200 OK",
                "code": 200,
                "location": ""
            }
        },
        {
            "sys": {
                "error": {
                    "code": 404,
                    "message": "404 Not Found"
                }
            }
        }
    ],
    "sys": {
        "error": {
            "code": 400,
            "message": "400 Bad Request"
        }
    }
}

Werden keine oder falsche Daten übertragen, so wird folgende Fehlermeldung zurückgegeben:

{
    "sys": {
        "error": {
            "code": 400,
            "message": "400 Bad Request"
        }
    }
}

Konfiguration der Route

In diesem Beispiel wird das zu ändernde Objekte über die ID bestimmt und geändert.

<route id="ROUTE-ID-UPDATE">
    <method>PUT</method>
    <presenter>MyPresenter</presenter>
    <pattern><![CDATA[^\/api\/object\/(?<id>[0-9]+)$]]></pattern>
    <template><![CDATA[/api/object/${id}]]></template>
    <configuration>
        <model>  <!-- Klassenname des Models -->
            <class>MyModel</class>    
        </model>
    </configuration>
</route> 

Mehrere Objekte können über folgende Konfiguration verarbeitet werden. Wichtig ist hier, dass der Parameter dataset definiert ist.

<route id="ROUTE-ID-UPDATE">
    <method>PUT</method>
    <presenter>MyPresenter</presenter>
    <pattern><![CDATA[^\/api\/object$]]></pattern>
    <template><![CDATA[/api/object]]></template>
    <parameters>
        <parameter name="dataset" type="ArrayType" />
    </parameters>
    <configuration>
        <model>  <!-- Klassenname des Models -->
            <class>MyModel</class>    
        </model>
    </configuration>
</route> 

Ein Redirect kann über den Linksbereich in der Route definiert werden.

<route id="ROUTE-ID-UPDATE">
    ...
    <links> 
        <!-- die ID der anzuwendende Route und die Relation "redirect" -->
        <link route="ROUTE-ID-UPDATE" relation="redirect" />
    </links>
</route> 

Objekte löschen

Über die DELETE Anfrage können ein oder mehrere Objekte gelöscht werden. Als Ergebnis wird entweder der Status 204 No Content oder wenn JSON unterstützt wird ein Array mit dem Ergebnis zurück gegeben. Die Einschränkung, welches Objekt gelöscht werden soll erfolgt über die in den Parametern übergebene ID.

Parmater Beschreibung
whatif Anfrage nur flüchtig, ohne echte Aktion durchführen

Die folgende Anfrage löscht den Datensatz mit der ID 1.

curl --request DELETE \
  --url 'http://example.com/api/myobject/1' \
  --header 'accept: application/json'

Wird an die URL der Parameter whatif angehängt, so wird der Datensatz nur geprüft, aber nicht gelöscht.

curl --request DELETE \
  --url 'http://example.com/api/myobject/1?whatif=true' \
  --header 'accept: application/json'

Mehrere Objekte können über ein JSON mit den entsprechenden IDs gelöscht werden. Hierzu muss in der Route (siehe unten) der Parameter dataset definiert werden.

curl --request DELETE \
  --url 'http://example.com/api/myobject' \
  --header 'accept: application/json' \
  --header 'content-type: application/json' \
  --data '{
        "dataset": [
            {
                "id": 1
            },
            {
                "id": 2
            }
        ]
    }'

Das Ergebnis ist dann im Erfolgsfall folgendes:

{
    "dataset": [
        {
            "sys": {
                "message": "200 OK",
                "code": 200
            }
        },
        {
            "sys": {
                "message": "200 OK",
                "code": 200
            }
        }
    ]
}

Werden die Objekte nicht gefunden, so wird ein 404 Fehler zurückgegeben.

Konfiguration der Route

In diesem Beispiel wird die ID des zu löschenden Objektes in die URL integriert und von dort ausgelesen. Somit ist die ID der URL Bestandteil der URL.

<route id="ROUTE-ID-DELETE">
    <method>DELETE</method>
    <presenter>MyPresenter</presenter>
    <pattern><![CDATA[^\/api\/object\/(?<id>[0-9]+)$]]></pattern>
    <template><![CDATA[/api/object/${id}]]></template>
    <configuration>
        <model>  <!-- Klassenname des Models -->
            <class>MyModel</class>    
        </model>
    </configuration>
</route> 

Sollen mehrere Objekte mit einem Request gelöscht werden, so kann dies über ein JSON erfolgen. Die entsprechende Route muß folgendermaßen aussehen.

<route id="ROUTE-ID-DELETE">
    <method>DELETE</method>
    <presenter>MyPresenter</presenter>
    <pattern><![CDATA[^\/api\/object$]]></pattern>
    <template><![CDATA[/api/object]]></template>
    <parameters>
        <parameter name="dataset" type="ArrayType" />
    </parameters>
    <configuration>
        <model>  <!-- Klassenname des Models -->
            <class>MyModel</class>    
        </model>
    </configuration>
</route> 

Kopfdaten anfragen

Head-Anfragen werden durch die GET-Methode bearbeitet. Das Verhalten ist dort beschrieben.

Eigenschaft eines Objektes ändern

Mittels PATCH-Anfragen lassen sich einzelne Eigenschaften eines Objektes überschreiben. Die Daten können entweder als application/json oder x-www-form-urlencoded übertragen werden.

Parmater Beschreibung
name Name des zu ändernden Feldes
uuid Primärschlüssel des Datensatzes der geändert werden soll
pk Alternativer Name für den Primärschlüssel
value Neuer Wert des zu ändernden Feldes
whatif Anfrage nur flüchtig, ohne echte Aktion durchführen
curl --request PATCH \
  --url 'http://{{domain}}/api/commerce/item/catalog/category' \
  --header 'accept: application/json' \
  --header 'content-type: application/x-www-form-urlencoded'
  -d "pk=5&name=flag&value=1425"

Im Erfolgsfall wird folgendes zurückgegeben

{
    "dataset": {
        "id": 5,
        "name": "Alter Name",
        "flag": 1425,
    },
    "sys": {
        "updated": "2017-10-22T12:43:37",
        "message": "200 OK",
        "code": 200
    }
}

Im Fehlerfall - fehlerhafte Validierung - wird folgendes zurückgegeben.

{
    "sys": {
        "validation": {
            "report": {
                "name": {
                    "message": "wrong value",
                    "state": "error",
                    "valid": false
                }
            }
        },
        "error": {
            "code": 400,
            "message": "400 Bad Request"
        }
    }
}

Konfiguration der Route

<route id="ROUTE-ID-PATCH">
    <method>PATCH</method>
    <pattern><![CDATA[^\/api\/object$]]></pattern>
    <template><![CDATA[/api/object]]></template>
    <configuration>
        <model>  <!-- Klassenname des Models -->
            <class>MyModel</class>    
        </model>
    </configuration>
</route>