Home > Backend Development > PHP Tutorial > Comprehensive analysis of PHP's poor design from 5 aspects_PHP Tutorial

Comprehensive analysis of PHP's poor design from 5 aspects_PHP Tutorial

WBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWB
Release: 2016-07-20 10:58:18
Original
729 people have browsed it

Translator’s Note: This article is very long and may be confusing to read and difficult to understand

Foreword

I have a weird temper. I complain about a lot of things. I don't like most technologies on the planet.

Not only is PHP awkward to use, but it either doesn't fit what I want or isn't the best. Satisfactory, or against my beliefs. I can tell you about a language, all the good ways I want to avoid, and all the bad ways I like it. Come on, ask! The conversation will be fun!

php is the only exception. Almost everything that php abstracts is broken. Including the language, frameworks, the entire ecosystem is a mess. I can barely list the cursed things individually because it's broken all over. Every time I When I was trying to compile a messy list of complaints about PHP, I got distracted by some trivial things, and the deeper I dug, the more shocking things I found.

PHP is embarrassing. It's so Broken, but trained amateurs praised it. PHP was doing some trivial fixes, but I chose to forget about it.

But I have to rid my system of this stuff, That's it, this is the last attempt.

To use a metaphor

I just casually complained to Mel, but she insisted that I publish it.

I can't even tell what's going on with PHP, because--it's okay. Think about it like you have a, um, toolbox. A bunch of tools. Seems okay, standard stuff.

You pull out the screw, it has three weird heads. OK, well, this is not very useful to you, but you guess it will be useful one day.

You take out the hammer and you are shocked. There are sharp claws on both sides. But it still works, I mean, you can hit it diagonally with the middle of both ends.

You take out the vise, but they don't have serrated surfaces. The surface is flat and smooth. It's not very useful, but it still works, no big deal.

You can keep going. The stuff in the toolbox is weird and iffy, but not worthless. Overall, there's not much wrong with it; it's The tools are all complete.

Now, imagine there are many carpenters using these tools, and they say to you: "What's the problem with these tools? We have all used them, and they all work well!". Craftsmen Show you the house they built, where every door is pentagonal and the roof collapses. You knock on the front door and it collapses inward, and they complain that you broke their door.

That’s the problem with PHP.

Standing

I think the following qualities are important to the productivity and usability of a language, and PHP is breaking it on a large scale them. If you don't agree with any of this, well, I can't imagine, we'll never agree.

>> A language has to be predictable. It's about reflecting human thoughts back to the computer The medium of execution, so the key to it is that the human understanding of the program must actually be correct.

>> The language must be consistent. Similar things must look similar, and different things are different. Learn the language With partial knowledge, you should be able to easily understand the rest.

>> The language must be concise. The new language should reduce the bad forms inherited from the old language. (We can also write machine code. ) New languages ​​should of course try to avoid weaving in new unique forms.

>> The language must be reliable. The language is a tool for solving problems; the introduction of new problems should be avoided as much as possible. Any "traps" will Lots of distractions.

>> The language must be debuggable. When something goes wrong, the programmer has to fix it, and we need to get the help we want.

i The position is:

>> PHP is full of surprises: mysql_real_escape_string, E_ACTUALLY_ALL

>> PHP is inconsistent: strpos, str_rot13

>> PHP Requires special form: error-checking around C API calls, ===

>> PHP weirdness: ==. for($foo as &$bar)

>> PHP is obscure: no stack traces or fatals by default, complex error reporting

I can’t explain why it is classified into these categories on a single question, otherwise it will be endless. I believe readers will think about it themselves.

Stop talking about this stuff with me

I know a lot of good arguments. I’ve also heard a lot of counter-arguments. These will just stop the conversation immediately. Don’t do it anymore Stop talking to me about this stuff, please. :(

>> Don't tell me "good developers can write good code in any language", or bad developers... La la la. This makes no sense. A good craftsman can use a stone or a hammer to drive a nail, but how many craftsmen have you seen using stone? One of the criteria for being a good developer is to be good at choosing tools.

>> Don't tell me it's the developer's job to memorize thousands of exceptions and quirks. Yes, this is necessary in any system because computers are stupid. This doesn't mean, the system can Crazy acceptance with no upper limit. PHP has only exceptions, which is not okay. Once you are wrestling with the language, you have to spend more effort to actually write the program. My tools do not have a positive effect on my application creation.

>> Don't tell me "that's how the C API works". What is the purpose of high level languages ​​on this planet, all they can provide are some string helper functions and a bunch of C wrappers If so, then use C! There is even a CGI library prepared for it.

>> Don’t give me the "you deserve it for doing weird things". If Two features exist, and one day, someone will find a reason to use them together. Again, this is not C; there is no specification here, and there is no need for "undefined behavior" here.

>> Don't get me started on the fact that Facebook and Wikipedia use PHP. I already knew it! They can also be written in Brainfuck, but as long as they are smart enough and keep tinkering with these things, they can always overcome the problems of the platform. As we all know, if you use other Language writing, development time could be cut in half or doubled; there is no point in pulling out these figures alone.

God forbid, don’t bullshit me about anything anymore! If the ones listed don’t hurt your PHP perspective , it doesn’t matter, so please stop having meaningless arguments on the Internet and continue to develop handsome and cool sites to prove me wrong:).

Tell you secretly: I like Python very much. I am also happy to Say things you don't want to hear about it, if you really want to. I'm not asking for it to be perfect; I just want to maximize its strengths and avoid its weaknesses and summarize the best things I want.

PHP

Language Core

CPAN is called "Perl's standard library". This does not say much about Perl's standard library, but it contains robust The idea that core can build powerful things.

Basic Principles

PHP was originally clearly designed for non-programmers (by implication, non-professional programs); Roots It's already hard to break away. Picked dialogue from the PHP 2.0 documentation:

Once you start distinguishing different operators for each type, you start to get complicated using the language. For example, you can't do strings for strings With '==', you now have to use 'eq'. I don't see this, especially with scripting languages ​​like PHP, most of which are quite simple and in most cases, as a non-programmer, just want a A language that contains a small amount of basic logic syntax, without incurring too much of a learning curve.

>> PHP does whatever it takes to keep moving forward. Anything is better than nothing.

>> ; This is not a correct design principle. Early PHP was influenced by Perl; a large number of standard libraries refer to C using "out" parameters; OO parts are designed like C++ and Java.

>> PHP is derived from other The language introduces a lot of inspiration, but is still difficult to understand for those familiar with other languages. (int) looks like C, but int does not exist. Namespaces are used. New array syntax uses [key => value] , unlike any other language that defines hash literals.

>> Weak typing (for example, silently automatically converting between strings/mumbers/etc.) is so complicated.

>> A small number of new features are implemented with new syntax; most work is done through functions or things that look like functions. In addition to class support, this of course requires new operators and keywords.

>> The problems listed on this page have official solutions - if you want to fund Zend to fix their open source programming language.

>> The road is long and the road is long. Consider the following code, picked out from somewhere in the PHP documentation.

<ol class="dp-c"><li class="alt"><span><span>@</span><span class="func">fopen</span><span>(</span><span class="string">'http://example.com/not-existing-file'</span><span>, </span><span class="string">'r'</span><span>); </span></span></li></ol>
Copy after login

What will it do?

>> If PHP is compiled with --disable-url-fopen-wrapper , it will not work. (The documentation doesn't say, what does "not work" mean; return null, throw an exception?)

>> Note that this has been removed in PHP 5.2.5.

>> Will not work if allow_url_fopen is disabled in php.ini. (Why? No way of knowing.)

>> Due to @ , non-existent file The warning will not be printed.

>> But if scream.enabled is set in php.ini, it will be printed again.

>> Or if scream is set manually with ini_set .enabled.

>> However, if the error_reporting level is not set, it is different.

>> If it is printed, the precise destination depends on display_errors, again in php .ini. or ini_set.

I can't tell you the behavior of this function call without looking at the compile-time flags, server-side configuration, and configuration in my program. These are all built-in behaviors.

>> The language is full of global and implicit state. mbstring uses global character encoding. func_get_arg and the like look like normal functions, but only operate on the currently executing function. Error/exception Processing is global by default. register_tick_function sets a global function to run for each tick (hook?) ---- What?!

>> does not have any thread support. (Not surprising, because it is already mentioned above given.) This, coupled with the lack of built-in fork (mentioned below), makes parallel programming extremely difficult.

>> Some parts of PHP will produce error code in practice.

>> json_decode returns null for incorrect input, although null is also a legal object for JSON decoding - this function is extremely unreliable unless you call json_last_error after each use.

>> 如果在位置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进制字符串(如, password hashes) 可能偶然会比较成 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] 是个语法错误. (已在 PHP 5.4 中修复)

>> 不像(从字面上看)任何其它语言都有的类似的操作符, ?: 是左结合的. 因此:

<ol class="dp-c">
<li class="alt"><span><span class="vars">$arg</span><span> = </span><span class="string">'T'</span><span>;  </span></span></li>
<li><span> </span></li>
<li class="alt">
<span class="vars">$vehicle</span><span> = ( ( </span><span class="vars">$arg</span><span> == </span><span class="string">'B'</span><span> ) ? </span><span class="string">'bus'</span><span> :  </span>
</li>
<li class="alt">
<span>             ( </span><span class="vars">$arg</span><span> == </span><span class="string">'A'</span><span> ) ? </span><span class="string">'airplane'</span><span> :  </span>
</li>
<li class="alt">
<span>             ( </span><span class="vars">$arg</span><span> == </span><span class="string">'T'</span><span> ) ? </span><span class="string">'train'</span><span> :  </span>
</li>
<li class="alt">
<span>             ( </span><span class="vars">$arg</span><span> == </span><span class="string">'C'</span><span> ) ? </span><span class="string">'car'</span><span> :  </span>
</li>
<li class="alt">
<span>             ( </span><span class="vars">$arg</span><span> == </span><span class="string">'H'</span><span> ) ? </span><span class="string">'horse'</span><span> :  </span>
</li>
<li class="alt">
<span>             </span><span class="string">'feet'</span><span> );  </span>
</li>
<li class="alt">
<span class="func">echo</span><span> </span><span class="vars">$vehicle</span><span>; </span>
</li>
</ol>
Copy after login

打印 horse.

变量

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

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

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

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

>> "Reference" makes variables unique in the language. PHP is dynamically typed, so variables are usually untyped... except for references, which modify function definitions, variable syntax, and assignments. Once a variable is Reference (can happen anywhere), it's always a reference. There's no obvious way to detect the value of a variable required for dereferencing.

>> Okay, I lied. Some "SPL types" also Acting on variables: $x = new SplBool(true); $x = "foo"; will fail. This is a bit like static typing, see for yourself.

>> 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.

>> A constant defined through a function is called Before taking a string; , they didn't exist. (This may actually be copying Perl's behavior with constants.)

>> Variable names are case-sensitive. Function and class names are not. Such that It would be weird to use camelCase naming for methods.

structs

>> array() and several similar structures are not functions. $func = "array" ; $func(); does not work.

>> Array unpacking can be done using list($a,$b) = .... The operation is completed. list() is a function-like syntax, like Arrays like that. I don't know why there isn't a real dedicated syntax, and I don't know why the names are so confusing.

>> (int) is obviously designed to be like C, but It's not a separate token; there's nothing called int in the language. Try this: var_dump(int) doesn't work, it throws a parsing error because the argument looks like a cast operator.

>> (integer) is an alias of (int). There are also (bool)/(boolean) and (float)/(double)/(real).

>> There is ( The array) operator is used to convert to an array and (object) is used to convert to an object. This sounds very thoughtful, but there is often a use case: you can use (array) to make a function parameter either a single element or an Can be a list, treated the same. But this is unreliable, because if someone passes a single object, converting it to an array will actually produce an array containing the object's properties. (Converting to an object performs the inversion operation.)

>> Functions like include() are basically C's #include: they dump the source code of other files into your file. There is no module system, not even for PHP code.

>> There are no functions or classes like nested or local scope. They are all global. include a file, and its variables are imported into the current function scope (giving the file access to your variables capability), but functions and classes are stored in the global scope.

>> To append an array, use $foo[] = $bar.

>> echo is not a function.

>> empty($var) is so extreme that it does not behave as a function for anything else, except variables, e.g. empty($var || $var2), is a parsing error. Why on Earth is this Things, why does the parser need to know empty?

>> There are also some redundant syntax blocks: if (...): ... endif;, etc.

Error handling

>> A unique operator of PHP is @ (actually borrowed from DOS), which hides errors.

>> PHP Errors do not provide stack traces. You have to install a handler to generate them. (But not fatal errors -- see below.)

>> PHP's parsing errors usually only throw the parsing status, not the parsing status.

>> PHP's parser refers to eg. :: internally as T_PAAMAYIM_NEKUDOTAYIM, and the << operator as T_SL. I say "internally" , but as mentioned above, the :: or << displayed to the programmer appears in the wrong position.

>> Most error handling prints a line of error log to the server log, not People see it and keep doing it.

>> E_STRICT looks like that, but it actually doesn’t have much protection, and there is no documentation to show what it actually does.

>> E_ALL contains all error classes -- except E_STRICT.

>> is weird and inconsistent about what is allowed and what is not. I don't know how E_STRICT applies here, But these are correct:

>> Trying to access a non-existent object property, such as, $foo->x. (warning)

>> Use variables to do It is a function name, variable name, or class name. (silent)

>> Trying to use an undefined constant. (notice)

>> Trying to access a non-object type Property.(notice)

>> Attempt to use non-existent variable name.(notice)

>> 2 < "foo" (hidden)

>> foreach (2 as $foo); (warning)

But the following will not work:

>> Trying to access non-existent class constants, such as $foo:: x. (fatal error)

>> Using a string constant as a function name, variable name, or class name. (parse error)

>> Trying to call an example Define function. (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 ?

函数

>> 函数调用似乎相当昂贵.

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

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

>> 函数参数可以具有 "类型提示", 基本上只是静态类型. 你不能要求某个参数是 int 或是 string 或是 对象 或其它 "核心" 类型, 即使每个内建函数使用这种类型, 可能因为 int 在PHP中不是个东西吧. (查看上面关于 (int) 的讨论). 你也不能使用特殊的被大量内建函数使用的伪类型装饰: mixed, number, or callback.

>> 因此, 下面:

<ol class="dp-c">
<li class="alt"><span><span class="keyword">function</span><span> foo(string </span><span class="vars">$s</span><span>) {}  </span></span></li>
<li>
<span>foo(</span><span class="string">"hello world"</span><span>); </span>
</li>
</ol>
Copy after login

产生错误 the error:

PHP Catchable fatal error: Argument 1 passed to foo() must be an instance of string, string given, called in...

>> 你可能会注意到 "类型提示" 实际上并不存在; 在程序中没有 string 类. 如果你试图使用 ReflectionParameter::getClass() 动态测试类型提示, 將会得到类型不存在, 使得实际上不可能取得该类型名.

>> 函数的返回值不能被推断

>> 將当前函数的参数传给另一个函数 (分派, 不罕见) 通过 call_user_func_array('other_function', func_get_args())完成. 但 func_get_args 在运行时抛出一个 fatal 错误, 抱怨它不能作为函数参数. 为什么为什么这是个类型错误? ( 已在 PHP 5.3 中修复)

>> 闭包需要显示的命名每个变量为 closed-over. 为什么解析器不想办法解决? (Okay, it’s because using a variable ever, at all, creates it unless explicitly told otherwise.)

>> Closed-over 变量, 通过和其它函数参数相同的语义"传递". 这样的话, 数组和字符串等等, 將以传值方式传给闭包. 除非使用 &.

>> 因为闭包变量会自动传递参数, 没有嵌套范围, 闭包不能指向私有方法, 不管是否定义在类中. ( 可能在 5.4 中修复? 不清楚.)

>> 函数没有命名参数. 实际上被 devs 显示拒绝, 因为它 "会导致代码臭味".

>> Function arguments with defaults can appear before function arguments without, even though the documentation points out that this is both weird and useless. (So why allow it?)

>> 向函数传递额外的参数会被忽略 (除了内建函数, 会抛出异常). 丢失的参数被假定为 null.

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

OO

>> The functional part of PHP is designed to be like C, but the object-oriented (ho ho) is designed to be like Java. I don’t want to overemphasize how jarring this is. I have yet to find a global with capital letters Functions, important built-in classes are named in camelCase, and have Java-style property accessors like getFoo. This is a dynamic language, right? Perl, Python, and Ruby all have some concept of accessing "properties" through code ; PHP only has cumbersome __get and the like. The type system is designed around the low-level Java language. Java and PHP's are in the same era. Java deliberately made more restrictions and copied Java. I can't understand it.

>> Classes are not objects. Metaprogramming has to point to them by string names, just like functions.

>> Built-in types are not objects, (unlike Perl ) cannot make it look like an object.

>> instanceof is an operator, although it was added very late, and most languages ​​​​have built in specialized functions and syntax. Is it influenced by Java? Class Not the first class? (I don't know if they are.)

>> But there is an is_a function. It has an optional parameter that specifies whether to allow the object to actually be a string-named class.

>> get_class is a function; there is no typeof operator. There is also is_subclass_of.

>> However, this does not work for built-in types, (again, int is not a thing ). In this case, you need is_int and so on.

>> The rvalue must be a variable or literal; it cannot be an expression. Otherwise it will cause... a parsing error.

>> clone is an operator?!

>> The design of OO is a monster that mixes Perl and Java.

>> Object properties are passed through $obj- >foo, but the class attribute is $obj::foo. I haven't seen any other language do this, or how it is useful.

>> However, instance methods can still be passed statically (Class::method) call. If called from other methods, it will be regarded as a regular method call on the current $this. I think.

>> new, private, public, protected, static, etc. Trying to win over Java developers? I know it's more of a personal taste thing, but I don't know why these things are necessary in a dynamic language -- in C++, of them Most of them are related to naming resolution at assembly and compile time.

>> Subclasses cannot override private methods. Public methods covered by subclasses are also not visible and can be called separately, private methods of the superclass. There will be Problems, such as when testing mocks objects. The

>> method cannot be named, such as "list", because list() is a special syntax (not a function) and the parser will be confused. . The reason for this ambiguity is unknown, and the class works just fine. ($foo->list() is not a syntax error.)

>> if thrown when parsing constructor arguments Exception (e.g., new Foo(bar()) and bar() throws), the constructor will not be called, but the destructor will. (Fixed in PHP 5.3)

>> Exceptions in __autoload and parsing functions will cause fatal errors.

>> There is no constructor or destructor. __construct is an initialization function, like Python's __init__. Memory cannot be allocated by calling the class and Create an object.

>> There is no default initialization function. When calling parent::__construct(), if the parent class does not define its own __construct method, a fatal error will occur.

>> OO brings an iterator interface, which is part of the language specification (such as... as...), but this interface does not actually have a built-in implementation (such as an array). If you want an array For iterators, you must wrap it with an ArrayIterator. There is no built-in way for an iterator to work as a first-class object.

>> classes can override the way they convert to strings, But you cannot overload how to convert to a number or any other built-in type.

>> Strings, numbers, and arrays all have string conversion methods; the language depends heavily on this. Functions and Classes They are all strings. However, if __toString is not defined, trying to convert a built-in or custom object (or even a closure) into a string will cause errors, and even echo may go wrong.

>> Equality or comparison operations cannot be overloaded.

>> Static variables in instance methods are global; their values ​​are shared across multiple instances of the class.

Standard Library

Perl "some requires assembly". Python is "batteries included". PHP is "the kitchen sink, it comes from Canada, but all the faucets are branded in C".

General

>> There is no type system. You can compile PHP, but you must specify what to load through php.ini, the option exists for the extension section (will Their contents are injected into the global namespace) or do not exist.

>> Since namespaces are a recent feature, the standard library has not been disrupted at all. There are thousands of them in the global namespace functions.

>> Some parts of the library are very inconsistent.

>> Underline vs. no underline: strpos/str_rot13, php_uname/phpversion, base64_encode/urlencode, gettype/ get_class

>> "to" to 2: ascii2ebcdic, bin2hex, deg2rad, strtolower, strtotime

>> Object+verb to verb+object: base64_decode, str_shuffle, var_dump versus create_function, recode_string

>> Parameter order: array_filter($input, $callback) versus array_map($callback, $input), strpos($haystack, $needle) versus array_search($needle, $haystack)

>> Prefix confusion: usleep vs microtime

>> Case insensitive functions vary on where the i goes in the name.

>> About half of the array Functions start with array_. The rest is not.

>> the kitchen sink. Libraries include:

>> binds ImageMagick, binds GraphicsMagick (a derivative of ImageMagick), and a few Several functions can detect EXIF ​​data (ImageMagick can already do this)

>> Functions that parse bbcode, some very special tags, are used by a few forum packages.

>> Too many XML packages. DOM (OO), DOM XML (not), libxml, SimpleXML, “XML Parser”, XMLReader/XMLWriter, and a bunch of things I can’t recognize are omitted. Of course There will be some differences, you are free to figure out the difference.

>> is bound to two special credit card processors, SPPLUS and MCVE. What?

>> ; Three ways to access the MySQL database: mysql, mysqli, and PDO abstraction.

C affects

It needs to have its own symbols. PHP is a A high-level, dynamically typed language. And then a lot of the standard library is still just a thin wrapper around the C APIs, with things like: "Out" parameters, even though PHP can return ad-hoc hashes or returns multiple parameters effortlessly.

>> At least a dozen functions are designed to get the last error in a subsystem (see below), although PHP has stored exceptions The processing function is 8 years old.

>> There is a mysql_real_escape_string, although there is already a mysql_escape_string with the same parameters, just because it is part of the MySQL C API.

>> Global behavior is non-global (like MySQL). Using multiple MySQL connections requires explicitly passing the connection handle to each function call.

>> wrappers are really, really, really nice Thin. For example, calling dba_nextkey without calling dba_firstkey will cause a segfault.

>> There are a bunch of ctype_* functions (such as ctype_alnum) that map C character functions with similar names, rather than, for example, isupper.

Genericism

If a function does two slightly different things, PHP creates two functions.

How do you sort in reverse order ? In Perl, you can use { $b <=> $a}. In Python, you might use .sort(reverse = True). In PHP, there is a special function called rsort().

>> Those functions that look like C error: curl_error, json_last_error, openssl_error_string, imap_errors, mysql_error, xml_get_error_code, bzerror, date_get_last_errors, are there any others?

>> Sorting functions: array_multisort, arsort, asort, ksort, krsort, natsort, natcasesort, sort, rsort, uasort, uksort, usort

>> Text retrieval functions: ereg, eregi, mb_ereg, mb_eregi, preg_match, strstr, strchr, stristr, strrchr, strpos, stripos, strrpos, strripos, mb_strpos, mb_strrpos, plus the variations that do replacements

>> has a large number of aliases: strstr/strchr, is_int/is_integer/is_long , is_float/is_double, pos/current, sizeof/count, chop/rtrim, implode/join, die/exit, trigger_error/user_error…

>> scandir returns a list of files in the currently given directory. Instead of (potentially beneficially) returning the files in the order they are returned, the function returns a sorted list of files. There is an optional parameter that returns the files in reverse alphabetical order. These are obviously not sufficient for sorting.

> ;> str_split splits the string into equal-length chunks. chunk_split splits the string into equal-length chunks and then connects them with a delimiter.

>> Reading compressed files requires a separate set of functions, depending on the format. There are six sets of functions, and their APIs are all different, such as bzip2, LZF, phar, rar, zip, and gzip/zlib

>> Because calling a function using a parameter array is So awkward (call_user_func_array), so there are companions like printf/vprintf and sprintf/vsprintf. They do the same thing, but one takes multiple parameters and the other takes an array of parameters.

Text

>> preg_replace with /e (eval) flag will replace the matching part with the string to be replaced, and then eval it.

>> Design of strtok Apparently equivalent to a C function, which has been considered a bad idea for many reasons. PHP can easily return an array (which is awkward in C), and there are many hacks in strtok(3) usage (modifying a string somewhere ), cannot be used here.

>> parse_str parses the query string, no indication of which from the function name. Instead it register_globals and dumps the query string into a local scope variable, unless you pass an array to fill it in. (Of course, what Also does not return)

>> explode will refuse to split when encountering a null delimiter. Every other string splitting implementation taking this approach should mean that the string should be split into characters ; PHP has a split function, confusingly called str_split but described as "convert a string into an array".

>> For formatting dates, there is strftime, which is handled natively like the C API The locale is the same. Of course there is also date, which has a completely different syntax and is only used in English.

>> "gzgetss -- Get the line pointer of the gz file and remove the HTML tag." Know this series of functions The concept, let me die.

>> mbstring

>> are all about "multi-byte", solving the character set problem.

>> Still handles ordinary strings. There is a single global "default" character set. Some functions allow specifying the character set, but it depends on all parameters and return values.

> ;> ereg_* functions are provided, but these are deprecated. preg_* Fortunately, with some PCRE-specific tags, they understand UTF-8.

System and Reflection

>> There are a bunch of functions, focused on text and variables. Compression and extraction are just the tip of the iceberg.

>> There are several ways to make PHP dynamic, here are a few See no obvious difference or relative benefit. Class tools cannot modify custom classes; runtime tools replace it and can modify anything custom; Reflection* classes can reflect most things in the language; there are many unique functions that are To report properties of functions and classes. Are these subsystems independent, related, redundant?

>> get_class($obj) returns the class name of the object. get_class() returns the function in the called function name of the class. Aside from that, the same function does completely different things: get_class(null)... behaves like the latter. So you can't trust it with a random variable. Surprise!

>> The stream_* classes allow the implementation of custom stream objects for use with fopen and other built-in things like file handling. For several internal reasons, "notification" cannot be implemented.

>> register_tick_function can accept closure objects. unregister_tick_function cannot; instead, it will throw an error complaining that the closure cannot be converted to a string.

>> php_uname tells you about the current operating system stuff.

>> fork and exec are not built-ins. They come from the pcntl extension, but are not included by default. popen does not provide pid files.

>> session_decode is used for reading Takes an arbitrary PHP session string, but only works if there is an active session. It dumps the result into $_SESSION instead of returning its value.

Miscellaneous

>> curl_multi_exec does not change curl_error when an error occurs, but it changes curl_error.

>> The parameters of mktime are in order: hour, minute, second, month, day , year

Data Manipulation

Programs are nothing but chewing and spitting out data. A large number of languages ​​are designed around data manipulation, from awk to Prolog to C. If a language can't manipulate data, it can't do anything.

Numbers

>> Integers are signed 32-bit numbers on 32-bit platforms. No Like its contemporaries in PHP, there is no automatic bigint promotion. So your math operations may result in different results due to CPU architecture. Your only way to select big integers is to use the GMP or BC wrapper function. (The developer may have built in New, separate, 64-bit type. This is crazy.)

>> PHP supports octal number syntax, starting with 0, so 012 is 10. However, 08 becomes 0. 8 (or 9) and any following numbers disappear. 01c is a syntax error.

>> pi is a function. Or there is a constant, M_PI.

>> No power operator, only pow function.

Text

>> No Unicode support. Only ASCII work is reliable, really. There is an mbstring extension , mentioned above, but will be slightly hit.

>> This means that using the built-in string functions to process UTF-8 text will be risky.

>> Similarly, outside of ASCII, there is no concept of case comparison. Although there are extended versions of case-sensitive functions, they do not consider é to be equal to É.

>> You cannot Interpolating keys, e.g., "$foo['key']" is a syntax error. You also cannot unquote it (which will generate a warning everywhere!), or use ${...}/{$... }

>> "${foo[0]}" is correct. "${foo[0][0]}" is a syntax error. Bad copy of Perl-like syntax (two Fundamentally different language)?

Array

Ugh, Sao Nian.

>> 这家伙扮演list数据类型, 操作hash, 和排序set, 解析 list, 偶尔会有些奇怪的组合. 它是怎样执行的? 以何种方式使用内存? 谁知道? 不喜欢, 反正我还有其它的选择.

>> => 不是操作符. 它是个特别的结构, 仅仅存在于 array(...) 和 foreach 结构中.

>> 负值索引不工作, 尽管 -1 也是个和0一样的合法键值.

>> 尽管这是语言级的数据结构, 但没有简短语法; array(...)是简短语法. (PHP 5.4 带来了"literals", [...].)

>> => 结构是基于 Perl , Perl允许 foo => 1 而不用引号. 在PHP中, 你这么做会得到警告; 没有无需引号创建 hash 字符串键值的方式.

>> 数组处理函数常常让人迷惑或有不确定行为, 因为它们不得不对 lists, hashes, 或可能两者的结合体做运算. 考虑 array 分组, "计算arrays的不同部分".

<ol class="dp-c">
<li class="alt"><span><span class="vars">$first</span><span>  = </span><span class="keyword">array</span><span>(</span><span class="string">"foo"</span><span> => 123, </span><span class="string">"bar"</span><span> => 456);  </span></span></li>
<li>
<span class="vars">$second</span><span> = </span><span class="keyword">array</span><span>(</span><span class="string">"foo"</span><span> => 456, </span><span class="string">"bar"</span><span> => 123);  </span>
</li>
<li class="alt">
<span class="func">echo</span><span> var_dump(</span><span class="func">array_diff</span><span>(</span><span class="vars">$first</span><span>, </span><span class="vars">$second</span><span>));  </span>
</li>
</ol>
Copy after login

这段代码將做什么? 如果 array_diff 將参数以 hashes 看待, 它们明显是不同的; 相同的keys有不同的值. 如果以list看待, 它们仍然是不同的; 值的顺序不同.

事实上 array_diff 认为它们相等, 因为它以 sets 对待: 仅仅比较值, 忽略顺序.

>> 同样, array_rand 随机选择keys时, 也有奇怪的行为, 这对大多数需要从列表中挑出东西的用例没什么帮助.

尽管大量PHP代码依赖key的顺序:

<ol class="dp-c">
<li class="alt"><span><span class="keyword">array</span><span>(</span><span class="string">"foo"</span><span>, </span><span class="string">"bar"</span><span>) != </span><span class="keyword">array</span><span>(</span><span class="string">"bar"</span><span>, </span><span class="string">"foo"</span><span>)  </span></span></li>
<li><span> </span></li>
<li class="alt">
<span class="keyword">array</span><span>(</span><span class="string">"foo"</span><span> => 1, </span><span class="string">"bar"</span><span> => 2) == </span><span class="keyword">array</span><span>(</span><span class="string">"bar"</span><span> => 2, </span><span class="string">"foo"</span><span> => 1) </span>
</li>
</ol>
Copy after login

>> 如果两个数组混合的话, 会发生什么? 我留给读者自己弄清楚. (我不知道)

>> array_fill 不能创建0长度的数组; 相反它会发出警告并返回 false.

>> 所有的(很多的...) 排序函数就地操作而什么都不返回. 想新建一个已排序数组的拷贝, 没门; 你不得不自己拷贝数组, 然后排序, 然后再使用数组.

>> 但 array_reverse 返回一个新数组.

>> 一堆被排序的东西和一些键值对听起来像是个某种强大的处理函数参数的方式, 但, 没门.

非数组

>> 标准库包含 "快速哈希", "特定的强类型"的hash结构OO实现. 然, 深入它, 有4类, 每种处理不同的键值对类型组合. 不清楚为什么内建的数组实现不能优化这些极其普通情况, 也不清楚它相对的性能怎样.

>> 有个 ArrayObject 类 (实现了4个不同的接口) , 它包装数组让它看起来像对象. 自定义类可以实现同样的接口. 但只有限的几个方法, 其中有一半不像内建的数组函数, 而内建的数组函数不知道怎样对ArrayObject或其它的类数组的类型操作.

函数

>> 函数不是数据. 闭包实际上是对象, 但普通的函数不是. 你甚至不能通过它们裸名称引用它们; var_dump(strstr) 会发出警告并猜测你的意思是字符串字面量, "strstr". 想辨别出字符串还是"函数"引用, 没门.

>> create_function 基本上是个 eval 的包装者. 它用普通的名字创建函数并在全局范围安装它(因此永远不会被垃圾回收---不要在循环中使用!). 它实际上对当前上下文一无所知, 因为它不是闭包. 名字包含一个 NUL 字节, 因此永远不会与普通函数冲突 (因为如果在文件的任何地方有 NUL的话, PHP 的解析器会失败).

>> Declaring a function named __lambda_func will break create_function—the actual implementation is to eval-create the function named __lambda_func, then internally rename it to the broken name. If __lambda_func already exists, the first part will throw a fatal error.

其它

>> 对 NULL 使用 (++) 生成 1. 对 NULL 用 (--) 生成 NULL.

>> 没有生成器.

Web 框架

执行环境

>> 一个单一共享文件 php.ini, 控制了 PHP 的大部分功能并织入了复杂的针对覆盖什么与何时覆盖的规则. PHP软件能部署在任意的机器上, 因此必须覆盖一些设置使环境正常, 这在很大程序上会违背像 php.ini 这样的机制的使用.

>> PHP基本上以CGI运行. 每次页面被点击, PHP 在执行前, 重编译整个环境. 就连 Python 的玩具框架的开发环境都不会这样.

>> 这就导致了整个 "PHP 加速器" 市场的形成, 仅仅编译一次, 就能加速PHP, 就像其它的语言一样. Zend, PHP的幕后公司, 將这个做为它们的商业模式.

>> For a long time, PHP errors were output to the client by default - I guess to help in the development environment. I don't think this is true, but I still see the occasional mysql error appearing in The top of the page.

>> The whitespace outside the tags, even in libraries, is treated by PHP as text and parsed into the response (or causes "headers already sent" " error). A popular approach is to ignore the ?> closing tag.

Deployment

The deployment method is often cited as the most advanced part of PHP: direct deployment of files That's it. Yes, it's easier than Python or Rury or Perl which require launching the whole process. But PHP leaves a lot to be desired.

I'd love to run web applications as application servers programs and reverse proxy them. This has the lowest cost and many benefits: you can manage servers and applications separately, and you can run multiple or a small number of application processes according to the number of machines, without the need for multiple web servers. You can run the application with a different user, you can choose the web server, you can tear down the application without disturbing the web server, you can deploy the application seamlessly, etc. Welding the application directly to the web server is ridiculous and there is nothing good about it Reasons why you should do this.

>> Every PHP application uses php.ini. But there is only one php.ini file, and it is global; if you are on a shared server, you need Modify it, or if you run two applications that require different settings, you're out of luck; you'll have to request all the necessary settings from the organization and put them in the application, such as using ini_set or in an Apache configuration file or in .htaccess Setting. If you can do it. Maybe wow, you have a lot of places to check to figure out how to get the value that has been set.

>> Similarly, there is no way to "isolate" a PHP application Easy, it depends on other parts of the system. Want to run two applications, want different library versions, or different PHP versions themselves? Start building another copy of Apache.

>> The "bunch of files" approach, in addition to making routing look like a sickly dumb ass, also means that you have to be careful with whitelisting or blacklisting to control what is accessible, because your URL hierarchy is your The hierarchy of the code tree. Configuration files and other "local modules" need to be guarded with something like C to avoid direct loading. Files in the version control system (such as .svn) need to be protected. Use mod_php to make everything in the file system is a potential entry point; with an application server, there is only one entry point, and the calling is controlled only by the URL.

>> You can't seamlessly upgrade a bunch of files running in CGI-style unless You want your application to crash and exhibit undefined behavior when users click on your site between upgrades.

>> Although configuring Apache to run PHP is "simple", there are still some pitfalls. The PHP documentation recommends using SetHandler to make the .php file run in PHP mode. AddHandler seems to run fine, but in fact there will be problems.

When you use AddHandler, you are telling Apache to "execute it as php", This is one possible way to handle .php files. But! Apache does not think of file extensions that way. It is designed to support files such as, index.html.en. With Apache, the file can have any number of files at the same time extension.

Assuming, you have a file upload form that stores some files in a public directory. To make sure no one can upload PHP files, you just check that the files cannot have a .php extension. All attacks All you need to do is upload a file named foo.php.txt; your upload tool won't see the problem, Apache will think it's PHP, and it will happily execute it.

This is not "use raw" filename" or "no better validation"; the problem is that your web server has to be configured to run any old code that makes PHP "easy to deploy". This is not a theoretical problem; I've found that a lot in practice site has similar issues.

Missing Features

I think all of these are centered around building a web application. Looks reasonable for PHP , is one of its selling points. It is a "Web language" and should have them.

>> No module system. PHP is a template.

>> No XSS Filter. htmlspecialchars is not an XSS filter.

>> No CSRF protection. You have to do it yourself.

>> No common standard database API. Things like PDO You have to wrap the API of each specific database and abstract different parts separately.

>> No routing system. Your site structure is your file system structure.

>> No authentication or authorization.

>> No development server.

>> No interactive debugging mode.

>> No consistent deployment mechanism; Just "copy all files to the server".

Safety

Language Boundaries

PHP's poor security may be amplified because it takes data out of one language and dumps it into another. This is a bad idea. "

Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template