问题:使用swoole compiler加密类似drupal这样的项目的时候在不做处理的情况下会出现项目无法运行的情况,分析了drupal的源码发现在drupal的方法中有一个方法会通过file_get_contents直接获取php文件的内容,然后将获取的内容用token_get_all函数进行代码分割,然后分析分割后的代码获取该文件的注释和use的类,因为file_get_contents所获取的代码是加密后的代码,所以也就产生了错误,当然不止这一处存在这样的问题,drupal加载了symfony,symfony中文件缓存也有类似的操作,通过读取php文件,对文件进行正则匹配然后缓存到新文件中
解决方案:对于获取类名,注释等,可以通过反射函数代替token_get_all函数,一些反射无法获取的信息比如use信息,则通过swoole_loader.so扩展进行获取
待解决:symfony的缓存文件机制和drupal的setting.php文件的处理暂时未想到合理的解决方案,因为两者都是通过分析php源码,然后在源码的基础上添加新的代码在存入文件的
StaticReflectionParser.php文件的改动主要如下,获取文件如果是加密文件则走新添加的代码,如果不是加密文件则还是走老方法
/** * @return void */ protected function parse() { if ($this->parsed || !$fileName = $this->finder->findFile($this->className)) { return; } $this->parsed = true; $contents = file_get_contents($fileName); if (strpos($contents, 'SWOOLEC') === false) { if ($this->classAnnotationOptimize) { if (preg_match("/\A.*^\s*((abstract|final)\s+)?class\s+{$this->shortClassName}\s+/sm", $contents, $matches)) { $contents = $matches[0]; } } $tokenParser = new TokenParser($contents); $docComment = ''; while ($token = $tokenParser->next(false)) { if (is_array($token)) { switch ($token[0]) { case T_USE: $this->useStatements = array_merge($this->useStatements, $tokenParser->parseUseStatement()); break; case T_DOC_COMMENT: $docComment = $token[1]; break; case T_CLASS: $this->docComment['class'] = $docComment; $docComment = ''; break; case T_VAR: case T_PRIVATE: case T_PROTECTED: case T_PUBLIC: $token = $tokenParser->next(); if ($token[0] === T_VARIABLE) { $propertyName = substr($token[1], 1); $this->docComment['property'][$propertyName] = $docComment; continue 2; } if ($token[0] !== T_FUNCTION) { // For example, it can be T_FINAL. continue 2; } // No break. case T_FUNCTION: // The next string after function is the name, but // there can be & before the function name so find the // string. while (($token = $tokenParser->next()) && $token[0] !== T_STRING) ; $methodName = $token[1]; $this->docComment['method'][$methodName] = $docComment; $docComment = ''; break; case T_EXTENDS: $this->parentClassName = $tokenParser->parseClass(); $nsPos = strpos($this->parentClassName, '\\'); $fullySpecified = false; if ($nsPos === 0) { $fullySpecified = true; } else { if ($nsPos) { $prefix = strtolower(substr($this->parentClassName, 0, $nsPos)); $postfix = substr($this->parentClassName, $nsPos); } else { $prefix = strtolower($this->parentClassName); $postfix = ''; } foreach ($this->useStatements as $alias => $use) { if ($alias == $prefix) { $this->parentClassName = '\\' . $use . $postfix; $fullySpecified = true; } } } if (!$fullySpecified) { $this->parentClassName = '\\' . $this->namespace . '\\' . $this->parentClassName; } break; } } } }else{ $ref = new \ReflectionClass($this->className); $parent_ref = $ref->getParentClass(); $this->docComment['class'] = $ref->getDocComment()?:''; if ($this->classAnnotationOptimize) { return; } if (is_file($fileName)) { $php_file_info = unserialize(naloinwenraswwww(realpath($fileName))); foreach ($php_file_info as $key => $info) { if ($key == 'swoole_namespaces' || $key == 'swoole_class_name') { continue; } $this->useStatements[$key] = $info; } } $this->parentClassName = $parent_ref->getName(); if (strpos($this->parentClassName, '\\')!==0) { $this->parentClassName = '\\'.$this->parentClassName; } $static_properties = []; $properties = $ref->getProperties(); $parent_properties = $this->createNewArrKey($parent_ref->getProperties()); foreach ($properties as $property) { if (isset($parent_properties[$property->name]) && $property->class == $parent_properties[$property->name]->class) { continue; } $static_properties[] = $property; } $last_comment = '';//兼容框架bug foreach ($static_properties as $property) { $property_comment = $property->getDocComment()?:$last_comment; if ($property_comment) $last_comment = $property_comment; $this->docComment['property'][$property->name] = $property_comment; } $static_methods = []; $methods = $ref->getMethods(); $parent_methods = $this->createNewArrKey($parent_ref->getMethods()); foreach ($methods as $method) { if (isset($parent_methods[$method->name]) && $method->class == $parent_methods[$method->name]->class) { continue; } $static_methods[] = $method; } $i = 0;//兼容框架bug foreach ($static_methods as $method) { $method_comment = $method->getDocComment()?:''; if (empty($method_comment) && $i == 0) $method_comment = $last_comment; $this->docComment['method'][$method->name] = $method_comment; } } }