Для использования функций обратного вызова, в классе должна быть предусмотрена возможность их обработки.
Рассмотрим следующий пример.
class Db{ private $login; private $password; private $callbacks = array(); private $userOptions = null; function __construct($log, $pas) { $this->login = $log; $this->password = $pas; } //Регистрирует функции обратного вызова. function registerCallback ($callbacks) { //Проверка возможности вызова анонимной функции if (!is_callable ($callbacks) ) { throw new Exception ( "Функция обратного вызова - невызываемая ! " ) ; } $this->callbacks[] = $callbacks; //Сохраняем в массив } function settings() { //В цикле предусматриваем вызов переданных функций (обратного вызова) foreach ( $this->callbacks as $callback){ $date = call_user_func ($callback, $this->login); //вызывает функцию $callback с аргументом $login if($date) $this->userOptions = $date; //массив данных сохраняем для дальнейшей обработки } } function connect(){ // if ($this->login ... || $this->password){. . .} //проверка логина и пароля echo "Вход пользователя $this->login : обрабатывается . . . <br>" ; $this->settings(); //вызываем метод обработки функций обратного вызова /* * Соединение с БД с применением настроек пользователя ($this->userOptions) * Результат соединения сохраняем в $result * if (!$result) throw new Exception ("Ошибка соединения") ; */ //Выведем пользовательские настройки для демонстрации echo '<pre>'; var_dump($this->userOptions); echo '</pre>'; echo 'Готово!<br><hr>'; return true; //при успехе соединения } } $settings = function(){ return [ 'charset' => 'utf-8', ]; }; $status = function(){ echo 'Пользователь имеет привилегированный статус.'; }; $db1= new Db('Serj', 123); $db1->registerCallback($settings); $db1->registerCallback($status); $db2 = new Db('Vasia', 456); $settings = function($login){ echo "Уникальный код пользователя $login: " . rand()*789; return [ 'charset' => 'utf-8', 'dbName' => 'localhost' ]; }; $db3 = new Db('Sveta', 789); $db3->registerCallback($settings); $db1->connect(); $db2->connect(); $db3->connect();
Результат выполнения:
Вход пользователя Serj : обрабатывается . . . Пользователь имеет привилегированный статус. array(1) { ["charset"]=> string(5) "utf-8" } Готово! ________________________________________ Вход пользователя Vasia : обрабатывается . . . NULL Готово! ________________________________________ Вход пользователя Sveta : обрабатывается . . . Уникальный код пользователя Sveta: 1253721 array(2) { ["charset"]=> string(5) "utf-8" ["dbName"]=> string(9) "localhost" } Готово!В данном примере, в качестве функции обратного вызова выступает анонимная функция, которую мы передаем в метод регистрирующий такие функции (сохраняет в массив функций). В нашем примере, функции обратного вызова используются для передачи массива с настройками подключения к базе данных. Так же они решают некоторые задачи (тут – вывод некоторой информации о пользователе).
При попытке соединения с БД (вызов метода connect() объекта Db), вызывается метод обрабатывающий функции обратного вызова - settings(). В нем, перебирается массив сохраненных раньше функций, каждую из которых вызывает функция call_user_func(). Вторым параметром которой мы передаем нужные аргументы функции обратного вызова. В данном случае, например, нам может понадобиться логин.
На этом этапе выводятся сообщения из данных функций обратного вызова, а т.к. они возвращают массив настроек – он сохраняется для дальнейшего использования.
Для примера, я сделал вывод массива настроек на экран в методе connect().
То есть наши функции обратного вызова выполняются только тогда, когда мы предусмотрим это кодом, а не при их объявлении. Таким образом, мы можем предусмотреть в их функционале использование переменных(свойств), которые появятся в области видимости функций обратного вызова только при их вызове. Так же при вызове, такая функция может иметь доступ к переменным/свойствам и методам той области видимости, где она была объявлена. Подробнее об этом в заметке про замыкания.