php-parser在Aop编程中的使用方法
这篇文章主要讲解了“php-parser在Aop编程中的使用方法”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“php-parser在Aop编程中的使用方法”吧!
创新互联拥有十余年成都网站建设工作经验,为各大企业提供网站建设、做网站服务,对于网页设计、PC网站建设(电脑版网站建设)、重庆APP开发公司、wap网站建设(手机版网站建设)、程序开发、网站优化(SEO优化)、微网站、域名注册等,凭借多年来在互联网的打拼,我们在互联网网站建设行业积累了很多网站制作、网站设计、网络营销经验,集策划、开发、设计、营销、管理等网站化运作于一体,具备承接各种规模类型的网站建设项目的能力。
在laravel下使用php-parser实现aop
composer require nikic/php-parser
Test.php
ProxyVisitor.php
enterNode -> leaveNode -> afterTraverse * * Class ProxyVisitor * @package App\Aop */ class ProxyVisitor extends NodeVisitorAbstract { protected $className; protected $proxyId; public function __construct($className, $proxyId) { $this->className = $className; $this->proxyId = $proxyId; } public function getProxyClassName() { return \basename(str_replace('\\', '/', $this->className)).'_'.$this->proxyId; } public function getClassName() { return '\\'.$this->className.'_'.$this->proxyId; } /** * @return \PhpParser\Node\Stmt\TraitUse */ private function getAopTraitUseNode(): TraitUse { // Use AopTrait trait use node return new TraitUse([new Name('\App\Aop\AopTrait')]); } /** * Called when leaving a node * 把类方法里的逻辑重置掉 * * @param Node $node * @return int|null|Node|Node[]|Class_|ClassMethod */ public function leaveNode(Node $node) { // Proxy Class if ($node instanceof Class_) { // Create proxy class base on parent class return new Class_($this->getProxyClassName(), [ 'flags' => $node->flags, 'stmts' => $node->stmts, 'extends' => new Name('\\'.$this->className), ]); } // Rewrite public and protected methods, without static methods if ($node instanceof ClassMethod && !$node->isStatic() && ($node->isPublic() || $node->isProtected())) { $methodName = $node->name->toString(); // Rebuild closure uses, only variable $uses = []; foreach ($node->params as $key => $param) { if ($param instanceof Param) { $uses[$key] = new Param($param->var, null, null, true); } } $params = [ // Add method to an closure new Closure([ 'static' => $node->isStatic(), 'uses' => $uses, 'stmts' => $node->stmts, ]), new String_($methodName), new FuncCall(new Name('func_get_args')), ]; $stmts = [ new Return_(new MethodCall(new Variable('this'), '__proxyCall', $params)) ]; $returnType = $node->getReturnType(); if ($returnType instanceof Name && $returnType->toString() === 'self') { $returnType = new Name('\\'.$this->className); } return new ClassMethod($methodName, [ 'flags' => $node->flags, 'byRef' => $node->byRef, 'params' => $node->params, 'returnType' => $returnType, 'stmts' => $stmts, ]); } } /** * Called once after traversal * 把AopTrait扔到类里 * * @param array $nodes * @return array|null|Node[] */ public function afterTraverse(array $nodes) { $addEnhancementMethods = true; $nodeFinder = new NodeFinder(); $nodeFinder->find($nodes, function (Node $node) use (&$addEnhancementMethods) { if ($node instanceof TraitUse) { foreach ($node->traits as $trait) { // Did AopTrait trait use ? if ($trait instanceof Name && $trait->toString() === '\\App\\Aop\\AopTrait') { $addEnhancementMethods = false; break; } } } }); // Find Class Node and then Add Aop Enhancement Methods nodes and getOriginalClassName() method $classNode = $nodeFinder->findFirstInstanceOf($nodes, Class_::class); $addEnhancementMethods && array_unshift($classNode->stmts, $this->getAopTraitUseNode()); return $nodes; } } /** * 切面 * * Trait AopTrait * @package App\Aop */ trait AopTrait { /** * AOP proxy call method * * @param \Closure $closure * @param string $method * @param array $params * @return mixed|null * @throws \Throwable */ public function __proxyCall(\Closure $closure, string $method, array $params) { $res = $closure(...$params); if (is_string($res)) { $res .= ' !!!'; } return $res; } }AopController.php
create(ParserFactory::PREFER_PHP7); $ast = $parser->parse(file_get_contents(base_path().'/app/Test.php')); // 把parser代码后的语法树(对象)转为字符串形式 // $dumper = new NodeDumper(); // dd($dumper->dump($ast)); $className = 'App\\Test'; $proxyId = uniqid(); $visitor = new ProxyVisitor($className, $proxyId); $traverser = new NodeTraverser(); $traverser->addVisitor($visitor); // 使用已注册的访问者遍历节点数组,返回遍历节点数组 $proxyAst = $traverser->traverse($ast); if (!$proxyAst) { throw new \Exception(sprintf('Class %s AST optimize failure', $className)); } $printer = new Standard(); // 打印一个节点数组 $proxyCode = $printer->prettyPrint($proxyAst); // dd($proxyCode); eval($proxyCode); $class = $visitor->getClassName(); $bean = new $class(); echo $bean->show(); } }感谢各位的阅读,以上就是“php-parser在Aop编程中的使用方法”的内容了,经过本文的学习后,相信大家对php-parser在Aop编程中的使用方法这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是创新互联,小编将为大家推送更多相关知识点的文章,欢迎关注!
网页名称:php-parser在Aop编程中的使用方法
分享网址:http://hbruida.cn/article/jhsics.html