[吐槽]刚读了 yii3-demo, PHP 框架是怎么把 PHP (优雅的)玩死的。

2020-04-13 16:30:36 +08:00
 dvaknheo
虽然是看 yii3-demo 吐槽的,但 Laravel 等框架也适用。

业务代码里,和框架相关的代码越少才是耦合性越低啊。口口声声说解耦,但是一看代码里一堆和框架代码相关的,这能叫解耦么。

业务代码里,框架相关的代码多,意味着碰到框架相关的代码就越多

读代码,最怕的之一是:这东西怎么来的。 一两个特例马上能教人懂,多了没法马上会啊。

View 里不能做任何计算,不能 include 非 View 的代码。

Laravel 优雅的带着 PHP 优雅的 Java 化。当初 PHP 上手就干的年代,这是 PHP 的优势。

现在一堆代码,业务相关的没几行,这还是 PHP 么。

ORM 就非用不可么,Data struct 不容易理解么

有好用的文件路由不用,非得手写路由 (src/Factory/AppRouterFactory.php)
PHPer 的原则应该是 其他路由模式是文件路由的补充啊。

配置文件里一堆 use (config/web.php)

MVC 缺层都是大家的共识了, 业务逻辑层叫 Service 或 Logic 我都无所谓,但直接 Controller 里调用 ORM,以前 10k 行的 Controller 啊。 从 Controller 里把业务逻辑剥离出来,跑命令行测试不好么。

PHP 开发速度很快,运行速度也很快。 没必要为了那些优雅牺牲开发速度,运行速度。

讲真,我动力再足一点,写个同功能的 插进这些框架的 demo 中, 让大家见识一下应该用什么样的手段最符合 PHP 的快速开发模式。
16060 次点击
所在节点    PHP
126 条回复
Varobjs
2020-04-14 09:56:13 +08:00
很赞同,其他路由都是文件路由的补充,
搞不懂什么玩意都要路由文件里配置,你能想象一个上千行路由文件,URI 和 controller 完全看不出来,要去搜索,
结果就是各种重复功能接口
Varobjs
2020-04-14 09:59:43 +08:00
还有个各种框架都跑偏的,就是里面揉了大量设计模式,就为了所谓优雅。个人理解是,设计模式是去揉复杂业务代码的
tant
2020-04-14 10:07:04 +08:00
我个人理解的后端框架其实主要分三大部分
1 、orm:,因为我是从最早那批过来的,已经习惯手写 sql 了,所以这个我觉得可有可无,对于我来说。orm 只能简化数据插入和修改的操作

2 、路由和模板:这部分还是比较重要 业务逻辑部分都是必须的

3 、IoC 容器:高级的抽象,这部分 php 应该用不到

php 其实非常适合中小型项目,没有那么多的抽象和业务逻辑,所以 orm 和 ioc 这部分基本可以不要

我前几年做过几个 php 项目,就写了个简单的框架,自己用的非常好:
orm 直接用 pdo 代替,自己在封装一些 helper 函数,这样增删改查就方便了
路由部分我仿造 java 的注解,用反射获取 php 类的注释自动生成 rewrite 文件,也就相当于是自动路由了
模板也是直接用的 php 的语法直接 include 就可以了,不需要其他的第三方库
直接用 autoload 按照规则命名好文件后自动加载不仅自己看着方便,也算半个 ioc 了

因为用的不多,所以没觉得第三方框架有什么好,对于第三方框架我就觉得 Yaf 挺好的,哈
ipwx
2020-04-14 10:11:44 +08:00
@king888 @Varobjs 如果所有人都很熟练某个框架,那么大家一起开搞,肯定比大家一起从头开始写,要快得多啊。毕竟有个标准框架在那里,轮子不用造,接口不用约定,奥力给就行了。熟练的框架使用者,一般都比熟练地从头开始写要快得多。不然各个语言就没那么多框架了。

说白了就是 PHP 开发者熟练使用框架的太少了,所以才感觉小项目开发用框架快不起来。沉浸在舒适区,不愿学习新的生产力,就和 jQuery 一把梭的老人实际上是一致的。当然,近些年前端的复杂性已经使得 jQuery 一把梭的老人越来越少了。至于 PHP,可能要等老一代程序员退出舞台吧?(毕竟 CRUD 有啥难的)
zjsxwc
2020-04-14 10:12:53 +08:00
@Varobjs

文件路由的好处是直白哪个文件就是哪个路由,
坏处是可能存在被攻击的漏洞可以任意执行你的每个 php 文件、由于和文件绑定写死了不方便解耦与后续重构与对外对接交流
tabris17
2020-04-14 10:24:57 +08:00
laravel 的容器不错,但是整个架构谈不上优雅
JokeEnd
2020-04-14 10:26:35 +08:00
传统 php 开发人员跟用框架的开发者差别很大,思维和开发方式也不一样,你说的这些都不是 php 的问题,是开发者本身的问题。
beyondye
2020-04-14 10:27:00 +08:00
是的太重了,为此我放弃了那些所谓流行的框架,自己写了一个适用自己的 php 框架,https://github.com/beyondye/ENPHP
svaj
2020-04-14 10:30:18 +08:00
thinkphp5 不错,然后基于 thinkphp5 开发的 fastadmin 可以,真正的快捷开发了,建了表 curd 就出来,搜索出来,导出都有,我觉得这个做外包项目挺香的,贼快
fancy111
2020-04-14 10:34:14 +08:00
前后端每年语言更新不多,花样玩得挺多。
encro
2020-04-14 10:42:23 +08:00
作为一个从 cake,ci,kahana,zf,yaf,yii1,yii2...一路用过来的人来说,每次接触一个新的流行框架,都学习了一种新的解决问题的办法,每一种框架的流行都是有其道理的,他的道理就是他迎合和解决了那个时段的主要问题。
至少我用起来,写的代码是越来越安全了,团队效率是越来越高了,而不是越来越低了,代码性能定位越来越容易了,而不是性能问题越来越突出了。

@dvaknheo

这东西怎么来的。 一两个特例马上能教人懂,多了没法马上会啊。
Yii 定位是 advanced 框架,强调是安全、可配置、可扩展、性能可见。不是 ci,cake 等脚手架、helper 类之类的框架。

View 里不能做任何计算,不能 include 非 View 的代码。
可以啊,你看的是伪 demo 吧随便找一个,既然是 PHP 文件,不能计算,你是来搞笑的吗? https://github.com/yiisoft/yii-demo/blob/master/views/contact/form.php

当然可以 include,但是你得搞对路径啊,但是建议采用$this->render 替代。

Laravel 优雅的带着 PHP 优雅的 Java 化。当初 PHP 上手就干的年代,这是 PHP 的优势。
上手就干是 4.3 以前的优势,后来的主要优势是社区、开源项目、官方库。


现在一堆代码,业务相关的没几行,这还是 PHP 么。
因为已经不需要写这么多业务代码了,你配置好 rule 之后,自动驾驶了,自动驾驶你不应该关心是否有方向盘,而应该是自动驾驶是否可靠。

ORM 就非用不可么,Data struct 不容易理解么
有 Yii::$app->db->createCommand 和 Query 任你调用

有好用的文件路由不用,非得手写路由 (src/Factory/AppRouterFactory.php)
route 不用任何配置都可以跑的,你用的是官方 demo 么?


配置文件里一堆 use (config/web.php)
是的,这次改版最大的变化之一了。
为了遵守 psr 规范,让各大框架组件能够通用目标,牺牲小我为大我。。牺牲精神值得赞扬,但是我也觉得太多了,其实以前是隐藏的,现在变得开放出来的。也可以理解框架为了变得通用,不得不做各种抽象,比如缓存,日志,数据库为了兼容各种方案,不得采用各种适配器。如果你自己写一个框架,不用兼容那么多场景,那么这块确实是可以简化的(笑)。

MVC 缺层都是大家的共识了, 业务逻辑层叫 Service 或 Logic 我都无所谓,但直接 Controller 里调用 ORM,以前 10k 行的 Controller 啊。 从 Controller 里把业务逻辑剥离出来,跑命令行测试不好么。
和 Yii2 无本质区别,加了类型的 PHP 。。。作者 samdark 以前是搞 JAVA 的?或者指使代码写多了,记性不好了,加了类型便于 IDE 方法提示,如果你记性一致很好,那么可以不要这个类型提示,代码一样可以跑的。
至于你说的 Service 和 Logic 有什么必要吗?参考我上一个回复


PHP 开发速度很快,运行速度也很快。 没必要为了那些优雅牺牲开发速度,运行速度。
开发速度,得看工具和生态,Yii 有 gii,有各种数据服务器端,客户端验证,各种第三方库。
运行速度,性能优化得看性价比、定位速度和解决方案,Yii 等框架提供了 debug,性能问题一目了然。我在一台 4 核 8G 得 CPU 也可以跑一年几亿得交易额,我觉得性能非常好了,如果再发展,我是能花钱可以添加一点机器资源的。Yii 的四层 cache 设计方案,可以让你控制缓存在页面,局部 HTML,数据,请求级别。


讲真,我动力再足一点,写个同功能的 插进这些框架的 demo 中, 让大家见识一下应该用什么样的手段最符合 PHP 的快速开发模式。
我倒觉得是时候去框架了,不过我认为值得尝试解决方案是云函数+UI 仓库+项目仓库,看看国内大厂和国外新兴就知道,越来越向 low code 发展了,但是 low code 的基础是大量成熟的解决方案,所以我认为当前符合 PHP 的快速开发模式就是一套成熟的云原生的框架加各种 demo 。其他的话我并不看好。

@zjsxwc

symfony 确实是标杆,甚至比以前 zf 做得更好,值得尊敬。目前在 PHP 界都在向 psr 靠拢。

@HiCode

1 、PHP 从一开始流行就是因为适合小型项目,开发效率及运行效率都不错;

同楼上的回复,这是 4.3 以前的优势,后来的主要优势是社区、开源项目、官方库

2 、PHP 大流行后,部分有追求的程序员希望给 PHP 加一点 B 格,开始用各种模式要求 PHP,让 PHP 往 Java 方向发展。但 PHP 是脚本语言,Java 不是,Java 本身有足够的性能可以支撑起各种设计模式的性能损耗(但还是经常被吐槽太重太慢)——而 PHP 并没有这个性能来支撑。

PHP 为什么性能不好,知道吗?
解决性能问题首先要做是定位,通常说 PHP 性能不好的,不能常驻内存导致的吧,至少我还没有发现其他 PHP 性能不好的地方,至少我觉得够用了,举一个其他例子?
常驻内存可以用 swoole 之类的解决下,当然也没必要仅限于用 PHP 开发。


3 、各类设计模式在 PHP 项目中的普及,确实提高了效率,增强了一丢丢的团队协作,但开发的复杂性和性能的损耗却让 PHP 失去了他最开始的拥趸。

PHPer 也可以学习的,而且以前的方式还是可以用啊,为什么大家都愿意用了呢?因为以前的方式已经发展到头了啊,满足需求了啊,新的方式适用新的方向。

4 、为了追求性能和模式,所谓高手们抛下了 PHP 改用 go 、java 、c#,留下一个所谓“优雅”的 PHP 开发氛围。

高手们抛弃 PHP 采用 GO,
不是因为性能和模式。
而是环境,
环境变化了,
恐龙就不能生存了,
云计算、大数据的环境来了,
人类为了掌握周边环境降低风险,
天生就会自动去觉察掌握学习周边环境便于生存,
go 和 PHP 方向还是不一样的,
如果你用 go 去开发一个电商网站,
比如人人商城这类的这时候你会觉得还是 PHP 好,
如果你去开发一个 FQ 工具或者爬虫或者即时通讯服务端,无疑 GO 跨平台编译,协程让你飞起来。
如果我们学习后不能思考工具的适用场景,那么就不是真学了,这也是码农和架构师的却别吧,码农拿着锤子都是钉子,架构师所有工具都能恰如其分的使用。
TangMonk
2020-04-14 10:43:17 +08:00
吐槽下 symfony 让我学习下
yc8332
2020-04-14 11:27:22 +08:00
现在 php 都 java 化了。。。真实越来越难搞了。。前端也是啊,越搞越复杂
dvaknheo
2020-04-14 11:33:00 +08:00
@encro 首先感谢这个回答。
先从 https://github.com/yiisoft/yii-demo/blob/master/views/contact/form.php 开始
<?php
// ...
echo Alert::widget()
//..
?>
这地方可以分拆成两个

alert::Widget() ; 我倾向于从 controller 里直接传入 $html_Alert_widget_sent; 不在这里执行代码。 这块是固定的数据。
问题不大,只需要在前面加上
这个 Widget 的东西

action="<?= $urlGenerator->generate('site/contact') ?>"

这个问题就大了 $urlGenerator 从哪里冒出来的? 看起来是 url 函数? 为什么不直接写成 url('site/contact') ; 或 _url('site/contact') ;

XX 从哪里冒出来的?这是看代码最怕的事情之一。

PHP 有个函数,get_defined_vars(); 再加上 var_dump($this); 基本就能搞定 view 里面的东西了。
其他 <?= Html::encode($body['subject'] ?? '') ?> 问题不大
其实最希望的是 View 里 一个命名空间都不用,代码简洁得多。

----
这个严重的

https://github.com/yiisoft/yii-demo/blob/master/src/Blog/BlogController.php

```
public function index(Request $request, ORMInterface $orm, ArchiveRepository $archiveRepo): Response
{
/** @var PostRepository $postRepo */
$postRepo = $orm->getRepository(Post::class);
/** @var TagRepository $tagRepo */
$tagRepo = $orm->getRepository(Tag::class);

$pageNum = (int)$request->getAttribute('page', 1);

$dataReader = $postRepo->findAllPreloaded();

$paginator = (new OffsetPaginator($dataReader))
->withPageSize(self::POSTS_PER_PAGE)
->withCurrentPage($pageNum);

$data = [
'paginator' => $paginator,
'archive' => $archiveRepo->getFullArchive()->withLimit(self::ARCHIVE_MONTHS_COUNT),
'tags' => $tagRepo->getTagMentions(self::POPULAR_TAGS_COUNT),
];
return $this->render('index', $data);
}
```
严重在于 这个 $orm 不知道怎么来的,你知道他是 ORMInterface 接口 . var_dump(get_class($orm)) 知道他是 Cycle\ORM\ORM

用 debug_print_backtrace(2); 跟踪, 最后得知在 Yiisoft\Injector\Injector 注入进去的。

OK 前面 Container 部分我肯定没去看文档,直接从代码中学习了。

现在问题就是,不知道这个 $orm 怎么自己使用, 需要一个 App::getOrm();


那么,抽出这个有什么意义呢?
我们要把业务逻辑放在单独地方,用命令行来跑,看结果啊,不然你 10K 行的控制器,后面人改去吧。


```
public function BlogService_GetIndexData(int $pageNum)
{
$orm = $this->getOrm();

$postRepo = $orm->getRepository(Post::class);
$tagRepo = $orm->getRepository(Tag::class);
$archiveRepo= $orm->getRepository(Archive::class);

$data = [
'paginator' =>$postRepo->getDataForIndex ($pageNum);
'archive' => $archiveRepo->getDataForIndex(self::ARCHIVE_MONTHS_COUNT),
'tags' => $tagRepo->getTagMentions(self::POPULAR_TAGS_COUNT),
];
return $data;
}
```
这样不清晰么。
--
希望别超过长度
jin7
2020-04-14 11:33:42 +08:00
直接用 java 就行了
maddot
2020-04-14 11:42:48 +08:00
小项目感觉还是 Yii1 好用,可惜 xue qiang 好像已经完全不管 Yii 这个项目了
dvaknheo
2020-04-14 12:04:45 +08:00
@encro
Yii 定位是 advanced 框架,强调是安全、可配置、可扩展、性能可见。

安全方面目前没看出来
配置方面, 框架是否能给默认配置。
https://github.com/yiisoft/yii-demo/tree/master/config
一堆配置文件。我的 业务工程,能否不做这些配置也能跑,他们就用默认的配置。

可扩展性。 哪些扩展不得不在 yii 下使用。

看到 Injector 用 ReflectionClass,就提一个,为什么非得要反射不可? php 的性能就耗费在这上面。
我知道 container ,di 的原则是要做到不改动库文件下,实现改动库文件的功能。
比如 0day 漏洞出现,不强行修改 vendor 目录下的文件 ,直接 在 业务工程 里 添加额外代码迅速临时修复。

php 的 view 文件,能不计算尽量别计算,这是一条原则。我见过一个 view 模板(非 php 文件)写 sql 计算的烂代码。
不然还做 V-C 分离干什么。 include, render 算起来是相同说法。


因为已经不需要写这么多业务代码了,你配置好 rule 之后,自动驾驶了,自动驾驶你不应该关心是否有方向盘,而应该是自动驾驶是否可靠。

结果就是 Java 那种方法, 结果就跑到研究 rule 上了。 还不如 debug 来的快 . spring struts hibernate 为什么被淘汰了?

我确实是看的官方代码
https://github.com/yiisoft/yii-demo/blob/master/src/Factory/AppRouterFactory.php

没想到路由配置躲在这个地方。

配置文件里一堆 use (config/web.php)
是的,这次改版最大的变化之一了。
重复:有没有默认配置,让我的 业务工程看起来简单。

至于你说的 Service 和 Logic 有什么必要吗?参考我上一个回复

Service 层 就是用于命令行运行,直接跑代码看结果的。

比如模拟某个人操作,没必要用 curl 模拟从他登录开始吧。
拿到 uid,直接调用 service 业务层就行了。

开发速度,得看工具和生态
还有个入门门槛。用丰富的生态和工具,搞死了入门者。

解决性能问题首先要做是定位,通常说 PHP 性能不好的,不能常驻内存导致的吧,至少我还没有发现其他 PHP 性能不好的地方,至少我觉得够用了,举一个其他例子?

Laravel 啊,我第一个见到性能出现在代码瓶颈而不是 IO 瓶颈的框架。
不能常驻内存确实是 PHP 的一个缺点, 在 composer 出现之前。php 引用第三方的代码很少。
执行完 可数个文件就够了。
composer 之后,加载就成了个大问题。
而所有的框架都是一堆文件。
php7.4 预加载,解决了一部分性能问题。但是并没有完全解决:

一个请求过来,框架的 hello world 要比纯 php 的 helloworld 跑多出很多 php 代码。
能减少这些代码量么? 1 性能就是为了使用,我们不优化。2 每次都要对配置里的 path 处理最后一个 / 还不是为了让 sb 使用者不要在 少 / 的时候多出莫名其妙的 bug 检查,类推。

为了追求性能和模式,所谓 [WEB] 高手们抛下了 PHP 改用 go 、java 、c#,留下一个所谓“优雅”的 PHP 开发氛围。
james122333
2020-04-14 12:17:03 +08:00
嗯 路由入口就可以做了

@dvaknheo
高手有书障啊 读太多反而被迷惑
dvaknheo
2020-04-14 12:18:23 +08:00
@TangMonk symfony 啊,我印象中就是 laravel 5 的 symfony 组件用的是 symfony 2.3 的, 而 symfony 升级到 3.4 了。万一 symfony 2.3 里有安全漏洞,laravel 5 不就麻烦了。


symfony 的中文资料太少。

doctine 和 symfony 的关系 。 在 symfony 网站也没指出来。

zend framework3 出了个 不同的 html 编码组件,原来 htmlspecailchars 有这么多问题。

var_dumper 各家都有。

symfony 作为一个 lib,确实是不错的 lib. 需要轮子的时候,找 symfony,然后找 zend framework3 就是。
IceBay
2020-04-14 12:27:33 +08:00
@dvaknheo #39

这台电脑预装的 win7,win7 已经停止更新了,而最新的已经在用 win10 了。

万一有漏洞怎么办,我还是不用这台电脑了

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

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

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

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

© 2021 V2EX