DBI doc имеет a chapter about subclassing, который упоминает метод $dbh->connected
, который ничего не делает. Кажется, это именно то, что вы хотите.
Когда подклассы используются тогда, после успешной нового подключения, то DBI-> подключить метод автоматически вызывает:
$dbh->connected($dsn, $user, $pass, \%attr);
Я не пробовал, но он может работать лишь на обезьяну - привязка этого подключенного метода к DBI напрямую без подклассификации. In connect
there is definitely a call to connected
.
Но я не знаю, где его исправить. Возможно, в драйвере. Быстрый grep of the cpan показывает, что сюда относятся только два драйвера, включенные в DBI dist. DBD::Gofer и DBD::Proxy, но этот пуст. В обоих случаях он находится в пакете DBD::<drivername>::db
.
Предположим, вы делаете MySQL, тогда вы пойдете и подключите его к своему драйверу. Либо подклассов и использовать этот драйвер, или просто обезьяна-латание его.
*DBD::mysql::db::connected = sub {
my ($dbh, dsn, $user, $pass, $attr, $old_driver) = @_;
warn 'Connected!';
}
Это должно работать так же с другими водителями, если они не имеют свои собственные connected
. В этом случае вы должны, вероятно, обернуть его вручную или использовать что-то вроде Class::Method::Modifiers's around
, чтобы обернуть его, чтобы убедиться, что исходное поведение остается неповрежденным.
На данный момент у вас также есть подключенный $dbh
, так что вы можете погулять в базе данных по адресу connected
, если хотите.
Конечно, это даст вам обратный вызов после при каждом подключении. Если вы хотите получить только пересоединения, вы можете создать закрытие над лексической переменной, которая учитывает соединения и пропустит первый.
{
my $connection_counter;
*DBD::mysql::db::connected = sub {
my ($dbh, dsn, $user, $pass, $attr, $old_driver) = @_;
return unless $connection_counter++; # skip first connection
warn 'Connected!';
}
}
Обратите внимание, что я не тестировал это.
Я предполагаю, что вы прочитали раздел [обратные вызовы] (https://metacpan.org/pod/DBI#Callbacks) документации? Похоже, вы можете добавить обратный вызов к любому методу * кроме * connect! Все, что я могу придумать, - это запланировать обезьяну 'DBI :: connect', чтобы вызвать реальное' connect', а затем передать '$ dbh', который он возвращает. – Borodin