有个 PHP 插件设计思路想跟大家探讨下是否可行?

2019-09-04 17:08:39 +08:00
 xiaotuzi

我自己开发了一个 MVC 架构的 CMS 系统(以前帖子提过,暂时只开发到 dev 版本,beta 还未发布),目前系统有个插件功能,我原本已有的一个设计思路是这样:

①系统入口-->根据路由检测 controller 及 action,优先调用插件 plugins 目录的 controller 和 action 如下:

url:http://xxxx/Index/index

↓↓访问插件目录( plugins )同名控制器 IndexController.php 里面的 index 方法

Home/plugins/IndexController.php

↓↓如果不存在同名控制器或者存在控制器,不存在对应方法 index,则访问系统控制器

Home/IndexController.php

上面这个是已有的插件设计思路,用户只需要制作同名控制器放入 plugins 文件夹即可,但是有个弊端是一个方法只能设计一个插件,因为不能存在多个同名文件共存的情况。所以,我打算重新增加一个插件设计,如下:

②系统入口-->根据路由检测系统模块 Home、controller 及 action,查询对应 hook 表内是否有注册这个控制器的插件(钩子),如下:

url:http://xxxx/Index/index

↓↓根据模块 Home、控制器 Index、方法 index 查询表 hook 是否有注册对应的钩子,如果有,则预选执行钩子,如:TestController.php 里面的 index 方法绑定了这个方法,存在多个则根据排序 orders,依次执行。

Home/plugins/TestController.php Class(Test)->index() 如果存在多个注册:

( Home/plugins/Test1Controller.php Class(Test1)->index1())

( Home/plugins/Test2Controller.php Class(Test2)->index2())

↓↓执行完 hook 表里注册的钩子,再执行真正的控制器,当然,有可能钩子里面就直接 exit 了,不再执行下去。

Home/IndexController.php Class(Index)->index()

如上,两种设计思路,可能都是我自创的,我希望是所有控制器都能够自由定义,不拘于个别放置埋点的地方才可以设计插件。第一种设计,在不改动系统文件情况下,完美融入系统,弊端前面也说了,一个类里面的同个方法不能接入多个插件。第二种是我今天刚设计出来的,在安装插件的时候,需要在 hook 表里面新增注册的插件,一个方法可以不限制注册插件个数,执行顺序也可以自由定义,我感觉每次查询数据库这个会导致很大的问题,如果 100W 访问,估计数据库直接 GG 了,要不改为读取文件的形式?实际运用不知道会出现什么状况?想问问大家有什么弊端?或者推荐一下你自己的设计思路,友善谈论。

4018 次点击
所在节点    PHP
11 条回复
yinjy
2019-09-04 17:23:26 +08:00
没看明白,感觉像中间件?
ben1024
2019-09-04 17:26:32 +08:00
可以注册时进行代码验证,注册后加入缓存
tmkook
2019-09-04 17:38:33 +08:00
不要考虑数据库查询次数,100W 访问?达到再想办法优化。改文件形式 IO 确定不是瓶颈?
xiaotuzi
2019-09-04 17:40:44 +08:00
@yinjy 就是入口对 url 解析,第一种先解析到插件目录调用同名控制器,第二种是根据控制器等查询注册的插件,再调用插件,最后调用系统方法。
xiaotuzi
2019-09-04 17:45:22 +08:00
@ben1024 加入缓存的话,类似读取本地缓存吗?那还是转为了文件存储,类似加载配置。
xiaotuzi
2019-09-04 17:46:45 +08:00
@tmkook 额,改为 include 引入配置的方式,会不会更好?注册插件的时候转为 json 存储到本地文件配置中,然后再入口引入配置。
ben1024
2019-09-04 20:07:48 +08:00
@xiaotuzi 看使用频率,低频文件,高频 redis
dvaknheo
2019-09-05 18:53:37 +08:00
嗯,类似功能最容易搞乱
最开始,你替换就行
后来,封装前后吧
再后来,一个插件变多个
再后来, 多个插件要有顺序

看怎么适度而止了
xiaotuzi
2019-09-06 06:51:16 +08:00
@dvaknheo 已经知道解决方案了。因为全局控制器可以插件重定义,所以在入口的时候做插件调用是最方便的,但是如果一个方法加入了很多插件,就可能导致运行大大增加,同时实例化几个插件类比一个方法内直接写执行内容是不一样的,所以效率上,同个方法上写执行内容要快,但是没办法,插件本来就额外功能,我也保留了第一种插件制作方式,如果觉得插件注册太多,自己想办法集成到一个文件内也是可以的。
关于第二种插件设计,先缓存 hook 表到缓存,每次方法只需要 foreach 去循环判断,有就执行,没有就跳过,不用一直访问数据库,一般人也不会一个方法加十几个插件进去吧…如果有,那就付费解决🌚
ywisax
2019-09-08 01:31:37 +08:00
太局限了。这样设计的话,等于一个路由给多个回调,也就是在路由的 mapping 上做下手脚。
既然提到 hook 了,就不如直接点,参考大部分现代框架的做法,将要打桩的上下文通过事件分发出去再收集回来,这样比你想的灵活多了。
Youngxj
2019-09-10 16:27:20 +08:00
一直想做插件模块,但是表单编程写久了,想不出来插件模块怎么搞了,难受

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/597931

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX