Contao Models

von Marco Simbürger

Contao Models

Ein Model repräsentiert einen Datensatz aus einer Tabelle. Models bieten einen Objekt-orientierten Zugriff auf Tabellen und ersetzen damit SQL-Abfragen weitgehend.

Einige fundamentale Methoden werden durch die Contao Model-Klasse implementiert. Jedes spezifische Model erbt von dieser Superklasse und kann selbst weitere Methoden definieren.

Nachfolgend ein paar Beispiel für die Verwendung von statischen Methoden der Contao Model-Klasse. Als Beispiel-Model wird das PageModel verwendet. Als Datensatz die Test-Seite "test-model.html" mit der internen ID 5.

//PageModel für den Datensatz mit der ID 5
$objPage = \PageModel::findByPk(5); 

//PageModel für den Datensatz mit der ID 5 ODER dem Alias 'test-model'
$objPage = \PageModel::findByIdOrAlias(5); 
$objPage = \PageModel::findByIdOrAlias('test-model');

//Alternative zu findByIdOrAlias()
$objPage = \PageModel::findOneBy('alias', 'test-model'); //Best practice!

//Mit findOneBy() kann auch nach anderen Feldern gesucht werden (Achtung bei identischen Werten, wie hier z.B. Titel)
$objPage = \PageModel::findOneBy('title', 'Test Model');

Mit der Methode row() erhält man alle Werte des Datensatzes als assoziatives Array zurück.

$objPage = \PageModel::findOneBy('alias', 'test-model');
$arrPage = $objPage->row();
print_r($arrPage);

Ausgabe:

Array
(
    [id] => 5
    [pid] => 1
    [sorting] => 384
    [tstamp] => 1453200781
    [title] => Test Model
    [alias] => test-model
    [type] => regular
    ...

PageModel selbst erbt von der Klasse Model und bietet zusätzliche Methoden an. Zum Beispiel:

//PageModel mit dem Datensatz mit der ID 5, aber nur wenn dieser veröffentlich ist
$objPage = \PageModel::findPublishedById(5); 

//PageModel der 404-Seite gemäss der Parent-ID
$objPage = \PageModel::find404ByPid(1);

So bietet jedes Model (PageModel, FileModel, ArticleModel usw.) eigene, spezifische Methoden an. Eine Übersicht mit weiteren Beispielen findest du hier: Beispiele Contao Models

 

Model-Collection

Anstatt nur einem Datensatz, können auch alle verfügbaren Datensätze abgefragt werden. Also in diesem Beispiele alle Datensätze von tl_page.

Dies geschieht mit Hilfe einer Collection. Eine Collection Instanz wird mit Model::findAll() bzw. Model::findBy() instanziiert.
ACHTUNG: Es gibt keine leere Collection! Werden keine Datensätze gefunden, ist der Rückgabewert von findAll() bzw. findBy() gleich null! Es ist dann kein Collection Objekt!

Ein Beispiel, um alle Datensätze von tl_page als jeweilges PageModel zu holen:

$objPages = \PageModel::findAll(); //Return \Contao\Model\Collection Object

Erhaltenes Collection Objekt:

Contao\Model\Collection Object
(
    [strTable:protected] => tl_page
    [intIndex:protected] => -1
    [arrModels:protected] => Array
    (
        [0] => Contao\PageModel Object
           (
           	...
           )
        [1] => Contao\PageModel Object
           (
           	...
           )
    )
)

Es können z.B. auch alle Datensätze gesucht werden, die z.B. published=1 besitzen. Hier kommt jetzt findBy() zum Einsatz.

$objPages = \PageModel::findBy('published', 1);

Es können auch mehrere Bedingungen angegeben werden. Beim Array sollte darauf geachtet werden, dass auch die Tabelle angegeben wird, da bei referenzierten Datensätzen sonst ggf. Fehler wegen duplikaten Spaltennamen auftreten können.

//Hole alle Seiten, die type='regular' UND published=1 sind
$objPages = \PageModel::findBy(
	array('tl_page.type=?', 'tl_page.published=?'),
	array('regular', 1)
);

//Alternative Schreibweise mit findAll()
$objPages = \PageModel::findAll(
	array(
		'column' => 'published',
		'value' => 1
	)
);

Mit der Methode findBy() können noch weitere nützliche Abfragen erstellt werden. Die Methode kann drei Parameter entgegennehmen:
1. Spaltenname(n) (mixed)
2. Wert(e) (mixed)
3. Optionale Optionen für die Abfrage (array)

Dadruch können z.B. solche Abfragen geschrieben werden:

//Collection Instanz von den Contao-Seiten (tl_page), die type='regular' und published=1 besitzen. Gib max. 2 Models zurück und sortiere sie nach 'alias' absteigend
$objPages = \PageModel::findBy(
  array('tl_page.type=?', 'tl_page.published=?'),
  array('regular', 1),
  array('limit' => 2, 'order' => 'tl_page.alias DESC')
);

//Spaltenname und Wert müssen nicht als Array angegeben werden, wenn es sich nur um eine Spalte handelt. (die Optionen jedoch schon, da ein array erwartet wird)
$objPages = \PageModel::findBy('published', 1, array('limit' => 5, 'order' => 'alias') );

Zugriff / Daten ausgeben

Natürlich können die Werte aus einer Collection Instanz auch ausgegeben/aufgelistet werden. Dank des IteratorAggregate interface kann eine normale foreach-Schlaufe angewendet werden.

$objPages = \PageModel::findBy('published', 1);
foreach($objPages as $objPage) {
    echo $objPage->title.'<br>';
}

Datensätze zählen

Wenn man also mehrere Datensätze holen kann, wäre es natürlich manchmal auch praktisch zu wissen, wie viele Datensätze überhaupt vorhanden sind. Auch dafür gibt es zwei nützliche Methoden:
countBy()  Gibt die Anzahl zutreffender Datensätze zurück
countAll()  Gibt die Anzahl aller Datensätze der Tabelle zurück
Zudem kann auf eine Collection Instanz selbst die Funktion count() angewendet werden, um die Anzahl der enthaltenen Models zu erfahren.

//Anzahl Datensätze, welche reguläre Seiten sind (type='regular' in tl_page)
$objPage = \PageModel::countBy('type', 'regular'); //5

//Anzahl aller Datensätze in tl_page
$objPage = \PageModel::countAll(); //8

//Alle veröffentlichten Datensätze aus tl_page holen und dann mit der Funktion count() zählen
$objPage = \PageModel::findBy('published', '1');
echo $objPage->count(); //Ausgabe: 7

Datensätze via Models bearbeiten und speichern

Es ist auch möglich, Datensätze via Models zu bearbeiten. Dazu wird der Datensatz zuerst als Model geholt, anschliessend werden die gewünschten Anpassungen getätigt und dann mit der Funktion save() gespeichert. Hier ein Beispiel, wie der Titel der Seite geändert wird:

$objPage = \PageModel::findByPk(5);
echo $objPage->title; //Ausgabe: Test Model
$objPage->title = 'Meine Test Model Seite';
$objPage->save();
echo $objPage->title; //Ausgabe: Meine Test Model Seite

Die Methode save() speichert alle Änderungen in die Datenbank. Man könnte also auch mehrere Änderungen vor dem save()-Aufruf vornehmen.
MERKE: Es werden nur Attribute gespeichert, für die eine Spalte in der Datenbank-Tabelle vorhanden ist! Es gibt in der Datenbank eine Spalte "title", deshlab kann der Wert dieses Attribut auch gelesen, geändert und gespeichert werden.

Model-Registry

Contao besitzt seit Version 3.2 eine Model-Registry. Das bedeutet, dass immer dieselbe Instanz eines Models zurückgegeben wird, sofern der Primärschlüssel übereinstimmt. Beispiel:

$objPage = \PageModel::findByPk(5);
$objPage2 = \PageModel::findByPk(5);

print_r($objPage === $objPage2); //Ausgabe: 1 bzw. true

Zurück

Kommentare

Kommentar von Andreas |

Eine weitere Möglichkeit Bilder per UUID abzurufen:
&#123;&#123;picture::<?php echo \StringUtil::binToUuid($this->origin['ctlg_ensembleImage']); ?>&#125;&#125;

Einen Kommentar schreiben

Was ist die Summe aus 6 und 9?