Die Callback Funktionen im Model ermöglichen es Daten vor und nach dem Abfragen oder Abspeichern zu verändern (CakePHP Book: 3.7.7 Callback Methods). Das kann zum Beispiel nützlich sein um Ausgaben für einen Benutzer je nach Rolle anzupassen. Die Daten werden erst gar nicht abgefragt indem das Query vorher entsprechend verändert wird. Somit wird auf unterster Ebene sichergestellt, dass jeder nur die Daten sieht die er sehen darf.
Callbacks funktionieren allerdings nicht, wenn die Daten über eine has and belongs to many Relation abgerufen werden.
Beispiel:
Folgende Datenbank sei gegeben
+--------+ +-------------------+ +-------------+
| people | <--> | department_people | <--> | departments |
+--------+ +-------------------+ +-------------+
department_people verbindet people und department über eine HABTM Relation.
Model person.php:
class Person extends AppModel {
var $name = 'Person';
// beforeFind Callback
function beforeFind($queryData) {
echo 'beforeFind';
$queryData = ... // queryData anpassen;
return $queryData;
}
// find überschreiben
function find($conditions = null, $fields = array(), $order = null, $recursive = null) {
echo 'find';
return parent::find($conditions, $fields, $order, $recursive);
}
}
Controller departments_people_controller.php:
class DepartmentsPeopleController extends AppController {
var $name = 'DepartmentsPeople';
function index() {
$res = $this->DepartmentsPeople->find('all');
// Gibt beforeFind und find aus.
$this->set(compact('res'));
}
}
Controller departments_controller.php:
class DepartmentsController extends AppController {
var $name = 'Departments';
function index() {
$res = $this->Departments->find('all');
// Keine Ausgabe
$this->set(compact('res'));
}
}
Das Problem ist also, dass weder das Callback beforeFind noch die überschriebene Methode find aufgerufen werden, wenn eine HABTM Verknüpfung vorliegt. Die Folge ist, dass die Änderungen an queryData folgenlos bleiben. Es gibt allerdings eine Möglichkeit auf die Abfrage Einfluss zu nehmen: der conditions Parameter im Model department.
Model department.php:
class Department extends AppModel {
var $name = 'Department';
var $hasAndBelongsToMany = array(
'Person' => array(
'className' => 'Person',
'joinTable' => 'departments_people',
'conditions' => array( ... ) // beliebige SQL Befehle als Bedingung für die Abfrage; auch Substatements
)
);
}
Allerdings muss diese Bedingung in jedes Model das mit Person über eine HABTM Relation verknüpft ist eingefügt werden.
Warum CakePHP allerdings das Model bei der Abfrage der Verknüpften Modelle nicht berücksichtigt ist mir ein Rätsel. Möglicherweise aus Performanz Gründen.