PHP的问题全面阐述PHP网站设计的问题.docx

上传人:b****6 文档编号:8472068 上传时间:2023-01-31 格式:DOCX 页数:20 大小:39.45KB
下载 相关 举报
PHP的问题全面阐述PHP网站设计的问题.docx_第1页
第1页 / 共20页
PHP的问题全面阐述PHP网站设计的问题.docx_第2页
第2页 / 共20页
PHP的问题全面阐述PHP网站设计的问题.docx_第3页
第3页 / 共20页
PHP的问题全面阐述PHP网站设计的问题.docx_第4页
第4页 / 共20页
PHP的问题全面阐述PHP网站设计的问题.docx_第5页
第5页 / 共20页
点击查看更多>>
下载资源
资源描述

PHP的问题全面阐述PHP网站设计的问题.docx

《PHP的问题全面阐述PHP网站设计的问题.docx》由会员分享,可在线阅读,更多相关《PHP的问题全面阐述PHP网站设计的问题.docx(20页珍藏版)》请在冰豆网上搜索。

PHP的问题全面阐述PHP网站设计的问题.docx

PHP的问题全面阐述PHP网站设计的问题

PHP的问题全面阐述PHP网站设计的问题

前言

我的脾气古怪。

我会抱怨很多东西。

这个星球上大多数技术我都不喜欢。

PHP不仅使用起来尴尬,还有要嘛我想要的不适合,要嘛不是最令人满意,要嘛违背我的信仰。

我可以告诉你关于一门语言,所有我想避免的好方式,所有我喜欢的坏方式。

来吧,问吧!

谈话会很有趣!

php是唯一的例外。

几乎php抽象的所有东西都是支离破碎的。

包括语言,框架,整个生态系统都一塌糊涂。

我几乎不能单独列出咒骂的事情,因为它全身都坏了。

每次我打算编辑一堆杂乱如麻的php抱怨清单的时候,我都被一些琐事打乱,越深入就越会发现其它令人震惊的事情。

php让人难堪。

它是如此的破碎,但那些被培训的业余爱好者,却对它称赞不已。

php在做一些徽不足道的挽回措施,但我选择忘记它。

不过我得让我的系统摆脱这些东西,也就这样了,这是最后一次尝试。

打个比喻

我只是随口和Mel抱怨下,而她却坚决让我发表出来。

我甚至说不出来PHP到底怎么了,因为—还好。

想想你有一个,嗯,工具箱吧。

一堆工具。

看起来还好,有标准的东西。

你拔除螺丝钉,它怪异的有三个头。

OK,好吧,这对你不太有用,但你猜迟早有天会有用。

你拿出榔头,被震住了,两边都有是尖爪。

但它仍然能用,我的意思是,你可以用两头的中部斜着敲。

你拿出老虎钳,但它们没有锯齿面。

表面平而光滑。

这没多大用,但依然能用,没什么。

你可以继续。

工具箱的东西都是怪异和琢磨不定的,但又不能说毫无价值。

整体看没什么大问题;它的工具都齐全。

现在,想象有很多使用这些工具的木匠,它们和你说:

”这些工具有什么问题呢?

我们都用过,它们工作都很好啊!

”。

工匠们给你展示他们建的房子,每个门都是五边形的而屋顶是癫倒的。

你敲前门,它向内倒榻了,而他们却抱怨你打破了他们的门。

这就是PHP的问题。

立场

我认为下面的特质对于一门语言的生产力和可用性是重要的,而PHP在大范围破坏它们。

如果你不同意这些,好吧,我无法想像,我们永远不会达成一致。

一门语言必须是可预见的。

它是將人类的思想反映给计算机执行的媒介,因此它的关键是,人类对程序的理解实际要正确。

语言必须一致。

相似的东西就要看起来相似,不同的就是不同。

学习了语言的部分知识,就应能很容易理解剩下的部分。

语言必须简洁。

新语言应该减少继承旧语言的不好的形式。

(我们也可以写机器码。

)新语言当然应努力避免织入新的特有的形式。

语言必须是可靠的。

语言是解决问题的工具;应尽量避免引入新问题。

任何”陷阱”都会大量的分散注意力。

语言必须是可调试的。

当出错的时候,程序员必须修正它,我们需要获得我们想要的帮助。

我的立场是:

PHP到处处充满惊奇:

mysql_real_escape_string,E_ACTUALLY_ALL

PHP不一致:

strpos,str_rot13

PHP需要特别形式:

error-checkingaroundCAPIcalls,===

PHP古怪:

==。

for($fooas&$bar)

PHP晦涩:

默认无栈跟踪或fatals,复杂的错误报告

我不能就单个问题解释为什么它归为这些类,否则將会没完没了。

我相信读者自己会思考。

不要再和我扯这些东西了

我知道很多有利的论点。

我也听到很多反驳的论点。

这些都只能让谈话立即停止。

不要再跟我扯这些东西了,求你了。

不要和我说”好的开发者能用任何语言写出好的代码”,或者坏开发者。

.吧啦吧啦。

这毫无意义。

好的工匠可以用石头或锤子驾驭钉子,但你见过有多少工匠用石头的?

成为一个好开发者的标准之一就是善于选择工具。

不要和我说熟记上千个例外和古怪行为是开发者的职责。

是的,这在任何系统中都是必要的,因为电脑是傻的。

这不意味着,系统能疯狂的接受而没有上限。

PHP有的只是异常,这是不行的,一旦和语言摔角决斗,你实际编写程序就要花费更多的努力。

我的工具不能为我创建应用产生积极作用。

不要和我说“那就是CAPI的工作方式”。

这星球上高级语言存在的目的是什么,它们能提供的一切仅仅是一些字符串助手函数和一堆C的包装器?

如果是这样,那就用C!

这里,甚至还有为它准备的CGI库。

不要和我扯“搞出奇怪的事,是你活该”。

如果存在两个特性,总有一天,某些人会找到一起使用它们的理由。

再次强调,这不是C;这里没有规范,这里不需要“未定义行为”。

不要再和我扯Facebook和Wikipedia就用的PHP.我早知道了!

它们也能用Brainfuck写,但只要他们足够陪明,不断折腾这些事情,他们总能克服平台的问题。

众所周知,如果使用其它语言编写,开发时间可能会减少一半或加倍;单独拿出这些数据毫无意义。

上帝保佑,不要再和我扯任何东西了!

如果列出的没有伤害你的PHP的观点,无所谓,因此请停止在网上做无意义的争论,继续开发高帅富酷的站点来证明我是错的。

偷偷告诉你:

我非常喜欢Python.我也很乐意对它说些你不爱听的话,如果你真想的话。

我并不要求它完美;我只是想扬长避短,总结我想要的最佳东西。

PHP

语言核心

CPAN被称为“Perl的标准库”。

这并没有对Perl的标准库做过多说明,但它蕴含了健壮的核心可以构建强大的东西的思想。

基本原则

PHP最初很明确的是为非程序员设计的(言外之意,非专业程序);根源已经很难脱离。

从PHP2.0文档中挑选出来的对话:

一旦你开始为每个类型区分不同的操作符,你就开始使用语言变得复杂了。

例如,你不能为strings使用‘==’,你现在必须用‘eq’。

我没看出这点来,特别是那些类似PHP的脚本语言,它们大多数相当简单而多数情况下,作为非程序员,只想要一门包含少量基本逻辑语法的语言,而不想付出过多学习曲线。

PHP为保持前进不惜代价。

什么都有比没有好。

这不是个正确的设计原则。

早期的PHP受Perl影响;大量的标准库参考C使用“out”参数;OO部分的设计像C++和Java.

PHP从其它语言中引入大量的灵感,但对那些熟知其它语言的人,仍然难以理解。

(int)看起来像C,但是int并不存在。

命名空间使用\。

新的数组语法使用[key=>value],不同于任何其它语言定义hash字面量的形式。

弱类型(例如,默默的自动在strings/mumbers/等间转换)是如此的复杂。

少量的新特性以新语法实现;大多数工作通过函数或者看起来像函数的东西完成。

除了类的支持,这理所当然的需要新的操作符和关键字。

本页列出的问题都有官方解决方案—如果你想资助Zend修复它们的开源编程语言的话。

路漫漫,其修远。

思考下面的代码,从PHP文档的某地方挑出来的。

1.@fopen(''r');

它將做什么?

如果PHP使用–disable-url-fopen-wrapper编译,它將不工作。

(文档没有说,“不工作”是什么意思;返回null,抛出异常?

注意这点已在PHP5.2.5中移除。

如果allow_url_fopen在php.ini中禁用,也將不工作。

(为什么?

无从得知。

由于@,non-existentfile的警告將不打印。

但如果在php.ini中设置了scream.enabled,它又將打印。

或者如果用ini_set手动设置scream.enabled.

但,如果error_reporting级别没设置,又不同。

如果打印出来了,精确去向依赖于display_errors,再一次还是在php.ini.或者ini_set中。

我无法告诉你这个函数调用的行为,如果没有查看编译时标志,服务器端配置,和我的程序中的配置的话。

这些都是内建行为。

该语言充满了全局和隐似状态。

mbstring使用全局字符编码。

func_get_arg之类的看起来像正常的函数,但是只对当前正在执行的函数操作。

Error/exception处理默认是全局的。

register_tick_function设置了一个全局函数去运行每个tick(钩子?

)—-什么?

没有任何线程支持。

(不奇怪,因为上面已给出。

)加之缺乏内建的fork(下面提到),使得并行编程极其困难。

PHP的某些部分在实践中会产生错误代码。

json_decode对不正确的输入返回null,尽管null也是一个JSON解码的合法对象—该函数极不可靠,除非你每次使用后都调用json_last_error.

如果在位置0处找到,array_search,strpos,和其它类似的函数返回0,但如果都没有找到的话。

会返回false

让我们稍稍展开最后一部分。

在C中,函数如strpos返回-1,如果未找到。

如果你没检查这种情况,却试着以下标使用它,那將可能命中垃圾内存,程序会崩溃。

(也许吧,这是C.谁泥马知道。

我确定至少有工具处理它)

话说,Python中,等效的.index方法將抛出一个异常,如果元素没找到的话。

如果你不检查该情形,程序將崩溃。

在PHP中,该函数返回false.如果你把FALSE作为下标使用,或者用它做其他事情,PHP会默默的將它转成0,但除了用于===比较。

程序是不会崩溃的;它將执行错误的逻辑,且无任何警告,除非你记得在每个使用strpos和其它类似函数的地方包含正确的样版处理代码。

这真是糟透了!

编程语言只是工具;它们是为我服务的。

这里,PHP给我布下了陷阱,等着我跳进去,而我不得不时刻警惕这些无聊的字符串操作和相等比较。

PHP是个雷区。

我已经听过很多关于PHP解析器的故事,它的开发者来自世界各地。

有从事PHP核心开发工作的人,有调试PHP核心的人,也有和核心开发者交流过的人。

没有一个故事是赞赏的。

因此不得不在这里插入一句,因为它值得重复:

PHP是个业余爱好者的社区。

极少数人设计,为它工作,或极少有人知道他们在做什么。

(哦,亲爱的读者,你当然是个极品例外!

)那些成长了,想转投其它平台的人,使整个社区的平均水平下降。

这个,就是这里,是PHP的最大问题:

绝对的盲目领导盲目。

好了,回来面对现实吧。

操作符

==不中用。

"foo"==TRUE,和"foo"==0…但,当然TRUE!

=0。

==会將两边转成数字,如果可能的话,这意味着它將转成floats如果可能。

所以大的16进制字符串(如,passwordhashes)可能偶然会比较成true,尽管它们不一样。

就连JavaScript都不会这样做。

由于某些原因,"6"=="6","4.2"=="4.20",和"133"=="0133"。

但注意133!

=0133,因为0133是八进制的。

===比较值和类型…除了对象,只有两边实际上是同一对象才为true!

对于对象,==比较值(或每个属性)和类型,这又是===比较任何非对象类型的行为。

好玩吗?

比较大小也好不到哪去。

甚至行为都不一致:

NULL<-1,而NULL==0。

排序也因此不确定;它依赖于在排序中比较元素的算法的顺序。

比较操作符尝试排序数组,以两种不同的方式:

首先按长度,然后按元素。

如果它们有相同数量的元素但不同的keys,它们是不可比的。

对象比较比其它比较做得更多…除了那些即不小于也不大于的对象。

为了类型更安全的==比较,我们有===。

为了类型更安全的<比较,我们有…什么也没有。

"123"<"0124",通常,不管你怎么做。

类型转换也无济于事。

尽管上面的举动很疯狂,但却明确拒绝Perl’s的字符串paris和算术运行符,PHP没有重载+.+就是通常的+,而。

是通常的连接符。

[]下标操作符也可以拼写成{}。

[]可以用于任何变量,不光是字符串和数组。

它返回null,无错误警告。

[]仅能获取单个元素。

foo()[0]是个语法错误。

(已在PHP5.4中修复)

不像(从字面上看)任何其它语言都有的类似的操作符,?

是左结合的。

因此:

1.$arg ='T';

2.$vehicle =(( $arg =='B')?

'bus':

3.( $arg =='A')?

'airplane':

4.( $arg =='T')?

'train':

5.( $arg =='C')?

'car':

6.( $arg =='H')?

'horse':

7.'feet');

8.echo $vehicle;

打印horse.

变量

无法声明变量。

当第一次使用时,不存在的变量会被创建为null值。

全局变量在使用前,需要global声明。

这是根据上面得出的自然结果,因此这是个完美的理由,但,如果没有显示的声明,全局变量甚至无法读取—PHP將悄悄的创建一个局部同名变量取代它。

我还没见过其它语言使用类似的方法处理范围问题。

没有引用。

PHP所谓的引用是个真正的别名;这无疑是一种倒退,不像Perl的引用,也没有像Python那样的对象标识传递。

没有明显的方式检测和取消引用。

”引用”使变量在语言中与众不同。

PHP是动态类型的,因此变量通常无类型…除了引用,它修饰函数定义,变量语法,和赋值。

一旦变量被引用(可在任何地方发生),它就一直是个引用。

没有明显的方法探测和解引用需要的变量值。

好吧,我说谎了。

有些”SPLtypes”也作用于变量:

$x=newSplBool(true);$x="foo";將失败。

这有点像静态类型,自己看看。

Areferencecanbetakentoakeythatdoesn’texistwithinanundefinedvariable(whichbecomesanarray)。

Usinganon-existentarraynormallyissuesanotice,butthisdoesnot.

通过函数定义的常量称为takingastring;这之前,它们不存在。

(这可能实际上是复制Perl使用常量的行为。

变量名是大小写敏感的。

函数和类名不是。

使得方法使用驼峰式命名会很奇怪。

结构

array()和几个类似的结构不是函数。

$func="array";$func();不工作。

数组拆包可以使用list($a,$b)=…操作完成。

list()是类函数语法,就像数组那样。

我不知道为什么不给一个真正的专用语法,也不知道为什么名字如些的让人迷惑。

(int)很显然的被设计成类似C,但它不是单独的标记;在语言中,没有东西被称为int.试试看:

var_dump(int)不工作,它会抛出一个解析错误,因为参数看起来像是强制转操作符。

(integer)是(int)的别名。

也有(bool)/(boolean)和(float)/(double)/(real)。

有个(array)操作符用来转成数组和(object)用来转成对象。

这听起来很贴心,但常常有个用例:

你可以用(array)使得某个函数参数,既可以是单个元素,也可以是列表,相同对待。

但这样做不可靠,因为如果某人传递了单个对象,把它转换成数组將实际上生成了一个包含对象属性的数组。

(转换成对象执行了反转操作。

include()这类的函数基本上就是C的#include:

他们將其它的文件源码转存到你的文件中。

没有模块系统,甚至对PHP代码也一样。

没有类似嵌套或者局部范围的函数或类。

它们都是全局的。

include某文件,它的变量导入到当前函数范围中(给了文件访问你的变量的能力),但是函数和类存入全局范围中。

追加数组使用$foo[]=$bar.

echo不是函数。

empty($var)是如此极端,对于任何其它东西不表现为函数,除了变量,e.g.empty($var||$var2),是个解析错误。

为什么地球上有这种东西,解析器为什么需要了解empty?

还有些冗余的语法块:

if(…):

…endif;,等等。

错误处理

PHP的一个独特操作符是@(实际上从DOS借用过来的),它隐藏错误。

PHP错误不提供栈轨迹。

你不得不安装一个处理器生成它们。

(但fatalerrors不行—见下文。

PHP的解析错误通常只抛出解析的状态,没其它东西了,使得调试很糟糕。

PHP的解析器所指的例如。

内部作为T_PAAMAYIM_NEKUDOTAYIM,而<<操作符作为T_SL.我说“内部的”,但像上面说的,给程序员显示的:

或<<出现在了错误的位置。

大多数错误处理打印给服务器日志打印一行错误日志,没人看到而一直进行。

E_STRICT看起来像那么回事,但它实际上没多少保护,没有文档显示它实际上是做什么的。

E_ALL包含了所有的错误类别—除了E_STRICT.

关于什么允许而什么不允许是古怪而不一致的。

我不知道E_STRICT是怎样适用于这里的,但这些却是正确的:

试图访问不存在的对象属性,如,$foo->x.(warning)

使用变量做为函数名,或者变量名,或者类名。

(silent)

试图使用未定义常量。

(notice)

试图访问非对象类型的属性。

(notice)

试图使用不存在的变量名。

(notice)

2<“foo”(隐藏)

foreach(2as$foo);(warning)

而下面这些不行:

试图访问不存在的类常量,如$foo:

x.(fatalerror)

使用字符串常量作为函数名,或变量名,或类名。

(parseerror)

试图调用一个示定义函数。

(fatalerror)

Leavingoffasemicolononthelaststatementinablockorfile.(parseerror)

使用list和其它准内建宏作为方法名。

(parseerror)

用下标访问函数的返回值,如:

foo()[0]。

(parseerror;已在5.4中修复)

在列表的其他地方也有几个关于其它怪异解析错误的好例子

__toString方法不能抛出异常。

如果你尝试,PHP將…呃,抛出一个异常。

(实际上是个fatalerror,可以被通过的,除了…)

PHP错误和PHP异常是完全不同的物种。

它们不能相互作用。

PHP错误(内部,称为trigger_error)不能被try/catch捕获。

同样,异常不能通过set_error_handler安装的错误处理器触发错误。

作为替代,有一个单独的set_exception_handler可以处理未捕获的异常,因为用try块包装你程序入口在mod_pho模块中是不可能的。

Fatal错误(例如,newClassDoesntExist())不能被任何东西捕获。

大量的完全无害的操作会抛出fatal错误,由于一些有争议的原因被迫终结你的程序。

关闭函数仍然运行,但它们无法获取栈轨迹(它们运行在上层),它们很难告知该程序是由一个错误还是程序的正常运行结束。

没有finally结构,使得包装代码(注册处理器,运行代码,注销处理器;monkeypatch,运行测试,unmonkeypatch)很难看,很难写。

尽管OO和异常大量的复制了Java的模式,这是故意的,因为finally“在PHP上下文中,只得其形不得其神”.Huh?

函数

函数调用似乎相当昂贵。

一些内建函数与reference-returning函数交互,呃,一种奇怪的方式。

正如在别处提到的,很多看起来像函数或者看起来它们应该是函数的东西实际上是语言的构成部分,因此无法像正常函数一样的工作。

函数参数可以具有“类型提示”,基本上只是静态类型。

你不能要求某个参数是int或是string或是对象或其它“核心”类型,即使每个内建函数使用这种类型,可能因为int在PHP中不是个东西吧。

(查看上面关于(int)的讨论)。

你也不能使用特殊的被大量内建函数使用的伪类型装饰:

mixed,number,orcallback.

因此,下面:

1.functionfoo(string $s){}

2.foo("helloworld");

产生错误theerror:

PHPCatchablefatalerror:

Argument1passedtofoo()mustbeaninstanceofstring,stringgiven,calledin…

你可能会注意到“类型提示”实际上并不存在;在程序中没有string类。

如果你试图使用ReflectionParameter:

getClass()动态测试类型提示,將会得到类型不存在,使得实际上不可能取得该类型名。

函数的返回值不能被推断

將当前函数的参数传给另一个函数(分派,不罕见)通过call_user_func_array(‘other_function’,func_get_args())完成。

但func_get_args在运行时抛出一个fatal错误,抱怨它不能作为函数参数。

为什么为什么这是个类型错误?

(已在PHP5.3中修复)

闭包需要显示的命名每个变量为closed-over.为什么解析器不想办法解决?

(Okay,it’sbecauseusingavariableever,atall,createsitunlessexplicitlytoldotherwise.)

Closed-over变量,通过和其它函数参数相同的语义”传递”。

这样的话,数组和字符串等等,將以传值方式传给闭包。

除非使用&.

因为闭包变量会自动传递参数,没有嵌套范围,闭包不能指向私有方法,不管是否定义在类中。

(可能在5.4中修复?

不清楚。

函数没有命名参数。

实际上被devs显示拒绝,因为它“会导致代码臭味”。

Functionargumentswithdefaultscanappearbeforefunctionargumentswithout,eventhoughthedocumentationpointsoutthatthisisbothweirdanduseless.(Sowhyallowit?

向函数传递额外的参数会被忽略(除了内建函数,会抛出异常)。

丢失的参数被假定为null.

”可变”函数需要func_num_args,func_get_arg,和func_get_args.这类事情没有语法。

OO

PHP的函数部分被设计成类似C,但面向对象(hoho)被设计成类似Java.我不想过分强调这有多不合谐。

我还没有发现一个有大写字母的全局函数,重要的内建类使用驼峰式方法命名,并有getFoo的Java风格的属性访问器。

这是门动态语言,对吗?

Perl,Python,和Ruby都有一些通过代码访问”属性”的概念;PHP仅仅有笨重的__get之类的东西。

类型系统围绕着低层的Java语言设计,Java和PHP’s处一时代,Java有意的做了更多限制,照搬Java,我百思不得其解。

类不是对象。

元编程不得不通过字符串名指向它们,就像函数一样。

内建的类型不是对象,(不像Perl)也无法使得看起来像对象。

instanceof是个操作符,尽管很晚才增加进来,而大多数语言都建有专门的函数和语法。

受Java影响吗?

类不是第一类?

(我不知道它们是不是。

但有一个is_a函数。

它有个可选参数指定是否允许对象实际是一个字符串命名的类。

get_class是函数;没有typeof操作符。

同样有is_subclass_of.

然而,这对于内建类型无法工作,(再一次,int不是个东西)。

这样,你需要is_int等等。

右值必须是变量或字面量;不能是表达式。

不然会导致…一个解析错误。

clone是一个操作符?

OO的设计是一只混合Perl和Java的怪物。

对象属性通过$obj->foo,但类属性是$obj:

foo.我没见过任何其它语言这样做,或者这样做有什么用。

而,实例方法仍然能通过静态的(Class:

method)调用。

如果从其它方法中这么调用,会在当前$this上被看成常规的方法调用。

我认为吧。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 自然科学 > 天文地理

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1