/** * 参数参考{@link set_error_handler}.<br /> * 要完成日志的正确记录,必须正确设置好linux的syslog.conf. (消息程序类型必须设置为local5.debug).<br /> * 例如:<br /> * 日志类型配置(如:/etc/syslog.conf)中添加设置:local5.debug /var/log/php.log <br /> * 如果使用统一的日志服务器来记录则为, local5.debug @192.168.0.119 <br /> * 其中 192.168.0.119为日志文件服务器. 然后还需到192.168.0.119修改syslog配置,来允许来自远程的日志.<br /> * 在(如:/etc/sysconfig/syslog)SYSLOG_OPTIONS选项中添加 -r . * @param int $errno * @param string $errstr * @param string $errfile * @param int $errline * @param array $errcontext */ public static function errorHandler($errno, $errstr, $errfile, $errline, &$errcontext) { $time = date('Y-m-d H:i:s'); if (is_object($errno)) { //当errorHanlder扑捉的为异常时 $errorMsg = (string) $errno; echo $errorMsg; } else { $errorMsg = ''; $errorMsg .= 'PHPServer: ' . $_SERVER['SERVER_ADDR'] . " \n"; $errorMsg .= 'ErrorLevel: ' . self::$errorConstantMap[$errno] . " \n"; $errorMsg .= 'File: ' . $errfile . " \n"; $errorMsg .= 'Line: ' . $errline . " \n"; $errorMsg .= 'Details: ' . $errstr; } //openlog(null, LOG_CONS, LOG_LOCAL5); //syslog(LOG_DEBUG, str_replace("\n",'#',$errorMsg)); if (DEBUG_MODE) { $errorMsg = $time . " \n" . $errorMsg; require_once ROOT_PATH . '/lib/common/Debug.php'; common\Debug::setInfo('PHP_Error', $errorMsg, true); if (DEBUG_LEVEL == 0) { echo $errorMsg; } } return true; }
/** * 启动应用 */ public function run() { self::$requestParams = RequestUtil::getParams(); $moduleAction = 'Module\\' . self::$requestParams->module . '\\' . ucfirst(self::$requestParams->action); if (!class_exists($moduleAction, true)) { $msg = 'Milanoo module/action not found !' . $moduleAction . "\n" . 'Parsed request parameters:' . "\n" . var_export(self::$requestParams, true); if (DEBUG_MODE) { \Lib\common\Debug::setInfo('MethodNotFound', $msg); return; } error_log($msg); header('HTTP/1.1 404 Not found'); require ROOT_PATH . 'errors/404.php'; die; } header('content-type:text/html;charset=utf-8'); //启动各模块之前运行各额外方法 \Lib\Bootstrap::run(); //执行个相应模块 $module = new $moduleAction(); }
/** * 使用STOMP对象发送.消息格式\n * { * "from": "米兰邮件中心 <*****@*****.**>", * "to": "*****@*****.**", * "subject": "Stomp消息测试", * "content": "测试内容<br /><ul><li><h1>测试</h1></li><li>第一行</li></ul>", * "headers": "Content-type:text/html;charset=utf-8;\r\nCc: 李健2 <*****@*****.**>", * "params": "", * "username": "******", * "password": "******" * } * @param array $data 邮件 * @param array $extraOptions 附加设置.默认:$extraOptions=array('async'=>true) * @return Boolean */ public function stompSend($data, $extraOptions = array('async' => true)) { $stomp = $this->stomp(); if (!$stomp) { return false; } $send = function (&$msg) use($stomp, &$extraOptions) { if (DEBUG_MODE) { \Lib\common\Debug::setInfo('StompMsg', $msg, true); } $msg = json_encode($msg); $header = array('persistent' => 'true'); if (isset($extraOptions['async']) && !$extraOptions['async']) { $header['receipt'] = 'none'; } if (isset($extraOptions['priority'])) { $header['priority'] = (int) $extraOptions['priority']; } $result = $stomp->send(cfg::STOMP_MAIL_QUEUE, $msg, $header); return $result; }; $result = false; if (isset($extraOptions['async']) && !$extraOptions['async']) { $transactionId = date('ID-Y-m-d-H-i-s'); $stomp->begin($transactionId, array('transaction' => $transactionId)); } if (!is_array(current($data))) { $data = array($data); } foreach ($data as $msg) { if (empty($msg['username'])) { $msg['username'] = cfg::SMTP_USER; } if (empty($msg['from'])) { if (defined('\\config\\Mail::SMTP_FROM')) { $msg['from'] = cfg::SMTP_FROM; } else { $msg['from'] = cfg::SMTP_USER; } } if (empty($msg['password']) && defined('\\config\\Mail::SMTP_PWD')) { $msg['password'] = cfg::SMTP_PWD; } $result = $send($msg); if (!$result) { break; } } if ($result) { if (!empty($transactionId)) { $result = $stomp->commit($transactionId); } } else { //发送消息失败 if (DEBUG_MODE) { \Lib\common\Debug::setInfo('StompError', $stomp->error()); } if (!empty($transactionId)) { $result = $stomp->abort($transactionId); } } if (!$result) { //发送消息失败后的其它错误 if (DEBUG_MODE) { \Lib\common\Debug::setInfo('StompError', $stomp->error()); } } return $result; }
/** * 调用webservice.例:<br /> * [code] * $interface = $this->getInterface('json');//在model中实例化数据接口 * $data = $interface->call(null,array('id'=>23,'status'=0));//使用\config\Webserice::serviceUrl 作为webservice的URL * $data2 = $interface->call('product/product/getDetails',array('pid'=>3123)); //使用\config\Webserice::serviceUrl并附加根据模块名和动作名组成的子空间地址 * [/code] * 当直接使用\config\Webserice::serviceUrl定义的地址或setUrl()指定的地址时需留$subNamespace为null * @param string $subNamespace 根据命名空间,模块及方法区分的子地址,属于webservice url中的一段 * @param array $paramGet 附加到url中进行提交的数据 * @param array $paramPost 通过post进行提交的数据 * @param boolen $forceArray 强制返回关联数组.默认true * @param string $appendix api地址后缀名称.默认为.htm * @return Object json deocde后的对象 */ public function call($subNamespace, $paramGet = array(), $paramPost = array(), $forceArray = true, $appendix = '.htm') { if (DEBUG_MODE) { $invokeStartTime = sprintf('%.8f', microtime(true)); $invokeKey = 'CallStartTime:' . $invokeStartTime; $e = new \Exception(); self::$wsCallInfoStack[$invokeKey]['StackTrace'] = $e->getTraceAsString(); } $serviceUrl = $this->serviceUrl; /** * 作为页面内及memcache缓存key * @var string */ $cacheKey = md5($serviceUrl . $subNamespace . serialize($paramPost) . serialize($paramGet)); if (isset(self::$cachedResult[$cacheKey])) { return self::$cachedResult[$cacheKey]; } $result = false; //20120905需求,当http://www.milanoo.com/?nocache=true,则不需要缓存 if (isset($_GET['nocache']) && $_GET['nocache'] == 'true') { $this->needCache = false; } if ($this->needCache) { ini_set('memcache.chunk_size', 1042 * 90); $m = \Lib\Cache::init(); $result = $m->get($cacheKey); if (DEBUG_MODE) { self::$wsCallInfoStack[$invokeKey]['TimeConsumedInFetchFromMemcache'] = sprintf('%.8f', (microtime(true) - $invokeStartTime) * 1000) . 'ms'; } } //当读取缓存失败或者不需要缓存时 if (false === $result || !$this->needCache) { if ($this->needCache) { $dataBak = $m->get($cacheKey . $this->suffix); if (false !== $dataBak) { //主键缓存失败时,从副键缓存中读取至主键,以便其后的请求读取成功 $m->set($cacheKey, $dataBak, 0, $this->cacheTime); if (DEBUG_MODE) { //标记读取了副键缓存的数据 self::$wsCallInfoStack[$invokeKey]['CacheHit'] = 2; } } if (DEBUG_MODE) { self::$wsCallInfoStack[$invokeKey]['TimeConsumedInFetchFromMemcache'] = sprintf('%.8f', (microtime(true) - $invokeStartTime) * 1000) . 'ms'; if (false !== $dataBak) { self::$wsCallInfoStack[$invokeKey]['ContentLengthStoredInMemcache'] = number_format(strlen($dataBak)); } } } if (is_string($subNamespace)) { //@todo webservice url地址需根据webservice的地址规则进行改变 $serviceUrl = rtrim($serviceUrl, '?\\/') . '/' . $subNamespace . $appendix; } $appendedValues = array(); if (is_array($paramGet)) { foreach ($paramGet as $k => $v) { $appendedValues[] = $k . '=' . urlencode($v); } } $appendedValues = implode('&', $appendedValues); if (!empty($appendedValues)) { if (strpos($this->serviceUrl, '?') === false) { $appendedValues = '?' . $appendedValues; } else { $appendedValues = '&' . $appendedValues; } $serviceUrl .= $appendedValues; } //die($serviceUrl); $ch = curl_init(); if ($this->requestMethod == 'POST') { curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $paramPost); } curl_setopt_array($ch, array(CURLOPT_URL => $serviceUrl, CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => \config\Webservice::TIMEOUT, CURLOPT_HEADER => true)); if (DEBUG_MODE) { self::$wsCallInfoStack[$invokeKey]['TimeStart'] = $invokeStartTime; self::$wsCallInfoStack[$invokeKey]['URL'] = $serviceUrl; self::$wsCallInfoStack[$invokeKey]['GET'] = $paramGet; self::$wsCallInfoStack[$invokeKey]['POST'] = $paramPost; } $rawReturn = curl_exec($ch); if (DEBUG_MODE) { $this->communicationInfo = curl_getinfo($ch); self::$wsCallInfoStack[$invokeKey]['Info'] = $this->communicationInfo; self::$wsCallInfoStack[$invokeKey]['TimeConsumedInWebservice'] = sprintf('%.8f', (microtime(true) - $invokeStartTime) * 1000) . 'ms'; } if ($errNo = curl_errno($ch)) { $err = new \Exception('webservice错误:' . "\n" . var_export($this->communicationInfo, true) . "\n"); error_log($err->getMessage() . "\n" . $err->getTraceAsString()); $this->errorInfo[$errNo] = curl_error($ch); if (DEBUG_MODE) { self::$wsCallInfoStack[$invokeKey]['Error'] = $this->errorInfo; debug::setInfo('WSCall', self::$wsCallInfoStack); } curl_close($ch); if ($this->needCache && false !== $dataBak) { //webservice 调用失败,返回副键值 $dataBak = gzuncompress($dataBak); if (DEBUG_LEVEL === 0) { self::$wsCallInfoStack[$invokeKey]['CachedData'] = $dataBak; } return self::$cachedResult[$cacheKey] = json_decode($dataBak, $forceArray); } else { return false; } } curl_close($ch); $parsedRawReturn = explode("\r\n\r\n", $rawReturn); if (count($parsedRawReturn) > 1) { $rawReturn = array_pop($parsedRawReturn); } else { $rawReturn = ''; } $rawReturnHeaders = explode("\r\n", array_pop($parsedRawReturn)); $headers = array('Protocol' => array_shift($rawReturnHeaders)); foreach ($rawReturnHeaders as $header) { $header = explode(': ', $header); $headers[$header[0]] = $header[1]; } if (isset($headers['Content-Encoding'])) { $return = gzuncompress($rawReturn); } else { $return = $rawReturn; $rawReturn = gzcompress($rawReturn, 9); } if (DEBUG_MODE) { $this->rawResponse = $return; } $return = json_decode($return, $forceArray); if (DEBUG_MODE) { if (DEBUG_LEVEL === 0) { self::$wsCallInfoStack[$invokeKey]['RawResponse'] = $this->rawResponse; } debug::setInfo('WSCall', self::$wsCallInfoStack); } if (($decodeError = json_last_error()) !== JSON_ERROR_NONE && !$this->needCache) { //webservice返回的数据解码错误 $err = new \Exception('数据解析错误.' . "\n" . 'webservice 返回:' . $this->rawResponse . "\n"); error_log($err->getMessage() . "\n" . $err->getTraceAsString()); return false; } else { if ($this->needCache) { if ($decodeError !== JSON_ERROR_NONE || !isset($return['code']) || $return['code'] >= 10000) { //解码失败,或者没有返回状态code属性, 或者webservice APP报错系统错误 if ($dataBak !== false) { //结果错误时则使用上次的正确结果(非开发模式下) $return = gzuncompress($dataBak); $return = json_decode($return, $forceArray); $rawReturn =& $dataBak; } } else { //当只有结果正确时才更新永久缓存,尽可能减小cache操作 $m->set($cacheKey . $this->suffix, $rawReturn, 0, 0); } $m->set($cacheKey, $rawReturn, 0, $this->cacheTime); } self::$cachedResult[$cacheKey] = $return; } if (DEBUG_MODE) { debug::setInfo('WSCall', self::$wsCallInfoStack); } return $return; } else { if (DEBUG_MODE) { self::$wsCallInfoStack[$invokeKey]['ContentLengthStoredInMemcache'] = number_format(strlen($result)); } $result = gzuncompress($result); if (DEBUG_MODE) { //标记读取了副键缓存的数据 self::$wsCallInfoStack[$invokeKey]['CacheHit'] = 1; if (DEBUG_LEVEL === 0) { self::$wsCallInfoStack[$invokeKey]['CachedData'] = $result; } debug::setInfo('WSCall', self::$wsCallInfoStack); } return self::$cachedResult[$cacheKey] = json_decode($result, $forceArray); } }