10
votes

Journalisation de toutes les demandes et réponses de savon en PHP

Est-ce que quelqu'un sait comment enregistrer toutes les demandes et les réponses avec le savacclient intégré dans PHP? Je pourrais en fait manuellement connecter manuellement tout avec SOAPCLIENT :: __ getlastrequest () et SOAPCLIENT :: __ getLasResponse () Mais nous avons ce beaucoup de demandes de savon dans notre système que je cherche Autres possibilités.

Remarque: J'utilise le mode WSDL, donc en utilisant une méthode que tunnels all au tout à SOAPCLIENT :: __ SOAPCALL () n'est pas une option


0 commentaires

7 Réponses :


1
votes

Est-ce que quelque chose comme ça fonctionne?

class MySoapClient extends SoapClient
{
    function __soapCall($function_name, $arguments, $options = null, $input_headers = null, &$output_headers = null) 
    {
        $out = parent::__soapCall($function_name, $arguments, $options, $input_headers, $output_headers);

        // log request here...
        // log response here...

        return $out;
    }
}


1 commentaires

Cela ne fonctionne pas ... Avez-vous un aperçu de la raison pour laquelle __soapCall ne peut plus être remplacé?



7
votes

Je pense que la meilleure façon est de remplacer SOAPCLIENT :: __ dorequest () code> (et pas SOAPCLIENT :: __ SOAPCALL () CODE>) Comme vous aurez un accès direct à la Demande - ainsi que sur la réponse-XML. Mais l'approche générale de la sous-classe SOAPCLIENT code> devrait être la voie à suivre.

class My_LoggingSoapClient extends SoapClient
{
    // logging methods

    function __doRequest($request, $location, $action, $version, $one_way = 0) 
    {
        $this->_logRequest($location, $action, $version, $request);
        $response = parent::__doRequest($request, $location, $action, $version, $one_way);
        $this->_logResponse($location, $action, $version, $response);
        return $response;
    }
}


3 commentaires

Je suppose que c'est une solution préférable au-dessus de la décorateur. En tant que SOAPCLIENT pas vraiment OOP-AISH, et il n'applique aucune interface, il n'est vraiment aucun moyen de rendre le décorateur compatible avec celui-ci du point de vue linguistique, si la dépendance du client de savon était de type Apparuré avec \ soapclient . Si vous écrivez une bibliothèque qui utilise ce client vous-même, bien sûr, mieux pour l'envelopper et implémenter une interface. Mais si vous souhaitez remplacer l'objet dans une bibliothèque déjà existante, qui s'attend à un objet de type SOAPCLIENT , les décorateurs ne le feront pas (mais encore une fois, s'il n'y a pas de conseils de type, vous pouvez y aller) .


@sevavietl c'est vrai. Mise en œuvre d'un décorateur compatible avec un indice de type SOAPCCLIENT Peut être problématique (en raison de l'interface manquante et de la nature dynamique du SOAPCLIENT API). Jamais essayé que moi-même, je ne peux pas juger s'il est possible en général ou non.


C'était la seule façon de travailler pour moi, en utilisant les méthodes dynamiques de WSDL.



18
votes

I Deuxième suggestion Aleksanders et Stefans mais ne sousclureait pas SavapClient. Au lieu de cela, je serrais le savacclient régulier dans un décorateur, car la journalisation n'est pas une préoccupation directe du savacclient. De plus, le couplage lâche vous permet de remplacer facilement le savacclient avec une mocke dans vos instances. Vous pouvez donc vous concentrer sur le test de la fonctionnalité de journalisation. Si vous souhaitez uniquement enregistrer des appels spécifiques, vous pouvez ajouter une certaine logique qui filtre les demandes et les réponses de dollars par $ ou tout ce que vous voyez en forme.

EDIT STRUT> Comme Stefan a suggéré d'ajouter du code, le décorateur serait Probablement regarder quelque chose comme ça, bien que je ne suis pas sûr de la méthode __Call () (voir Stefans Commentaires) P>

class SoapClientLogger
{
    protected $soapClient;

    // wrapping the SoapClient instance with the decorator
    public function __construct(SoapClient $client)
    {
        $this->soapClient = $client;
    }

    // Overloading __doRequest with your logging code
    function __doRequest($request, $location, $action, $version, $one_way = 0) 
    {
         $this->log($request, $location, $action, $version);

         $response = $this->soapClient->__doRequest($request, $location, 
                                                    $action, $version, 
                                                    $one_way);

         $this->log($response, $location, $action, $version);
         return $response;
    }

    public function log($request, $location, $action, $version)
    {
        // here you could add filterings to log only items, e.g.
        if($action === 'foo') {
            // code to log item
        }
    }

    // route all other method calls directly to soapClient
    public function __call($method, $args)
    {
        // you could also add method_exists check here
        return call_user_func_array(array($this->soapClient, $method), $args);
    }
}


6 commentaires

L'utilisation d'un décorateur est une très bonne idée. En fait, j'irais avec une solution de décorateur moi-même si je devais travailler sur le même problème. Mais je pense, la solution de sous-classement est un peu plus compréhensible.


Et puis il y a un problème de PHP qui désactive le empilement de décorateurs si vous utilisez la méthode-Overloading-Feature __ appel () dans l'un de vos décorateurs ou dans la classe être décoré ( savacclient dans ce cas).


Je ne savais pas qu'il y avait un problème avec __Call (). Avez-vous un lien où je peux lire à ce sujet? Ce serait bien de savoir. Oh, et j'ai ajouté le code ci-dessus.


Ce que je voulais dire, c'est que vous ne pouvez pas déterminer si une méthode est appelable lors de l'utilisation de __ appel () , appelera donc une méthode non existante augmentera toujours une erreur fatale. En cas de décoration du SOAPCLIENT , vous pouvez vérifier is_callable (tableau ($ ceci-> SOAPCLIENT, méthode $)) et in_array ($ méthode, $ this-> SOAPCLIENT-> __GETHONCTIONS ()) . Mais cela ne permettra pas de pile des décorateurs.


Oubliez ma remarque sur le problème (et l'empilement des décorateurs) ... il est possible de faire les chèques que j'ai montrés ci-dessus et pourrons toujours empiler vos décorateurs. Désolé pour tout le chaos g


J'ai essayé cette solution, mais la méthode du journal n'est pas appelée, l'appel est transféré droit à Soapclient



7
votes

Désolé de revoir un tel ancien poste, mais j'ai rencontré des défis avec la mise en œuvre de la réponse acceptée d'un décorateur qui est responsable de la journalisation des demandes de savon et que je voulais partager au cas où quelqu'un d'autre se déroule.

Imaginez Vous configurez votre instance comme ci-après, à l'aide de la classe SOAPClientlogger décrite dans la réponse acceptée. P>

$mySoapClient->AddMember($parameters); // AddMember is defined in the WSDL


0 commentaires

3
votes

Adressant le problème soulevé dans https://stackoverflow.com/a/3939077/861788 Je suis venu avec ce qui suit Solution ( Source complète ):

use Lc5\Toolbox\LoggingSoapClient\LoggingSoapClient;
use Lc5\Toolbox\LoggingSoapClient\TraceableSoapClient;
use Lc5\Toolbox\LoggingSoapClient\MessageXmlFormatter;
use Monolog\Handler\StreamHandler;
use Monolog\Logger;

$handler = new StreamHandler('path/to/your.log');
$handler->setFormatter(new MessageXmlFormatter());

$logger = new Logger('soap');
$logger->pushHandler($handler);

$soapClient = new LoggingSoapClient(new TraceableSoapClient('http://example.com'), $logger);


0 commentaires

-2
votes

J'ai vérifié les demandes et les réponses avec Wireshark.


0 commentaires

0
votes

Je sais que c'est une question très ancienne, mais je vois des morceaux et des morceaux et il est difficile de le faire tout ensemble.

en expansinant sur Stefan Gehrig Réponse , j'ai fini par avoir à étendre SoapClient afin de pouvoir utiliser les méthodes dynamiques de la WSDL. Aussi, hors de commodité, cette classe ajoute l'option de traçage directement dans la construction. xxx

espère que cela aide à fournir une clarté sur les solutions possibles.


0 commentaires