花了四个月打磨的 laravel plus 开源 | laravel china 社区-380玩彩网官网入口

花了四个月时间,经过了两个项目的打磨,我写的 laravel plus 终于像个样子了,可以开箱即用了。

采用最新的 php8 的语法,大量借鉴了 springboot 中的 aop 编程思想,全方面拥抱注解。来看一下吧。

路由和控制器

采用注解路由,避免了在控制器和 api.php 的路由文件间跳转。首先在 api.php 中注册:

use zenith\laravelplus\easyrouter;
easyrouter::register();

接着就可以非常流畅的写路由了:

use zenith\laravelplus\attributes\routes\getmapping;
use zenith\laravelplus\attributes\routes\postmapping;
use zenith\laravelplus\attributes\routes\prefix;
#[prefix(path: '/user')]
class usercontroller
{
    #[getmapping(path: '/login')]
    public function login() {}
    #[postmapping(path: '/register')]
    public function register() {}
}

获取请求参数

获取请求参数可以使用 #requestbody 注解。先注册一个控制器中间件:

use zenith\laravelplus\middlewares\requestbodyinjector;
abstract class controller implements hasmiddleware
{
    public static function middleware(): array
    {
        return [
           requestbodyinjector::class, 
        ];
    }
}

然后就可以使用注解来将 request body 中的参数注入到类中的,结合 getter/setter 就很方便,ide 给出的提示会很友好:

use zenith\laravelplus\attributes\routes\getmapping;
use zenith\laravelplus\attributes\requests\requestbody;
class usercontroller extends controller
{
    #[getmapping(path: '/login')]
    public function login(#[requestbody] registerparams $params) {}
}
class registerparams
{
    // the modifiers must be public or protected.
    protected string $username;
    protected string $password;
}

参数校验

一样的,你需要先注册中间件,参数校验以及填充默认值:

use zenith\laravelplus\middlewares\requestparamsdefaultvalueinjector;
abstract class controller implements hasmiddleware
{
    public static function middleware(): array
    {
        return [
            requestparamsdefaultvalueinjector::class
            parametervalidation::class,
        ];
    }
}

接着就可以使用 #[param] 注解来校验参数了:

use zenith\laravelplus\attributes\validators\param;
class usercontroller extends controller
{
    #[getmapping(path: '/login')]
    #[param(key: 'username', rules: 'required|string|max:32', message: 'username is required.')]
    public function login() {}
}

也支持自定义的验证器,如下:

use closure;
use illuminate\contracts\validation\validationrule;
class passwordrule implements validationrule
{
    public function validate(string $attribute, mixed $value, closure $fail): void
    {
        $ispass = strlen($value) >= 8 && preg_match('/[a-za-z]/', $value) &&
            preg_match('/\d/', $value) &&
            preg_match('/[^a-za-z\d]/', $value);
        if (! $ispass) {
            $fail('the :attribute must be least 8 characters and contain at least one letter, one number and one special character.');
        }
    }
}

验证规则写类名就可以了:

use zenith\laravelplus\attributes\validators\param;
class usercontroller
{
    #[getmapping(path: '/login')]
    #[param(key: 'username', rules: passwordrule::class, message: 'password is error')]
    public function login() {}
}

支持参数的默认值设置:

use zenith\laravelplus\attributes\validators\param;
use zenith\laravelplus\attributes\requests\requestbody;
class usercontroller extends controller
{
    #[param(key: 'page', rule: 'integer|min:1|max:100', default: 1, required: false, message: 'page is error')]
    public function querylist(#[requestbody] queryparams $params) 
    {
        dump($params->getpage());       // output: 1
    }
}

dto、vo、bean

这里的 bean 和 java 中的 bean 并非一个意思,而是 dto 的意思,就是承载数据的对象。

use zenith\laravelplus\bean;
/**
 * @method getusername()
 * @method setusername()
 * @method getpassword()
 * @method setpassword()
 */
class registerparams extends bean
{
    protected string $username;
    protected string $password;
}
new registerparams(['username' => 'bob', 'password' => 'passw0rd'])

除了自动实现 getter/setter 外,还支持 toarray() 以及 tojson()equal() 等方法, 还可以无限级嵌套。

use zenith\laravelplus\bean;
class user extends bean
{
    protected company $company;
}
class company extends bean
{
    protected string $name;
}

支持数组 bean 的嵌套:

use zenith\laravelplus\bean;
use zenith\laravelplus\attributes\beanlist;
/**
 * @method company[] getcompanies()
 */
class user extends bean
{
    /**
     * @var company[]
     */
    #[beanlist(value: company::class)]
    protected array $companies;
}

支持类型转换:

use zenith\laravelplus\bean::
use zenith\laravelplus\attributes\typeconverter;
class user extends bean
{
    #[typeconverter(value: boolconverter::class)]
    protected boolenum $isguest;
}
class boolconverter
{
    public function convert(bool|string $value): boolenum
    {
        if ($value === 'yes' || $value === 'yes' || $value === 'y' || $value === 'y') {
            return boolenum::true;
        }
        if ($value === 'no' || $value === 'no' || $value === 'n' || $value === 'n') {
            return boolenum::false;
        }
        return $value ? boolenum::true : boolenum::false;
    }
}

依赖注入

laravel 只支持通过构造函数注入,下面的示例演示了使用注解讲依赖注入到成员属性:

use zenith\laravelplus\traits\injectable;
class usercontroller
{
    use injectable;
    #[autowired]
    private userservice $userservice;
    public function register()
    {
        $this->userservice->register(); 
    }
}

除此之外,还支持 #[service]#[component]#[logic] 等注入的注解。

总结

总而言之,还有更多其他的功能,比如简化了 crud,通过 #[value] 注入配置到类属性…自动生成接口文档、mock 数据….

,欢迎点 star 或者使用、或者参与开发、或者交流讨论。

本作品采用《cc 协议》,转载必须注明作者和本文链接
本帖由系统于 1个月前 自动加精
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
以构建论坛项目 larabbs 为线索,展开对 laravel 框架的全面学习。应用程序架构思路贴近 laravel 框架的设计哲学。
讨论数量: 77

请问下楼主是自由开发者吗?像这种四个月做开源项目没有收益全靠爱心发电吗?

1个月前
(楼主) 1个月前
jaguarjack

fpm 吗?如果是的话,那么注解是每次请求都解析一次吗

1个月前
jaguarjack (作者) 1个月前
(楼主) 1个月前
(楼主) 1个月前
(楼主) 1个月前

终于有人开始做注解这件事了 : 1: 已 star

1个月前
(楼主) 1个月前

很好 但是我不用,你这个适合自己折腾, 不适合生产环境 :flushed:

1个月前
(楼主) 1个月前

感觉路由注解对于稍微复杂点的项目来说,后期维护成本比定义在 router.php 中的要高很多!

1个月前
(楼主) 1个月前

注解的大量使用,还可以直接通过扫描注解生成接口或者 sdk 或者其他文档,代码即文档。

这是通过 laravel-plus 直接生成的接口文档,你可以在命令行下输入 php artisan docs:build 命令即可,支持 vitepress。

1个月前

其他的都实践过了,佬,这是什么操作:public function querylist(#[requestbody] queryparams $params) 给个关键字~

1个月前
(楼主) 1个月前
yangweijie

支持 事务注解吗 嵌套事务?

1个月前
(楼主) 1个月前
cooper

面向 spring boot 编程 :smiley:

1个月前
(楼主) 1个月前

有错别字修改下 讲 ->将:

然后就可以使用注解来讲(将) request body 中的...

除了 javac#, 还能在 rust 项目看到这种写法,不过叫法不一样,rust 叫宏编程。

注解能提升开发效率,就是存在一点学习成本,团队采用的话,大家都按照注释的思路去写代码,这提升不是一点半点,算是一种编程范式。下个项目就试试这个工具,支持! : 1:

1个月前
(楼主) 1个月前
(楼主) 1个月前
bigbug-gg (作者) 1个月前
(楼主) 1个月前

: 1:

1个月前
(楼主) 1个月前

问个问题,如果使用#[param] 注解来校验参数,message参数可以支持多语言吗?

1个月前
(楼主) 1个月前

你做的非常好,可是php越做越垃圾,忘了自己的初衷,也没跟上多线程并发时代,只会搞些语法糖

1个月前
(楼主) 1个月前
1个月前
(楼主) 1个月前

支持在参数类中配置校验规则的注解吗?

class registerparams
{
    #[param(rules: 'required|string|max:32', message: 'username is required.')]
    protected string $username;
    protected string $password;
}
1个月前
(楼主) 3周前
(楼主) 1个月前
(楼主) 1个月前
(作者) 1个月前

本人一直在写nodejs的nest和php laravel、webman和go的gin等,最喜欢的还是laravel,也很喜欢nestjs的@注解,hyperf其实是支持注解的,这套aop思想给代码整洁和易用性提供了很大的便利,希望楼主这个项目越来越好,会持续关注。

1个月前
(楼主) 1个月前

支持 octane吗

1个月前
(楼主) 1个月前

:joy:这样做的目的是啥呢?能加快开发速度还是能够让项目运行更快?

1个月前
(楼主) 1个月前
leirhy

看完还觉得还是直接用laravel吧,这个还得重学一遍,适合自己团队折腾 :joy:

1个月前
(楼主) 1个月前
1个月前
(楼主) 1个月前
(楼主) 1个月前
1个月前
cooper

他来了 :grin:

1个月前
(楼主) 1个月前
cooper (作者) 1个月前
(楼主) 1个月前

和 hyperf 框架很像了

1个月前
(楼主) 1个月前

牛逼,尽然能够全部自己实现。
不过我是利用现成的去改的
路由注解:spatie/laravel-route-attributes
数据对象:spatie/laravel-data,比如dto,vo等等,写了一些工具直接从数据库生成dto和vo,并自动添加一些基础的注解验证。还有fromcurrentuser和fromcurrentuserproperty(注入当前用户)等注解
文档的话(openapi):zircote/swagger-php和darkaonline/l5-swagger,zircote/swagger-php这个开源项目的代码很难去改,历史悠久了。为了省时间,还是硬着头皮去看了。自己写了一些zircote/swagger-php的processor去解析laravel中的路由,数据传输对象(dto)等等,可以少写许多zircote/swagger-php注解。ui使用的
和swagger ui

1个月前
(楼主) 1个月前
(作者) 1个月前

我也在做这个事情 实现了校验和文档生成的功能 不过没有做路由通过注解实现 主要是实现swagger文档和自动化测试 不知道用人想要这个不 我在考虑要不要开源

1个月前
(楼主) 1个月前
一个人的江湖

好东西 : 1:

1个月前
(楼主) 4周前

laravel本身就够慢了,注解反射解析比较适合常驻内存的运行模式。

1个月前
(楼主) 4周前

任何语言、框架只要使用了反射,性能都会大打折扣,说实话 spring boot 也很慢,好在 java 注解提升了开发效率。应用在内部后台其实无所谓,慢点不影响啥。
如果是对外的,只能说是buff叠满了。数据库的io已经很低了,基本是走的内网连接。这里慢一点那里慢一点,接口耗时就能到一两秒。前端也这么搞,一个页面加载下来一两分钟,点一个加载转半天圈

3周前
(楼主) 3周前
(作者) 3周前
(楼主) 3周前
(作者) 3周前

今天闲暇之余观摩了老哥的作品,对代码质量和严谨性深感钦佩。
这绝对是一个极具潜力的作品。如果能持续不断地进行精细打磨未来的可能性不可限量。

在此基础上,是否可以考虑增加一些可能性?

  • 统一注解接口,提供类似中间件的处理机制,允许用户自定义注解。
    注解实体不仅限于存储注解信息,还可以包含生命周期管理以及更多的元数据(何时被扫描, 被附加注解bind于什么单位, 运行时所处容器沙箱, 触发事件, 销毁时机等)。

  • 优雅的路由注册方式,设计一种更优雅的方法来切入路由注册流程,确保在不对现有业务逻辑造成侵扰的前提下,能够更加细致地干涉业务流程。

  • 结构化缓存机制,将扫描的结果结构化并缓存至内存或外部存储中,并考虑在进程重启或重载时的数据同步问题。

以上仅是我对该项目当前架构的一些设想,我很想知道作者对于这些想法的看法如何

3周前
(楼主) 3周前
(楼主) 3周前
(楼主) 3周前
(楼主) 3周前
(楼主) 3周前
月光

虽然我觉得以 laravel 目前的状态强行上这套 aop 没有什么优势,但我仍然觉得很牛,star 了有机会看看各种实现。

1周前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!
未填写
文章
8
粉丝
4
喜欢
67
收藏
44
排名:1004
访问:5482
博客标签
社区赞助商
网站地图