Ecrire des messages dans la console du navigateur en PHP

Une petite astuce simple pour écrire des informations de debug dans la console du navigateur web depuis un script PHP.

Voilà à titre d'exemple l'objet d'écriture lorsque l'objet de gestion de logs de ma librairie PHP est configuré pour écrire dans la console web du navigateur :

<?php

namespace rnb\log\writer;

use \rnb\log\Logger;

/**
 *  Writer de log dans la console du navigateur web.
 *
 *  @class \rnb\log\ConsoleWriter
 */
class ConsoleWriter implements Writer
{
    const LOG_STRING = 'phpLog = %s; console.%s(phpLog);';
    
    /**
     * Ensemble des logs.
     * @type string
     */
    private $buffer = '';

    /**
     *  Clean A string to render it in the Web Console.
     *  
     *  @param mixed $str A string or an object overriding ``__toString`` method
     *  @return string.
     */
    private function filterString($str)
    {
        $str = (string) $str;
        $str = str_replace("\r\n", "\n", $str);
        $str = str_replace("\n", " \\n", $str);
        $str = str_replace('"', '\\"', $str);
        
        return '"' . $str . '"';
    }
    
    /**
     * @see \rnb\log\Writer::write()
     */
    public function write($message, $levelLabel)
    {
        if (is_object($message) || is_array($message)) {
            if (is_object($message) && method_exists($message, '__toString')) {
                $message = $this->filterString($message);
            } else {
                if ($message instanceof \Exception) {
                    $message = [
                        'message' => $message->getMessage(),
                        'file' => $message->getFile(),
                        'line' => $message->getLine()
                    ];
                }
                $message = json_encode($message);
                if ($message === false) {
                    $message = '"logger - json_encode error: ' 
                            . json_last_error() . '"';
                }
            }
        } else if (is_string($message)) {
            $message = $this->filterString($message);
        } else if (is_numeric($message)) {
            $message = print_r($message, true);
            $message = str_replace(',', '.', $message);
        } else if (empty($message)) {
            $message = 'undefined';
        } else {
            $message = $this->filterString($message);
        }
        switch ($levelLabel) {
            case Logger::$labels[\LOG_EMERG]:
            case Logger::$labels[\LOG_ALERT]:
            case Logger::$labels[\LOG_CRIT]:
                $method = 'error';
                break;
            case Logger::$labels[\LOG_NOTICE]:
                $method = 'log';
                break;
            default:
                $method = $levelLabel;
        }
        $this->buffer .= sprintf(self::LOG_STRING, $message, $method);
    }
    
    /**
     * @see \rnb\log\Writer::flush()
     */
    public function flush()
    {
        if (!empty($this->buffer)) {
            echo '<script>var phplog; ' . $this->buffer . '</script>';
            $this->buffer = '';
        }
    }
}
\rnb\log\writer\ConsoleWriter.

La technique est simple :

  • On transforme d'abord les variables PHP en une représentation compréhensible en javascript ; ainsi, pour les objets ou les tableaux par exemple, cela consiste à obtenir une chaîne de caractères décrivant un objet JSON.
  • On insère ensuite cette représentation dans une chaîne de caractères qui représente un élément HTML script et dans lequel on appelle une méthode de la console web en fonction de la trace souhaitée (error, warn, log).
  • Il ne reste plus qu'à injecter cette chaîne de caractères dans le buffer de sortie.