Créer un panel pour la Web Debug Toolbar utilisant l'Event Dispatcher

1 gravatar Par Grégoire Marchal - 09/02/2011

Allez, un petit tutoriel aujourd'hui. On va créer un panel pour la WDT (Web Debug Toolbar) qui va afficher la liste des requêtes WebService SOAP (mais vous pouvez l'adapter à ce que vous voulez) exécutées sur la page, à la manière des panels Doctrine/Propel (dont je me suis inspirés) qui affichent les requêtes SQL. Son contenu sera alimenté par des événements gérés par l'Event Dispatcher.

Pour la création du squelette du panel sfWebDebugPanelSoapClient, je vous laisse suivre le tutoriel officiel, qui est très bien fait. Une fois que c'est fait, on va remplir ce panel en utilisant l'Event Dispatcher. Pour cela, on va commencer par générer les événements ; ça se passe donc dans mon cas dans la class MySoapClient, la classe qui gère les choses que je veux logger.

Je commence par y créer la méthode qui crée et dispatche l'événement :

  /**
   * Dispatch a 'soapclient.log' event (used by web debug panel)
   *
   * @param SoapCommand $oCommand  The executed command
   * @param int         $iDuration The duration of the soap call
   */
  protected function dispatchEvent($oCommand, $iDuration)
  {
    $this->context->getEventDispatcher()->notify(new sfEvent($this, 'soapclient.log', array(
      'command'  => $oCommand,
      'duration' => $iDuration,
    )));
  }

Comme vous le voyez, je crée un événement de type "soapclient.log" portant sur l'objet courant ($this), et je fournis au passage des paramètres informatifs que j'afficherai dans mon panel un peu plus tard... Puis j'utilise l'Event Dispatcher pour notifier les objets qui écoutent les événements "soapclient.log" qu'il y en a un nouveau !

Il faut ensuite appeler cette méthode au moment opportun, dans mon cas, immédiatement après l'appel au WebService.

    $iTime = microtime(true);
    // do your stuff...
    $this->dispatchEvent($oCommand, microtime(true) - $iTime);

Retournons maintenant dans la classe panel sfWebDebugPanelSoapClient, afin justement de lui dire d'écouter ce type d'événements. Pour cela, on va surcharger son constructeur afin de connecter une méthode à cet événement.

  protected $aEvents = array();

  public function __construct(sfWebDebug $webDebug)
  {
    parent::__construct($webDebug);
    $this->webDebug->getEventDispatcher()->connect('soapclient.log', array($this, 'listenForSoapClientLogs'));
  }

  /**
   * Listens to soapclient.log event and record them
   *
   * @param sfEvent $event
   */
  public function listenForSoapClientLogs(sfEvent $event)
  {
    $this->aEvents[] = $event;
  }

Dans le constructeur, on demande à l'Event Dispatcher d'appeler la méthode "listenForSoapClientLogs" de notre classe dès qu'il reçoit un événement de type "soapclient.log". Dans cette méthode, on stocke juste chaque événement reçu dans un tableau, propriété de notre classe.

On a désormais toutes les billes. Il n'y a plus qu'à afficher le tout dans notre panel.

  /**
   * Get the html content of the panel
   *
   * @return string $html
   */
  public function getPanelContent()
  {
    return '
    <div id="sfWebDebugSoapClientLogs">
      <ol>'.implode("\n", $this->getSoapClientLogs()).'</ol>
    </div>
    ';
  }

  /**
   * Retrieves events as html
   *
   * @return string
   */
  protected function getSoapClientLogs()
  {
    $aRet = array();
    $i = 1;
    foreach ($this->aEvents as $oEvent)
    {
      $aParams = $oEvent->getParameters();

      $oClient = $oEvent->getSubject();
      $oCommand = $aParams['command'];

      $sHtml = '
        <li>
          ' . get_class($oCommand) . ' (' . round(($aParams['duration'] * 1000), 2) . ' ms)
          ...
        </li>
      ';

      $aRet[] = $sHtml;
      $i++;
    }
    return $aRet;
  }

Et voilà ! Le tour est joué ! On a un joli panel pour débugger dans mon cas un client SOAP, mais je suis sûr que vous en ferez plein de trucs utiles !

Soap Debug Panel

Retour à l'accueil

Commentaires (1)

gravatar Par bourvill, le 09/05/2011 à 22:20
Excellent!!!!
Sympa sur l’event listener

Commenter