首页 > 编程语言 >php注解使用示例

php注解使用示例

时间:2022-11-04 17:59:38浏览次数:39  
标签:function 示例 route controller 注解 php 路由

今天看到php注解的介绍文章很感兴趣,动手实际试了试挺好玩,写这篇文章记录下 php从8开始支持原生注解功能了,我们可以写个小的例子看看注解怎么玩。   先确定我们的任务目标 1、编写一个注解类route处理根据注解反射将使用注解的方法加入到路由列表 2、定义入口文件初始化项目自动完成路由列表的更新 3、根据URL请求从路由列表获取路由信息找到对应类实例化并执行对应方法   先做个约定: 1、约定路由格式为:http://localhost/8/index.php?c=index&a=index 这里c 表示控制器controller,a 表示动作 action 也就是类方法 2、约定目录结构 root |---index.php |---config.php |---route.php ---|controller |---index.php |---work.php   config.php配置文件,route.php注解路由类文件和index.php 入口文件平级 controller/indexController.php,controller/workController.php两个使用注解的测试控制器位于下一级目录controller中   前期准备 先准备两个类用来测试

<?php
class indexController
{
    #[route('/controller/index','get')]
    public function index():void
    {
        echo "This is attribute index controller \r\n";
    }

    #[route('/controller/test','get')]
    public function test():void
    {
        echo "This is attribute test controller \r\n";
    }
}

 

indexController控制器类,有两个方法index和test
<?php
class workController
{
    #[route('/controller/work','post')]
    public function work():void
    {
        echo "This is attribute work controller \r\n";
    }
}

 

workController控制器类,有一个方法work   前期工作完成,开始实际编写注解路由类
<?php
#[Attribute(Attribute::IS_REPEATABLE|Attribute::TARGET_METHOD)]
class route{

    public static $all = [];

    public static $path = '';

    public static $method = 'GET';

    public static $function = '';

    public static $controller = '';

    public function __construct(){}


    public function setPath(string $path):self
    {
        $this->path = $path;
        return $this;
    }

    public function setMethod(string $method):self
    {
        $this->method = $method;
        return $this;
    }

    public function setFunction(string $function):self
    {
        $this->function = $function;
        return $this;
    }

    public function setController(string $controller):self
    {
        $this->controller = $controller;
        return $this;
    }


    public function addRoute():void
    {
        self::$all[str_replace("Controller","",$this->controller)][$this->function] = $this;
    }
  先定义路由的相关类属性,这里不考虑访问范围问题都用public修饰符 在这个类中定义了设置path、method、function、controller属性的方法,返回值用$this表示可以链式调用 addRoute() 方法将当前对应按 [‘控制器’][‘方法’] 的二维数组存起来备用 这里要说明下#[Attribute(Attribute::IS_REPEATABLE|Attribute::TARGET_METHOD)] 这就是注解的定义,有这个表示这个类是注解类Attribute是注解关键词,后面小括号里的是注解属性配置 IS_REPEATABLE 表示这个注解可以重复使用 TARGET_METHOD 表示这个注解只能用来修饰类内的方法   注意:这里定义的TARGET_METHOD在php语法检查时不会进行验证,即用这个注解修饰属性或类代码也不会报错,但执行会抛出异常

 

有了注解类我们就可以开始实际使用了
<?php
    public static function setRoute($controllerClass){
        
        $ref = new ReflectionClass($controllerClass);
        $controller = $ref->getName();
        $methods = $ref->getMethods();

        foreach($methods as $method){
            $function = $method->getName();
            $attributes = $method->getAttributes(route::class);

            foreach($attributes as $attribute){

                 $route = $attribute->newInstance();
                // 拿到注解上的参数
                $params = $attribute->getArguments();

                $route->setController($controller)
                    ->setFunction($function)
                    ->setPath($params[0])
                    ->setMethod($params[1])
                    ->addRoute();
            }
        }
    }
}
在route类定义新的方法,根据注解反射路由列表setRoute()方法接收一个被route注解修饰的类作为参数。 通过反射获取控制器名称,方法列表将其调用route一系列方法设置属性并加入路由列表   现在我们可以使用注解生成路由列表了 indexController类的两个方法都使用route注解进行修饰,并指定path和method两个参数 此时我们打印route::$all路由列表

 

 

可以看到当前的路由列表确实是按照['控制器']['方法']的二维数组组装起来了,并且保存了每个路由的对象 到这里核心的使用注解生成路由列表其实已结束了,但如果不能看看效果谁知道你是不是胡说的呢?因此下面我们完善这个例子实现通过localhost/8/index.php?c=index&a=index格式的URL访问对应控制器的功能  
<?php
class app{
    public function appInit():self
    {
        if(glob("./controller/*.php")){
            foreach(glob("./controller/*.php") as $fileName){
                require_once($fileName);
                $className = str_replace("./controller/","",str_replace(".php","",$fileName));
                route::setRoute($className);
                //route::$all;exit();
            }
        }

        return $this;
    }

    public function run($config){
        $controller = $_GET['c']??$config['default_controller'];
        $action = $_GET['a']??$config['default_function'];

        if(isset(route::$all[$controller][$action])){
            $route = route::$all[$controller][$action];
            $className = $route->controller;
            $function = $route->function;
            (new $className)->$function();
        }else{
            exit("404 Not Found!");
        }
    }
}
这里我们定义一个app类作为项目的基本对象当前类中定义了两个方法 appInit()初始化项目并返回类对象 run() 根据对应的配置运行指定的路由和操作 为方便处理我这里直接遍历了controller目录,在实际的项目中应该使用自动加载机制按需加载 初始化时将controller目录下的全部控制器方法调用route类加入到路由列表   到这里我们只剩最后一步了,将请求过来的URL解析,找到controller 和 action 然后执行方法 这一步我们交给run()方法执行, run()方法接收$_GET参数 c 和 a 分别对应 控制器和动作 判断如果路由列表中有对应的控制器和方法则将类实例化,调用对应方法,如果路由列表中没有这个对应路由则返回404错误。 需要指出的是这里404并不一定是没有这个对应方法,也有可能是有方法但没有使用route注解修饰导致反射找不到这个方法。

 

 

有此控制器和动作执行对应类对应方法

 

 

没有这个动作或控制器返回404 最后为了健壮性我们增加一个默认的控制器和默认动作,如果URL中没有传任何控制器和动作参数则走默认动作,将这个配置提取到配置文件中
<?php
$config = array(
    'default_controller'=>'index',
    'default_function'=>'index',
);


return $config;
这样如果什么都不传我们的代码会默认访问index控制器下的index方法

 

 

贴上完整代码:
<?php
#[Attribute(Attribute::IS_REPEATABLE|Attribute::TARGET_METHOD)]
class route{

    public static $all = [];

    public static $path = '';

    public static $method = 'GET';

    public static $function = '';

    public static $controller = '';

    public function __construct(){}


    public function setPath(string $path):self
    {
        $this->path = $path;
        return $this;
    }

    public function setMethod(string $method):self
    {
        $this->method = $method;
        return $this;
    }

    public function setFunction(string $function):self
    {
        $this->function = $function;
        return $this;
    }

    public function setController(string $controller):self
    {
        $this->controller = $controller;
        return $this;
    }


    public function addRoute():void
    {
        self::$all[str_replace("Controller","",$this->controller)][$this->function] = $this;
    }

    public static function setRoute($controllerClass){
       
        $ref = new ReflectionClass($controllerClass);

        $controller = $ref->getName();

        $methods = $ref->getMethods();


        foreach($methods as $method){
            $function = $method->getName();
            $attributes = $method->getAttributes(route::class);

            foreach($attributes as $attribute){
 
                 $route = $attribute->newInstance();
                // 拿到注解上的参数
                $params = $attribute->getArguments();

                $route->setController($controller)
                    ->setFunction($function)
                    ->setPath($params[0])
                    ->setMethod($params[1])
                    ->addRoute();
            }
        }
    }
}
route.php  
<?php
class app{
    public function appInit():self
    {
        if(glob("./controller/*.php")){
            foreach(glob("./controller/*.php") as $fileName){
                require_once($fileName);
                $className = str_replace("./controller/","",str_replace(".php","",$fileName));
                route::setRoute($className);
                //route::$all;exit();
            }
        }

        return $this;
    }

    public function run($config){
        $controller = $_GET['c']??$config['default_controller'];
        $action = $_GET['a']??$config['default_function'];

        if(isset(route::$all[$controller][$action])){
            $route = route::$all[$controller][$action];
            $className = $route->controller;
            $function = $route->function;
            (new $className)->$function();
        }else{
            exit("404 Not Found!");
        }
    }
}
init.php  
<?php
class indexController
{
    #[route('/controller/index','get')]
    public function index():void
    {
        echo "This is attribute index controller \r\n";
    }

    #[route('/controller/test','get')]
    public function test():void
    {
        echo "This is attribute test controller \r\n";
    }
}
indexController.php  
<?php
class workController
{
    #[route('/controller/work','post')]
    public function work():void
    {
        echo "This is attribute work controller \r\n";
    }
}
workController.php  
<?php
$config = array(
    'default_controller'=>'index',
    'default_function'=>'index',
);


return $config;
config.php  
<?php
require_once('./config.php');
require_once('./route.php');
require_once('./init.php');

(new app)->appInit()->run($config);
index.php

标签:function,示例,route,controller,注解,php,路由
From: https://www.cnblogs.com/python-gulp-php/p/16858596.html

相关文章

  • 乘风破浪,遇见最佳跨平台跨终端框架.Net Core/.Net生态 - .Net应用架构示例项目集锦,研
    .NETApplicationArchitecturehttps://github.com/dotnet-architecture位于Github上dotnet-architecture名下的项目是集结了开源社区智慧的示范结晶,是研究和学习最新D......
  • php curl请求 header头携带参数
    phpcurl请求header头携带参数  ......
  • 声明Spring Bean和注入Bean的几种常用注解和区别
    Spring声明Bean的注解: @Component:组件,没有明确的角色。 @Service:在业务逻辑层(Service层)使用。@Repository: 再数据访问层(Dao层)使用。@Controller:再展现层(MVC->Sprin......
  • 自定义注解获取请求Header中的值
    前言这几天开发一个项目,为了方便,前台将当前登陆人的ID和名称放在每个请求的Header中(这里不考虑安全性之类的),这样后台只要需要用到,就直接从Header中get出来就可以了。后台......
  • @Cacheable注解实现Redis缓存
    SpringBoot缓存之@Cacheable介绍简介介绍:Spring从3.1开始就引入了对Cache的支持。定义了org.springframework.cache.Cache和org.springframework.cache.Cach......
  • Andorid图片等比例缩放解决方案示例
    前言图片等比例缩放平时经常用到,网上也提供了很多种方式来解决。这里记录自己开发过程中用到的一种等比例缩放场景。AndroidimageViewadjustViewBounds属性设置,可以支持等......
  • kotlin 注解声明与使用
    前言函数的调用需要知道函数所在的类,函数的入参个数和参数类型,注解和反射可以跳过这个限制,注解和反射可以编写事先未知的任意类代码。注解可以为类库赋予特定的语义,反射可以......
  • Linux下grep讲解及用法示例
    关于正则表达式的讲解请看博文:​这里写链接内容​​简介grep(缩写来自GloballysearchaRegularExpressionandPrint)是一种强大的文本搜索工具,它能使用特定模式匹配(包括......
  • 十堰网站建设用php、java、.net哪个编程语言好
    前言对于这个问题,我的回答是:在十堰网站建设时没有什么编程语言是最好的,只有适合自己的才是最好的!或许你对我的回复不是很满意,不过没关系,你可以看看我的分析就知道了。Php......
  • [2021N1CTF国际赛]Easyphp-Wp
    文章目录​​写在前面​​​​Wp​​​​简单分析​​​​小实验验证猜想可效性​​​​构造tar​​​​参考文章​​写在前面在各种带飞的情况下,web被带ak了,这里比较想写一......