当前位置: 首页 > 后端技术 > PHP

php8注解详解

时间:2023-03-29 19:05:17 PHP

注解语法#[Route]#[Route()]#[Route("/path",["get"])]#[Route(path:"/path",methods:["get"])]其实语法和实例化类很相似,只是少了new关键字。需要注意的是注解名不能是变量,只能是常量或者常量表达式//instantiatedclass$route=newRoute(path:"/path",methods:["get"]);(path:"/path",methods:["get"])是php8的新语法,传参时可以指定参数名,不要按照形参的顺序传参。注解类作用域在定义注解类时,可以使用内置的注解类#[Attribute]来定义注解类的作用域,也可以省略,PHP会根据使用场景自动动态定义作用域.注解作用范围列表:Attribute::TARGET_CLASSAttribute::TARGET_FUNCTIONAttribute::TARGET_METHODAttribute::TARGET_PROPERTYAttribute::TARGET_CLASS_CONSTANTAttribute::TARGET_PARAMETERAttribute::TARGET_ALLAttribute::IS_REPEATABLE在使用时,#[Attribute]同],为方便起见,一般采用前者。1~7很好理解,分别对应类,函数,类方法,类属性,类常量,参数,all,前6项可以用|组合或任意运算符,例如Attribute::TARGET_CLASS|属性::TARGET_FUNCTION。(Attribute::TARGET_ALL包括前6个项目,但不包括Attribute::IS_REPEATABLE)。Attribute::IS_REPEATABLE设置注解是否可以重复,例如:classIndexController{#[Route('/index')]#[Route('/index_alias')]publicfunctionindex(){echo"hello!world".PHP_EOL;}}如果未设置Attribute::IS_REPEATABLE,则Route不允许重复使用。上面说了,如果不指定作用域,PHP会动态确定作用域,怎么理解?例子:handler=$handler;返回$这个;}publicfunctionrun(){call_user_func([new$this->handler->class,$this->handler->name]);}}classIndexController{#[Route(path:"/index_alias",methods:["get"])]#[Route(path:"/index",methods:["get"])]publicfunctionindex():无效{回声“你好!世界”。PHP_EOL;}#[Route("/test")]publicfunctiontest():void{echo"test".PHP_EOL;}}classCLIRouter{受保护的静态数组$routes=[];publicstaticfunctionsetRoutes(array$routes):void{self::$routes=$routes;}公共静态函数match($path){foreach(self::$routesas$route){if($route->path==$path){返回$route;}}die('404'.PHP_EOL);}}$controller=newReflectionClass(IndexController::class);$methods=$controller->getMethods(ReflectionMethod::IS_PUBLIC);$路线=[];foreach($methodsas$method){$attributes=$method->getAttributes(路线::类);foreach($attributesas$attribute){$routes[]=$attribute->newInstance()->setHandler($method);}}}CLIRouter::setRoutes($routes);CLIRouter::match($argv[1])->run();phptest.php/indexphptest.php/index_aliasphptest.php/test使用newInstance时,定义的动作范围会生效,注解类定义的动作范围和实际修改的范围是否一致在其他场景不检测注意命名空间$attribute->getName(),'args'=>$attribute->getArguments()];}var_dump($arr);}}namespaceDoctrine\ORM\Mapping{classEntity{}}namespaceDoctrine\ORM\Attributes{classTable{}}namespaceFoo{使用Doctrine\ORM\Mapping\Entity;使用Doctrine\ORM\Mapping作为ORM;使用Doctrine\ORM\Attributes;#[Entity("importedclass")]#[ORM\Entity("importednamespace")]#[\Doctrine\ORM\Mapping\Entity("absolutefromnamespace")]#[\Entity("importabsolutefromglobal")]#[Attributes\Table()]functionfoo(){}}namespace{classEntity{}dump_attributes((newReflectionFunction('Foo\foo'))->getAttributes());}//输出:array(5){[0]=>array(2){["name"]=>string(27)"Doctrine\ORM\Mapping\Entity"["args"]=>array(1){[0]=>string(14)"importedclass"}}[1]=>array(2){["name"]=>string(27)"Doctrine\ORM\Mapping\Entity"["args"]=>array(1){[0]=>string(18)"importednamespace"}}[2]=>array(2){["name"]=>string(27)"Doctrine\ORM\Mapping\Entity"["args"]=>array(1){[0]=>string(23)"absolutefromnamespace"}}[3]=>array(2){["name"]=>string(6)"Entity"["args"]=>array(1){[0]=>string(27)"importabsolutefromglobal"}}[4]=>array(2){["name"]=>string(29)"Doctrine\ORM\Attributes\Table"["args"]=>array(0){}}}与普通类的命名空间一致其他需要注意的问题不能放在注解类的参数列表中使用unpack语法。$a->getName(),$ref->getMethod('foo')->getAttributes()));$ref=new\ReflectionClass(C2::class);print_r(array_map(fn($a)=>$a->getName(),$ref->getMethod('foo')->getAttributes()));$ref=new\ReflectionClass(C3::class);print_r(array_map(fn($a)=>$a->getName(),$ref->getMethod('foo')->getAttributes()));C3继承了C1的foo方法,也继承了foo的注解。而C2重写了C1的foo方法,所以注解不存在。