设为首页收藏本站

LUPA开源社区

 找回密码
 注册
文章 帖子 博客

挑刺PHP:全面解析PHP的糟糕设计

2012-4-22 10:25| 发布者: joejoe0332| 查看: 15582| 评论: 1|原作者: OSCHINA|来自: OSCHINA

摘要: 译者注:这篇文章很长,而且可能读起来很乱,很难懂 前言 我的脾气古怪. 我会抱怨很多东西. 这个星球上大多数技术我都不喜欢. PHP不仅使用起来尴尬, 还有要嘛我想要的不适合, 要嘛不是最令人满意, 要嘛违背我的信 ...

变量

>>    无法声明变量. 当第一次使用时, 不存在的变量会被创建为 null 值.

>>    全局变量在使用前, 需要 global 声明. 这是根据上面得出的自然结果, 因此这是个完美的理由, 但, 如果没有显示的声明, 全局变量甚至无法读取 -- PHP 將悄悄的创建一个局部同名变量取代它. 我还没见过其它语言使用类似的方法处理范围问题.

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

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

>>    "引用" 使变量在语言中与众不同. PHP 是动态类型的, 因此变量通常无类型... 除了引用, 它修饰函数定义, 变量语法, 和赋值. 一旦变量被引用(可在任何地方发生), 它就一直是个引用. 没有明显的方法探测和解引用需要的变量值.

>>    好吧, 我说谎了. 有些"SPL types" 也作用于变量: $x = new SplBool(true); $x = "foo"; 將失败. 这有点像静态类型, 自己看看.

>>    A reference can be taken to a key that doesn’t exist within an undefined variable (which becomes an array). Using a non-existent array normally issues a notice, but this does not.

>>    通过函数定义的常量称为 taking a string; 这之前, 它们不存在. (这可能实际上是复制 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 错误不提供栈轨迹. 你不得不安装一个处理器生成它们. (但 fatal errors不行 -- 见下文.)

>>    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 (2 as $foo); (warning)

而下面这些不行:

        >>    试图访问不存在的类常量, 如 $foo::x. (fatal error)

        >>    使用字符串常量作为函数名, 或变量名, 或类名. (parse error)

        >>    试图调用一个示定义函数. (fatal error)

        >>    Leaving off a semicolon on the last statement in a block or file. (parse error)

        >>    使用 list 和其它准内建宏作为方法名. (parse error)

        >>    用下标访问函数的返回值, 如: foo()[0]. (parse error; 已在 5.4 中修复)

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

>>    __toString 方法不能抛出异常. 如果你尝试, PHP 將 ... 呃, 抛出一个异常. (实际上是个 fatal error, 可以被通过的, 除了...)

>>   PHP 错误和 PHP 异常是完全不同的物种. 它们不能相互作用.

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

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

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

        >>    Fatal 错误 (例如, new ClassDoesntExist()) 不能被任何东西捕获. 大量的完全无害的操作会抛出 fatal 错误, 由 于一些有争议的原因被迫终结你的程序. 关闭函数仍然运行, 但它们无法获取栈轨迹(它们运行在上层), 它们很难告知该程序是由一个错误还是程序的正常运行结束.

>>    没有 finally 结构, 使得包装代码 (注册处理器, 运行代码, 注销处理器; monkeypatch, 运行测试, unmonkeypatch) 很难看, 很难写. 尽管 OO 和异常大量的复制了Java的模式, 这是故意的, 因为 finally "在PHP上下文中, 只得其形不得其神".Huh ?


酷毙
1

雷人

鲜花

鸡蛋

漂亮

刚表态过的朋友 (1 人)

  • 快毕业了,没工作经验,
    找份工作好难啊?
    赶紧去人才芯片公司磨练吧!!

最新评论

关于LUPA|人才芯片工程|人才招聘|LUPA认证|LUPA教育|LUPA开源社区 ( 浙B2-20090187 浙公网安备 33010602006705号   

返回顶部