2016-10-18 9 views
0

注:私の質問では、Symfony Consoleコンポーネントをかなり参考にしていますが、この問題はユーザーインターフェイスのコンテキストで考えると、より広いと考えることができます。Symfonyのコマンドラインで出力をデカップリングする

Symfony Console componentを使用してコンソールアプリケーションを作成しています。私はクラステストを最小限に抑えようとしています。単体テストを簡単にし、一般にはより良い方法です。

私のアプリには完了までに時間がかかることがあるので、実行中の進行状況バーと一般的なテキスト出力を使用して何が起こっているかをユーザに知らせたいと思います。 symfonyは、コマンドのexecuteメソッドに渡されるConsole OutputInterfaceのSymfonyのインスタンスを必要とします。ここまでは順調ですね;私は進歩バーと出力テキストを作成することができます私はしてください。しかし、私のアプリの重い吊り上げはすべて、コマンドのexecuteメソッドでは起こらず、代わりに私のアプリケーションのコアクラスの中にあります。これらのクラスは、コンソールアプリケーションで使用されていることを知らないでください。

出力クラスを自分のコアに注入することなく、コンソール(またはユーザーインターフェイス)にフィードバックを提供する方法がわからないため、このようにしておくのは苦労しています。そうすることで、コンソール出力クラスとアプリケーションコアとの間の結合が強くなります。私はイベントディスパッチャー(Symfonyには1つあります)を使用することを考えましたが、それも私のコアがディスパッチャーと結合されることを意味します(おそらくそれは問題ありません)。理想的には、アプリケーションの状態を呼び出されたコマンドのexecuteメソッドに戻して、出力を実行できるようにする必要があります。

誰かが正しい方向に私を向けることができますか?私はこれが実際にはかなり一般的なケースでなければならないと感じていますが、それについてはあまり見つけられません。

お時間をありがとうございます!

答えて

3

私は、イベントディスパッチャのアプローチを以前に成功裏に使用しました。たとえば、処理の開始、進行、および終了時にイベントをトリガーし、それに基づいてイベントリスナーにプログレスバーを更新させることができます。

<?php 

$progress = $this->getHelperSet()->get('progress'); 
$dispatcher = $this->getContainer()->get('event_dispatcher'); 

$dispatcher->addListener('my_start_event', function (GenericEvent $event) use ($progress, $output) { 
    $progress->start($output, $event->getArgument('total')); 
}); 

$dispatcher->addListener('my_progress_event', function() use ($progress) { 
    $progress->advance(); 
}); 

$dispatcher->addListener('my_finish_event', function() use ($progress) { 
    $progress->finish(); 
}); 

あなたが本当にあなたのサービスでイベントディスパッチャのカップリングを避けたい場合は、拡張または飾るあなたのクラスを(おそらく共有インタフェースを実装)、およびのみがイベントディスパッチャを使用することができます。ただし、進捗状況を通知できるようにするには、基本クラスに拡張ポイント(公開または保護されたメソッド)が必要です。

+0

これは最も簡単な解決策のようです。少なくとも、私のアプリケーションのコアはユーザーインターフェイスについての知識がなく、進捗イベントを発生させることにさらに関わってくるだろうと思う。ああ、はい、あなたは私のサービス(EventAwareServiceなど)を拡張し、元のサービスで保護されたメソッドを持つことについてあなたが意味するものを参照してください。 –

関連する問題