sgy727 发表于 2023-10-13 08:33:11

PHP到底有多糟糕?

不知道什么时候“PHP是最好的编程语言”成为了对PHP本身最大的戏谑。很多人似乎很不屑,甚至蔑视使用PHP的人。似乎他只是一个玩具,简单、混乱、不成气候。这使得我这样一个小phper有时候会觉得自己就像一个在大人面前活尿泥的孩子,很菜,很不专业。
今天,我不想听编程的核心,不想听思想、理论知识等与语言本身无关的东西,因为道理我都懂。我就想知道,在你们心中客观的讲,PHP究竟有多糟糕?

滋滋629 发表于 2023-10-13 08:34:10

我是没怎么感受到php有多垃圾,可能我入行晚,而且一入行就是php7.4,8.0,什么包加载,内置函数,swoole,我用着方便的一批!
最重要的,我没经历过各位所说的php就是做web的阶段,从我入行就是用php给app,小程序做api!
但是我还是在转Go,我自己大学本身就是学c和java的,java没人带所以才改行,而且从我做php第二个项目就是给公司带来4000多个w纯利的项目,什么集群,负载均衡,队列,异步三个月一股脑的全塞进脑子里了,当然还是同学带着做的。
现在,自己在公司单挑20多万台终端设备的物联网项目,工资也还行。
那么,目前促使我转Go,甚至拿公司生产环境测Go的唯一原因就是php不值钱,go可以吹牛逼,值钱!

20220926补充,我的三个给老板挣钱的项目,刚开始都是老板们一句话,通常都是“要不这个项目,咱们搞一下?你多久上线给我测试?”!目前这个物联网,我是实打实的从老板决定做,到上线测试,收钱,只做了13天!为啥我一个人做,因为人家现成的工程,包部署要他25万,而我给他保证20天上线测试!最后,上线测试和正式商用,只隔了一个半小时!
我不是说php有多牛逼,我是想说php糟糕吗?糟糕的恐怕是你自己吧?你能不能做到15天上线,2小时商用,然后不出大问题?老板不是傻逼,通常都很精明,他们敢找你做,通常是你有项目落地,甚至给其他老板挣钱了,才会找你,好像扯远了

ilylyh1314 发表于 2023-10-13 08:34:34

我来回答这个问题是告诉各位开发者:你们根本不会用PHP这是个非常有趣的问题

无论是提问者还是回答者,无论是支持者还是反对者,都没有聊技术上的事,都只是观念的碰撞.
这很好理解,因为PHP已经流行了那么多年了,技术上没有那么多糟糕的地方,本质上还是开发人员观念的问题,这是一个我们必须要承认的事实,不同的开发人员的观念是不一样的,比如:
有的人认为代码是给人看的,他们狂热的推崇ORM,
有的人认为代码是给机器跑的,拼接的SQL比什么都快;
学院派认为一个语言需要有健壮的设计,所以狂热地推崇GO之类的语言,
实用派则认为语言的任何发展方向都要为开发人员服务,所以兼容性/实用性/稳定性处于不可撼动的地位.
激进的人总是想抛弃糟糕的,引入更酷的,
保守的人老是想着保留能用的,只引入不可或缺的.
注重长远架构设计的人会对业务做出层层分层,
需要快速实现的人做个MVC就已经谢天谢地了.
这种冲突很有意思,没什么对错,但我不是和事佬,我来回答这个问题是告诉各位开发者:你们根本不会用PHP(狗头).
当然,开个玩笑.
PHP有很多打开方式,所以当我们聊PHP时,最好说清楚自己在说什么,比如:

[*]PHP-FPM:传统的经典的动态语言使用方式
[*]PHP-CLI:普遍的强大的高性能的使用方式
[*]PHP-扩展:C/C++级别的扩展能力
以上三种打开方式大家可能都或多或少的了解一些:
PHP-FPM最流行的代表无疑是Wordpress,还有一大堆普遍常见的开发框架和开源产品,如ThinkPHP,Laravel,各类shop.
PHP-CLI也是最近流行起来的开发方式,比如Workerman/Swoole/React-PHP,能够获得更高的性能(相对PHP-FPM,主要是频繁加载等环节),类似Java和Go的部署模式,更多的网络开发能力,比如长链接/微服务,也有更安全的加载方式,比如以前的挂马方式就废了,PHP不再以动态加载的方式运行.
PHP-扩展却不是一个轻松地事,复杂的Zend-API让人望而却步,每个开发者都劝自己,不要搞扩展,好好活着,没必要深入C/C++,还不如学GO了.实际上PHP的扩展也有很多开发方式,比如swoole作者的PHP-X,和我介绍过的一个项目:PHP-CPP,他们把复杂的Zend-API抽象封装,让扩展的开发就像写PHP那样简单(真的,使用PHP-CPP写扩展真的跟PHP一样简单,强烈推荐)
如何开发 PHP 扩展?PHP 扩展应该注意些什么? - PHP武器库的回答 - 知乎 https://www.zhihu.com/question/20012801/answer/2390907392几个有趣的打开方式

以上几种用法算是"官方的","标配的","兼容的"用法,就是说你在PHP-FPM可以运行的代码,在PHP-CLI也能运行,在PHP-扩展中也能调用成功.
但是这里我要介绍几个其他的打开方式,他们或许不能完全兼容原来代码的运行方式,但也为我们的一些业务提供了一些新的开发方式,满足我们一些特殊的要求.
KPHP

KPHP是一个PHP编译器,能够将PHP代码编译成本地二进制文件.
KPHP会将PHP的代码转换成等效的C++代码,然后编译生成的C++代码并以嵌入式HTTP的方式运行.可以把它认为是PHP的"转译",因为他是把PHP的代码"翻译"成C++的代码,但最终效果来看,也算是一个PHP的"编译器".
KPHP不是面向JIT的,所有的了类型都是在编译时(翻译成C++时)推断的,不存在"慢启动"阶段.
但是:
KPHP并不是一个万能的项目,他不是PHP的一个分支,也不是PHP的一个扩展,它是一个全新的独立的运行PHP代码的方式,他有很多的限制,你可能没办法编译你现有的项目(比如ThinkPHP).
KPHP的诸多限制:

[*]不能编译本身就不能编译的功能,不能比如变量名调用函数:$fname()
[*]不能编译破坏系统类型的代码,比如数组中混合数字和对象
[*]一些PHP的细节特性,比如生成器和匿名类
KPHP和PHP本身有很多差异,比如在PHP中,运行时才会报错,而在KPHP中,必须修复所有错误才能运行,再比如在KPHP中所有的代码都是内联的,如果a文件需要b文件的函数,那就require引入b文件,这时其他文件不需要引入b文件也能调用到那个函数,同时KPHP不支持evel,反射,数组指针等等特性.
由于以上诸多限制,一般情况下你并不能将你现有的业务直接使用KPHP编译成二进制.
但是这并不代表他一无是处,你可以按照KPHP的规范标准去写代码,比如你系统中的某一个独立的小模块,然后把他编译成二进制文件,至少这部分系统不需要担心代码泄露的问题.
性能,你肯定想了解它的性能.
实际上对于密集的算法逻辑,比如冒泡排序,在网站给出的 测试中:

[*]PHP7.4 花费 2100毫秒,
[*]KPHP 花费 480毫秒,
[*]只有四分之一的时间
如果将冒泡排序使用跟多的数组函数进行优化,

[*]KPHP花费270毫秒
[*]C++花费220毫秒
[*]KPHP的性能几乎和C++一样
在小编看来,KPHP的性能确实不错,不过小编认为KPHP更棒的地方在于能够将PHP代码编译成二进制文件,这样我们在分发系统(产品)的时候,完全可以把最核心的技术和功能编译成二进制,避免代码泄露.
peachpie

另一个有趣的项目是peachpie,它能将PHP便以为.NET,这样就能获得.NET的能力,比如跨平台,二进制.
它的目标如下:

[*]提高性能,一般的将PHP编译成.NET之后,性能会得到一定的提升
[*]安全性.在标准化和可管理的.NET环境或.NET core环境中运行,代码都是编译过的
[*]跨平台开发,可以将PHP编译成可移植类库,在所有的.NET平台中运行
[*]完全兼容.NET,为peachpie编写的代码与PHP完全兼容
[*]双向操作,可以用C#和PHP混合编写,通过.NET框架通信
与之前介绍的KPHP而言,peachpie的目标和定位是为PHP提供一个新的运行平台,并且应当完全利用和兼容PHP的全部生态,这当然是美好的愿望.
但实际上,peachpie也并没有实现百分之百的PHP的特性,不过也完成了大部分:

http://pic1.zhimg.com/v2-94855ad21dc4fb7ecabbec8e649a9850_r.jpg?source=1940ef5c
更完整的函数表可以参考他的官网.
在小编看来,peachpie也为我们提供了一个新的分发方式,我们可以将一些简单地核心的最有价值的一部分功能使用peachpie来分发,完全可以做到保护代码的效果.
PHP-JS

这是一个很有趣的项目,他能够使用PHP来运行JS的代码,是的,可以在PHP中运行JS的代码,就好像用PHP做了一个Node一样,当然并没有Node那样的生态.
他可以在PHP中运行JS,并且和JS之间互通变量函数,让小编很激动的是,也可以互通资源类型和对象,比如PDO,
我们可以在PHP中实例化一个PDO资源,然后传递到JS代码当中:
$context = new JS\Context;

$context->assign('print_r', function($variable) { print_r($variable); });

$context->assign('database', new mysqli('example.com', 'user', 'password', 'database'));


$script = <<<'EOD'

    var result = database.query("SELECT id FROM test ORDER BY id ASC");

    while (row = result.fetch_assoc())
    {
      print_r(row);
    }

EOD;

// execute the script now
$context->evaluate($script);
当然小编多次尝试安装PHP-JS,但是他是一个C++扩展,遇到了很多新手问题,以后有机会会继续研究.
PHP-CPP

这个项目在前面已经简单介绍了一下,可以通过那个链接详细查看,这里小编还是想推荐一下它.
简单来说,就是使用C++来为PHP编写扩展,并且可以做到一个扩展只在一个站点加载.
面对PHP的扩展,每个人都会告诉你,ZendAPI是复杂的,混乱的,你驯服不了他,别浪费时间了.
实际上是这样的,但是PHP-CPP将ZendAPI封装起来,并且提供了完善的文档和注释,使得使用C++开发扩展变得非常容易和优雅,写起来甚至和PHP代码一样简单.
并且我们都知道,使用扩展来开发具体业务会有几个问题,

[*]没办法动态加载扩展
[*]扩展必须存储在指定的目录
[*]扩展一旦加载,对这个服务器上所有的站点都生效
实际上PHP-CPP完美的解决了这些问题,基本做法是,不要使用PHP原生的方式加载扩展,而是先用PHP-CPP做一个加载扩展的功能,使用C++的能力,来做动态加载,并且可以让你的扩展存储在任意位置,随意分发,同时也可以让加载的扩展只对指定站点生效,不存在安全问题.

结论

小编在开头说大家不会PHP,其实只是一句玩笑,但是对于国内大多数的开发展而言,包括PHP和其他的开发者,都有一个错误的概念:PHP=PHP-FPM.
就是说所有人都认为PHP-FPM就是PHP,只能做HTTP.
实际上并不是,小编介绍的这几个项目可能并不是主流趋势,但是PHP-CLI的开发方式已经流行起来了,比如ReactPHP在国外火了很久了,WebMan是workerman近两年推出的一个面向HTTP的一个解决方案,Swoole则被各类培训机构宣传.
所以PHP到底有多糟糕呢?
其实没那么糟糕,很多东西你不知道而已.

chinacfan 发表于 2023-10-13 08:35:19

看到 @Summer 的回答我也是无奈了,到今天了,还有人在转发这种一眼就能看出问题的谣言
复制一下之前发过的想法:

80%的互联网用PHP是个传播广泛的谣言,实际上原文是这样的“PHP is used by 78.9% of all the websites whose server-side programming language we know.”即:“PHP在所有服务端语言已知的web网站中,占78.9%”。事实上,PHP是少数几个会在HTTP头中暴露出明显特征的Web编程语言,而其他语言要么显示的是自己框架的名字(如flask),要么干脆就是nginx/squid之类的反向代理的名称。它跟实际上的市场占有率其实毫无关系。 从结果上也可以很容易看出这种局限性:第二名是http://ASP.NET,这同样是一种很容易看出特征的Web技术。可以尝试在 https://w3techs.com/sites/info/youtube.com 中查找下知名的网站,你会发现,基本只有PHP语言的网站正确显示了相应的技术。

除了HTTP头以外,W3Tech的统计还会识别常见的内容管理工具的源码特征,主要是WordPress之类的,然后会用这种工具的语言来标记这个网站。这些特征主要在基于模板的上一代web中比较有效,而对前后端分离的下一代web基本无效。

zhaoxiaoning 发表于 2023-10-13 08:35:45

随手讲一下 php 的 trialing comma 和 == 吧;

trialing comma

trialing comma 是这样的一个问题,在 php 7.3 之前,下面的是合法的
array(1,);
isset($a,);
unset($a,);

下面的是不合法的
test(1,);
ClassName::test(1,);
$a->test(1,);
new ClassName(1,);
虽然这个 trialing comma 在 php 7.3 中一致了rfc:trailing-comma-function-calls;不过别的语言第一版就解决的问题 php 直到去年才解决还不够糟糕么?

不过你以为这就解决了么?并没有,在 php 7.3 中下面是不合法的:
empty($a,);另外如果你用 psysh 或者用 php language server 的话,依然会提示出错。为什么呢,因为这个语法坑同时坑了 PHP-parser 和 torlerant-php-parser 两个唯二可用的 php 写的 php-parser 库。因为坑了两个 parser 库的原因,这个问题同时坑了 psysh, 唯一可用的 php repl。

还有,你猜猜这些代码报的是 parser error 还是 fatal error?(答案,一部分报的是 fatal error,另一部分报的是 parser error;我第一次碰到时我还以为是 psysh 的 bug,后来发现这些不合规语法的确就是报 fatal error)
==

然后这是我觉得最好玩的 php 的 == 了;首先 js 的三位一体图或者 == 表大家都知道;但是众所周知,php 比 js 好十倍:

[*]字符串可以等于 boolean,比如 "PHP SKR" == true;
[*]字符串可以等于数字,比如 "    233" == 233 "0233" == 233
3. array 和 object 不一致, [] 的比较有 == ],但是 new stdClass != new stdClass
4. object 和 字符串不一致;一个重载了 __toString 的类实例可以等于 string,但是不能和数字比较
5. 部分情况下(抛出 php notice)的情况下,== 没有返回值;
6. "   " == 0 ,不等于 false 和 null
7. [] == null 和 false ,不等于 0
我一时间能够想到的也就这么多了,并且为了行文简便起见省略了 === 下的 array 坑

如果只是这样的话,大不了就不用 == 就行了;但是呢,如果和 php 比 js 好十倍的库函数结合起来就能比 js 好一百倍。比如说,php 判断是否为数组内元素的 in_array 在默认情况下是 ==。
于是我们有
in_array(true, ["PHP SKR"]); // true
in_array("    ", ); // true
in_array(0, ,]); // true 现在重头戏来了
in_array(0, ) ? xecho(1): xecho(0);
// 为什么这里用 xecho 呢?因为直接用 echo 会有一个 parser 错误;大家猜猜会输出 1 还是 输出 0?
答案是都不输出,in_array 会在第一个元素报 PHP Notice 然后终止整行。

@灵剑 就说过,「你们 phper 总说 X 语言能做的 php 也能做,但是你们是否能说什么只是 php 能做其他语言不能做的」?显然,这么好的 == 和 in_array 就是只有 php 能做但是其他语言做不到的,是 php 特别好特波 SKR 的证明。

当 php 迈入 7.3 之后,变得更好了;我们通过引入 <=> 符号增强了 == 在现代 php 编程中的作用。因为 <=> 是使用 == 的,结合起来在比 JS 好一千倍的 PHP 中,我们可以

true <=> "PHP SKR";
"   012" <=> 12;
[] <=> 11;
<=> ;
(array) $obj <=> ["\0\0#privateKey" => 1];
不要问我这些东西的结果,这么好的操作符比「endofunctor 范猫上的 monoid」难多了,我学不会。

xiaoliang 发表于 2023-10-13 08:36:11

PHP 有多糟糕,简单说,PHP 是主流工业语言里最糟糕的。

看看 Swoole 的作者韩天峰怎么评价的:
PHP 语言有 20 多年的历史,由于一直保持向下兼容。存在很多糟糕的地方,比如:

[*]混乱的函数命名
[*]不友好的 Array/String 函数,至今数组和字符串的操作都没有实现 OO 接口
[*]混乱的参数顺序,导致完全记不住一个函数的用法,每次需要查手册或借助 IDE
[*]难用的 Zend API ,导致了在应用与内核之间,很难有一个中间层。比如 Node.js 做的就很好,它提供的 C++ API 可以让其他 C++ 程序员很方便地为 Node 编写扩展模块。而 Zend API 几乎就是地狱模式,对开发者要求太高了。我在今年新开发的 PHP-X 就是为了解决这个问题
[*]缺乏异步 IO 网络层,PHP 官方只提供了 sockets、stream、select 等 IO 函数,无法满足现在大并发时代的需求。所以就有了 Swoole 这个项目
[*]缺乏对多线程的支持,虽然有一个 pthreads 项目,但这个连玩具都算不上。多线程需要 PHP 语言底层进行支持,而 PHP 设计之初就没考虑过多线程

当然,PHP 也有明显的优点,比如其部署对于虚拟主机的友好超过(除了古老的 ASP 之外的)所有其他主流语言,因此在互联网应用爆发初期就占领了巨大市场,一些世界上最大的网站最初(甚至至今)都是 PHP 写的,这是其至今屹立不倒的核心原因。

如韩天峰所言,PHP 的糟糕主要源自于历史包袱。
或曰,其他语言也有历史包袱呀?确实,但是 PHP 的历史包袱特别严重。

这有几个原因。
第一,PHP 最初设计(相比其他编程语言)就很不专业。尽管 Rasmus 是个很优秀的程序员,但是语言设计方面不是他所专长,而且一开始他根本没有打算做个语言,而只是给自己个人使用的简单工具集。这些历史可以自行查阅 Rasmus 的访谈。这导致从设计到实现都有很多临时性的举措。奇怪的大小写设定(PHP黑系列之一:PHP 为什么大小写规则是如此不规则?),函数命名不一致(PHP黑系列之二:PHP 为什么函数命名是如此不一致?)等的根源都是这些未经设计的偶然因素。即使底层代码在PHP3之后就基本重写了,但由于后面提到的原因遗毒至今。
第二,PHP 的后续开发(相比其他编程语言)也缺乏语言设计专家的参与。一些借鉴其他编程语言的新特性虽然总体上还是可用的,但是可能存在微妙的语义问题或实现限制。一些设计错误并没有被修复,反而被延续和扩大。最典型的比如允许函数、常量同名,本来在PHP引入类、接口的时候就应该修正,但结果是允许类、函数、常量同名。这导致当 PHP 发展到今天,常量不能是闭包(Why PHP doesn't allow anonymous functions inside CONST?),导致命名空间必须用 use const/function 这样脱裤子放屁的语法(这个问题以后我有空会在《PHP黑系列》中单独讲一讲)。一些常用库的设计和改进也全凭运气。比如 JSON 相关的 API 的扩展和变更中出现了明显的失误(主要是由于后续维护者没能理解和保持最初 API 的隐含约束,以后我有空会在《PHP黑系列》中单独讲一讲)。
第三,PHP 社区信奉实用主义。实用主义不是不好,但是过度的实用主义导致 PHP 社区普遍低估其他因素(如编程体验)的重要性。PHP 历史上的巨大成功加剧了这种心理倾向,进一步削弱了改善动力。这可能也造成了对语言改善有想法的人(包括语言设计专家)与 PHP 社区的互相排斥。这反过来恶化了第二点。另一方面,由于 Rasmus 本人并没有领导 PHP 后续开发,也没有像 Python/Ruby/Perl 等语言的创造者那样保留对语言发展关键问题的最后的『仁慈独裁』权力,使得 PHP 后续发展历史上缺少敢于拍板做革命性修正的灵魂人物(所谓革命性修正,如 python3、perl6、ES6 等,注意这里不讨论革命性修正的具体得失)。

其实自从 PHP 5.4 之后,PHP 核心社区在语言改善上是有很多进步的,包括敢于做一些破坏兼容性的修改,开发节奏也比以前要快很多。PHP 7 更是一个非常巨大的改进。我们也看到了很多致力于提升开发体验和解决历史问题的 aggressive 的提案。但是更广泛的 PHP 开发者社区心态上还是没有跟上(此处国外了解不多,主要谈国内)。举个例子来说,本问题下的某个认为『PHP 谈不上有多糟糕』的高赞答主,之前在许多其他涉及 PHP 的问题发出『JIT 也不见得快』的评论。PHP 7 没有做 JIT 的原因,鸟哥解释过。糟糕的是,一些人把鸟哥的解释理解为『PHP 不需要 JIT』,或者『JIT 没用』,并且反以(没有JIT)为荣。实际上真正的原因是 PHP 以前的实现太糟糕了,以至于上了 JIT 也没卵用。在 PHP 7 重写了底层的 zval 之后,现在已经重新上了 JIT 并体现出了可观的性能提升。当然,我是不指望这些人能承认打脸的,他们只会继续拿这些事情来宣扬 PHP 是『最好的语言』。
PHP 社区的问题还表现在缺乏生态多样性。同样是引入静态类型的方言,Hack 的接受程度远远小于 TypeScript(之于 JavaScript)。注意,我不是在讨论 PHP 是否应该引入静态类型,而是在探讨一个世界顶级技术公司对其核心技术资产的推动力。PHP 领域,facebook 已经是顶级玩家。JS 领域,像 facebook 这个等级的,就多得去了。但是 facebook 对 PHP 社区的影响力居然远远不如其对 JS 社区的影响力。可见 PHP 社区的糟糕。我要是 facebook 的技术决策者,早晚是要抛弃 PHP 的(实际上已经开始抛弃了)。

总之,PHP 的糟糕最主要在于很难摆脱历史包袱。糟糕中的糟糕则是,尽管 PHP 核心开发团队确实在不断改进,但更广泛的社区似乎仍然心态保守。

先写这些吧。
页: [1]
查看完整版本: PHP到底有多糟糕?