2017-02-21 5 views
2

私はDBIを介して抽象化を提供するモジュールを扱い、自動的に再接続します。 `DBI-> connectの後にいくつかのアクションを実行する必要があります。DBI再接続後のフック方法

このモジュールを変更せずにそこにフックを追加する方法はありますか?私はドキュメントでそれを見つける運がない。私は何か見落としてますか?

+1

ドキュメントの[コールバックセクション](https://metacpan.org/pod/DBI#Callbacks)を読んだとしますか? * connect *を除く任意のメソッドにコールバックを追加できるようです!私が考えることができるのは、本当の 'connect'を呼び出し、それが返す' $ dbh'を渡すための 'DBI :: connect'パッチを猿に与えることです。 – Borodin

答えて

3

DBI docはa chapter about subclassingです。これは何もしない$dbh->connectedメソッドを示しています。それはまさにあなたが望むものと思われます。

$dbh->connected($dsn, $user, $pass, \%attr); 

私はそれを試していないが、それはただの猿でうまくいくかもしれない:サブクラス化が成功した新しい接続した後、DBI->メソッドを接続して、自動的に呼び出して、その後、使用されている

- 何かをサブクラス化せずに、この接続されたメソッドを直接DBIにパッチする。 In connectthere is definitely a call to connected

しかし、どこにパッチを当てるべきかはわかりません。 grep of the cpanは、DBI distに含まれるドライバが2つしかないことを示しています。 DBD::GoferDBD::Proxyですが、それは空です。両方とも、DBD::<drivername>::dbパッケージに入っています。

あなたがMySQLをやっているとしましょう。それからあなたのドライバに接続してください。彼らは自分のconnectedを持っていない限り、サブクラス化によって、そのドライバを使用して、または単に猿パッチングその中で。

*DBD::mysql::db::connected = sub { 
    my ($dbh, dsn, $user, $pass, $attr, $old_driver) = @_; 

    warn 'Connected!'; 
} 

これは、他のドライバーと同じように動作するはずのどちらか。その場合は、おそらく手動でラップするか、Class::Method::Modifiersaroundのようなものを使用して元の動作が元のままであることを確認してください。

また、現時点では$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!'; 
    } 
} 

私はこれをテストしていませんのでご注意ください。

+1

私はあなたが正しいと思っていますが、OPは*「DBIを抽象化するモジュールを扱います」*彼らは変更したくないので、サブクラスの使用は可能ではないようです。私は、既存のサブクラスをサブクラス化することは、抽象化がどのように行われているかが問題ではないかと思います。 – Borodin

+0

ありがとうございます。私が今まで気づいていなかった「DBI」のコーナーについて教えてくれました。 – Borodin

+0

@Borodin私はそれも知らなかった。私は幸運にもドキュメントをスキミングしてしまった。 ;) – simbabque

関連する問題