首页 > 解决方案 > Zend SOAP 服务器日志功能

问题描述

我编写了一个 Zend SOAP 服务器来处理请求并将响应返回给查询我们库存的供应商。

现在我想在服务器中添加日志功能,以便在出现问题时进行调试。

我发现这个很酷的小类覆盖了 PHP SoapServer: https ://blog.mayflower.de/179-Extending-class-SoapServer-PHP5-for-debugging.html

我想为 Zend Soap 服务器做同样的事情。唯一的修改是这条线吗?
class overloadedZendSoapServer extends Zend\Soap\Server

我也认为需要添加这个才能访问 Timer 类:
require_once __DIR__ . '/vendor/autoload.php';

最好在函数中将每条消息记录到我的 Postgres DB 中,setDebugValue()还是最好在发送响应之前soapDebug[]在函数末尾记录整个数组?handle()

任何意见?

标签: phpsoapzend-framework

解决方案


以下是我如何修改文章中的代码以创建记录信息的服务:

<?php
    require_once __DIR__ . '/vendor/autoload.php';

    use Zend\Soap\AutoDiscover;
    use Zend\Soap\Server;
    use Zend\Soap\Wsdl;
    use Weew\Timer\Timer;

    class Util {

        /*
        * Beautify an XML string.
        *
        * @param    string    Compressed/Unformatted XML string
        * @return   string    Formatted XML string
        */
        static function beautifyXmlString ( $xml ) {
            // add marker linefeeds to aid the pretty-tokeniser
            // (adds a linefeed between all tag-end boundaries)
            $xml = preg_replace ( '/(>)(<)(\/*)/', "$1\n$2$3", $xml );

            // now indent the tags
            $token = strtok ( $xml, "\n" );

            // holds formatted version as it is built
            $result = '';

            // initial indent
            $pad = 0;

            // returns from preg_matches()
            $matches = array();

            // scan each line and adjust indent based on opening/closing tags
            while ( $token !== false )
            {  
                // test for the various tag states

                // 1. open and closing tags on same line - no change
                if ( preg_match ( '/.+<\/\w[^>]*>$/', $token, $matches ) ) :
                    $indent = 0;

                // 2. closing tag - outdent now
                elseif ( preg_match ( '/^<\/\w/', $token, $matches ) ) :
                    $pad--;

                // 3. opening tag - don't pad this one, only subsequent tags
                elseif ( preg_match ( '/^<\w[^>]*[^\/]>.*$/',
                        $token, $matches ) ) :
                    $indent=1;

                // 4. no indentation needed
                else :
                    $indent = 0;

                endif;

                // pad the line with the required number of leading spaces
                $line = str_pad ( $token, strlen ( $token ) +
                        $pad, "\t", STR_PAD_LEFT );

                // add to the cumulative result, with linefeed
                $result .= $line . "\n";

                // get the next token
                $token = strtok ( "\n" );

                // update the pad size for subsequent lines
                $pad += $indent;
            }
            return $result;
        } // static function beautifyXmlString

        /*
        * Build Multiple insert SQL from array
        *
        * @arrs    array    Array of values to build inserts from
        * @return  array    returns sql and params array
        */
        function insert_multiple_query($tablename, $arrs = array()) {
            $raw_cols = '(';
            $raw_vals = '(';
            $ctr1=1;  

            // PREPARE THE COLUMNS 
            foreach(array_keys($arrs) as $key1) {
                $raw_cols .= strtolower($key1).','; 
                $raw_vals .= '$'.$ctr1.',';
                $ctr1++;
            };

            $final_cols = rtrim($raw_cols,',') . ')';
            $final_vals = rtrim($raw_vals,',') . ')';

            $ctr2 = 0; $param = array();

            // PREPARE THE PARAMETERS
            foreach(array_keys($arrs) as $arr_param) {        
                $param[$arr_param.'_'.$ctr2] = $arrs[$arr_param];
                $ctr2++;
            };

            // PREPARE THE CLAUSE 
            $clause = 'INSERT INTO '.$tablename . ' ' . $final_cols . ' VALUES ' . $final_vals;

            // RETURN THE CLAUSE AND THE PARAMETERS 
            $return['clause'] = $clause;
            $return['param']  = $param;
            return $return; 
         } // function insert_multiple_query
    } // class Util

    class overloadedZendSoapServer extends Zend\Soap\Server {

        const DB_SERVER   = "localhost";
        const DB_PORT     = "55432";
        const DB_USER     = "dev";
        const DB_PASSWORD = "5e8edd851d2fdfbd7415232c67367cc3";
        const DB          = "db";

        /**
         * Timer object
         *
         * @var Timer
         */
        private $debugTimer = null;

        private $Util = null;

        /**
         * Array with all debug values
         *
         * @var array
         */
        protected $soapDebug = array();

        /**
         * Constructor
         *
         * @param mixed $wsdl
         * @param array[optional] $options
         */
        public function __construct($wsdl, $options = null) {
            $this->debugTimer = new Timer();
            $this->Util = new Util();
            return parent::__construct($wsdl, $options);
        }

        /**
         * Store a named value in the debug array.
         *
         * @param string $name
         * @param mixed $value
         */
        private function setDebugValue($name, $value) {
            $this->soapDebug[$name] = $value;
        }

        /**
         * Returns a value from the debug values.
         *
         * @param string $name
         * @return mixed
         */
        public function getDebugValue($name) {
            if (array_key_exists($name, $this->soapDebug)) {
                return $this->soapDebug[$name];
            }

            return false;
        }

        /**
         * Returns all debug values as array.
         *
         * @return array
         */
        public function getAllDebugValues() {
            return $this->soapDebug;
        }

        /**
         * Log all debuging values to the DB
         *
         * @param array $query - contains the insert query and the values to insert
         * @return void
         */
        public function LogToDB($query) {

            $return = $this->Util->insert_multiple_query('soap_logs', $query); 

            $db = pg_connect("host=".self::DB_SERVER." port=".self::DB_PORT." user=".self::DB_USER." password=".self::DB_PASSWORD." dbname=".self::DB);

            $result = pg_prepare($db, "soap_log_query", $return['clause']);
            $result = pg_execute($db, "soap_log_query", $return["param"]);
            if ($result === false){
                echo "DB is down";
                exit;
            }else{
                $rows = pg_fetch_all($result);
            }
            echo json_encode($rows);
            pg_free_result($result);        
        }

        /**
         * Collect some debuging values and handle the soap request.
         *
         * @param string $request
         * @return void
         */
        public function handle($request = null) {
            $this->debugTimer->start();

            // store the remote ip-address
            $this->setDebugValue('RemoteAddress', $_SERVER['REMOTE_ADDR']);

            // check variable HTTP_RAW_POST_DATA
            if (!isset($GLOBALS['HTTP_RAW_POST_DATA'])) {
                $GLOBALS['HTTP_RAW_POST_DATA'] = file_get_contents('php://input');
            }

            // check input param
            if (is_null($request)) {
                $request = $GLOBALS['HTTP_RAW_POST_DATA']; 
            }

            // store the request string
            $this->setDebugValue('RequestString', $this->Util->beautifyXmlString($request));

            // store the request headers
            if (function_exists('apache_request_headers')) {
                $this->setDebugValue('RequestHeader', serialize(apache_request_headers()));
            }

            // start output buffering
            ob_end_flush();
            ob_start();

            // finaly call SoapServer::handle() - store result
            $result = parent::handle($request);

            // store the response string
            $this->setDebugValue('ResponseString', $this->Util->beautifyXmlString(ob_get_contents()));
            $this->debugTimer->stop();

            // stop debug timer and store values
            $this->setDebugValue('CallDuration', $this->debugTimer->getDuration());

            // flush buffer
            ob_flush();

            // store the response headers
            if (function_exists('apache_response_headers')) {
                $this->setDebugValue('ResponseHeader', serialize(apache_response_headers()));
            }

            /*
                Send all debug values for this request to log
            */
            $this->LogToDB($this->getAllDebugValues());

            // return stored soap-call result
            return $result;
        }
    }

    class PT {
        /**
         * function ReqInv
         * Function to return the inventory for the passed request.
         * 
         *  @param string $request 
         *  @return string
         */
        function ReqInv($request) {
            try {
                // PTResp takes the request, parses it to get some info
                // and calls the DB to retrieve the inventory, formats 
                // the response and stores it in a variable $pt, 
                // the toString() function returns the formatted 
                // SOAP response.
                $pt = new PTResp($request);
                return $pt->toString();
            } catch(Exception $e) {
                return 'Message: ' .$e->getMessage();
            }
        }   
    }



    if (isset($_GET['wsdl'])) {
        $wsdl = new AutoDiscover();
        $wsdl->setUri('http://localhost/soap/server.php');
        $wsdl->setClass('PT');
        $wsdl->handle();
    } else {
        $server = new overloadedZendSoapServer('http://localhost/soap/server.php?wsdl');
        $server->setClass('PT');
        $server->setEncoding('ISO-8859-1');
        $server->handle();
    }

推荐阅读