[inhalt]
Projekt BISO 3 - Handbuch

Backend-Controller und deren Aufbau

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.

Standard-Routing

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:

Ein Beispiel-Controller:

class BfTerminController extends KPController {
    // Route: backend/bf_termin/list
    public function listAction() {
        return ['foo' => 'bar'];
    }
}

Helper-Klassen und -Methoden

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:

Basis-Controller-Klasse KPController

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.

Helper-Trait: EntityRequestTrait

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: BaseWertelistController

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)");
        }
    }
}