BISO setzt das Backend-Framework Gaia für das backend-seitige Request-Handling ein. Ein zentraler Aspekt des Frameworks sind die Controller-Klassen, welche die URL-Routen abhandeln.
In GAIA und somit auch in BISO werden URL-Routen standardmässig (ohne zusätzliche Konfiguration) nach folgendem Schema abgearbeitet:
http[s]://[biso-host/pfad/zum/webroot]/backend/[controller]/[action]
Dabei entspricht:
[controller] dem Namen der zugehörigen Entität (bsp: backend/bf_termin/list handelt Requests zur Entität BfTermin im Controller BfTerminController ab) in "snail case"[action] dem Namen der zugehörigen Action-Methode (bsp: backend/bf_termin/list) in "snail case" im Controller, hier also BfTerminController::listAction().Ein Beispiel-Controller:
class BfTerminController extends KPController {
// Route: backend/bf_termin/list
public function listAction() {
return ['foo' => 'bar'];
}
}
Da viele Controller mehr oder weniger dieselbe Funktionalität benötigen / abhandeln, haben wir sehr viele Helper-Klassen und -Methoden erstellt, welche genutzt werden sollen:
Alle Controller sollen von KPController erben:
class BfTerminController extends KPController {
// ...
}
Der KPController sorgt dafür, dass bei allen Requests die Authentifikation sichergestellt ist, und liefert wichtige Basisfunktionen.
Das Trait EntityRequestTrait stellt Standard-Funktionen zur Verfügung, welche in Controllern immer wieder genutzt werden. Es stellt Funktionen zum Parsen und Setzen von Filtern, Limit/Offset und Filter-Parametern sowie für die Response zur Verfügung.
Ebenso werden Standard-Implementationen für Store- und Destroy-Actions zur Verfügung gestellt.
Beispiel-Anwendung:
class InformationController extends KPController {
// Trait in Klasse einbinden:
use EntityRequestTrait;
/**
* In der List-Action wird nur noch die `entityList`-Methode aufgerufen:
* dies ist eine Algorithm-Funktion, welche diverse Helper-Methoden
* aufruft:
*/
protected function listAction(EntityService $es) {
$eb = $es->createEntityBuilder(Information::class);
/**
* entityList ruft auf:
* - processJsonFilter: sucht nach einem ExtJS-Filter-JSON in $this->param['filter']
* und wendet ihn auf dem EntityBuilder an
* - processQueryFilter(): wird nach processJsonFilter aufgerufen und kann in
* Kindklassen implementiert werden (leere Template-Methode)
* - afterFilterProcessing(): wird nach processQueryFilter aufgerufen und kann in
* Kindklassen implementiert werden (leere Template-Methode)
* - processOffsetLimit(): prozessiert 'limit' und 'start'-Parameter und wendet
* sie auf dem EntityBuilder an
* - processSort(): prozessiert 'sort' (ein ExtJS sort-object-array) und wendet
* sie auf dem EntityBuilder an. Wenn 'sort' nicht geliefert wird,
* wird `processDefaultSort()` (leere Template-Methode) aufgerufen.
*/
return $this->entityList($eb, $this->params);
}
/**
* Beispiel-Implementation
*/
protected function processDefaultSort(EntityBuilder $eb, $params) {
$eb->addOrderBy('modification_date', 'DESC');
}
/**
* Beispiel-Implementation
*/
protected function afterFilterProcessing(EntityBuilder $eb, $params) {
if (isset($params['show_current_information'])) {
$eb->andWhere('anzeigen_von IS NULL AND anzeigen_bis IS NULL');
}
}
/**
* Beispiel-Implementation
*/
protected function processQueryFilter(EntityBuilder $eb, $params) {
if ($this->checkParam('quicksearch', false)) {
$pieces = array_filter(preg_split('/\s+/', $this->getParam('quicksearch')));
if (count($pieces)) {
foreach ($pieces as $idx => $piece) {
$queryVar = "query{$idx}";
$eb->andWhere("
lower(name) LIKE lower(:{$queryVar}) OR
lower(person_name) LIKE lower(:{$queryVar}) OR
lower(person_vorname) LIKE lower(:{$queryVar})
", ["{$queryVar}" => '%' . $piece . '%']);
}
}
}
}
}
Verwenden der Standard-Store- und Destroy-Implementationen:
class BfLogController extends KPController{
use EntityRequestTrait;
/**
* store action
*/
public function storeAction(EntityService $es) {
return $this->defaultEntityStore($es, BfLog::class);
}
protected function beforeStore(BfLog $log) {
// beforeStore kann mittels false das Speichern einer Entity verhindern:
if (.....) {
return false;
}
}
protected function afterStore(BfLog $log) {
// hier wird die gespeicherte Entity übergeben.
// ... do some....
}
/**
* destroy action
*/
public function destroyAction(EntityService $es){
return $this->defaultEntityDestroy($es, BfLog::class);
}
protected function beforeDestroy(BfLog $log) {
// beforeDestroy kann mittels false das Löschen einer Entity verhindern:
if (.....) {
return false;
}
}
}
Für einfache Wertelisten, welche alle dieselbe Logik verwenden, kann der BaseWertelistController verwendet werden. Die Klasse implementiert Standard-Aktionen für List, Store und Destroy:
use Gaia\ORM\EntityBuilder;
class AusbildungController extends BaseWertelistController {
protected $stdSort = 'reihenfolge,bbt_code';
protected function buildQuickSearchFilter(EntityBuilder $eb, $query) {
$eb->andWhere("
bbt_code::text ILIKE :query OR
lbz_code::text ILIKE :query OR
ch19_code::text ILIKE :query OR
ausbildung_kurz::text ILIKE :query OR
ausbildung_lang::text ILIKE :query OR
ausbildung_kurz_fr::text ILIKE :query OR
ausbildung_lang_fr::text ILIKE :query",
[':query' => $query]
);
}
protected function buildOwnFilter(EntityBuilder $eb) {
if ($this->checkParam('onlyActive', false)) {
$eb->andWhere("(aktiv_ab <= CURRENT_DATE OR aktiv_ab IS NULL)");
$eb->andWhere("(aktiv_bis >= CURRENT_DATE OR aktiv_bis IS NULL)");
}
}
}