Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to comprehensively analyze the bad design of PHP

2025-01-16 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

How to comprehensively analyze the bad design of PHP, many novices are not very clear about this, in order to help you solve this problem, the following editor will explain in detail for you, people with this need can come to learn, I hope you can gain something.

PHP is not only awkward to use, but also either what I want is not suitable, or it is not the most satisfactory, or it goes against my beliefs. I can tell you about a language, all the good ways I want to avoid, all the bad ways I like. Come on, ask! The conversation will be fun!

Php is the only exception. Almost everything abstracted by php is fragmented. Including the language, the framework, the whole ecosystem is a mess. I can hardly list the curses separately because it's broken all over. Every time I try to edit a messy list of php complaints, I am disturbed by trifles, and the deeper I go, the more shocking I discover.

Php is embarrassing. It is so broken, but those trained amateurs praise it. Php is doing some trivial remedial measures, but I choose to forget it.

But I have to get my system out of these things, and that's it, this is my last attempt.

Make an analogy

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

I can't even tell what happened to PHP, because-- it's okay. Think you have a, uh, toolbox. A pile of tools. It looks fine. There is something standard.

When you pull out the screw, it has three weird heads. OK, well, it's not very useful to you, but you guess it will work sooner or later.

You took out your hammer and were shocked, with sharp claws on both sides. But it still works. I mean, you can hit it diagonally in the middle of both ends.

You take out pliers, but they have no zigzag surfaces. The surface is flat and smooth. It's not of much use, but it still works. It's nothing.

You can go on. The things in the toolbox are weird and uncertain, but they are not worthless. There is no big problem as a whole; it has a full range of tools.

Now, imagine a lot of carpenters who use these tools, and they say to you, "what's wrong with these tools? we've all used it. They all work well." The craftsmen show you the house they built, each door is pentagonal and the roof is collapsed. You knock on the front door and it falls in, and they complain that you broke their door.

This is the problem with PHP.

Standpoint

I think the following characteristics are important for the productivity and usability of a language, and PHP destroys them on a large scale. If you don't agree with this, well, I can't imagine that we'll never agree.

A language must be predictable. It is the medium that reflects human thoughts to computer execution, so its key is that human understanding of programs should be correct.

The language must be consistent. Similar things should look similar, but different things are different. After learning part of the language, you should be able to understand the rest easily.

The language must be concise. The new language should reduce the bad forms of inheriting the old language. We can also write machine codes. New languages should, of course, try to avoid weaving into new and unique forms.

The language must be reliable. Language is a tool for solving problems; new problems should be avoided as far as possible. Any "trap" will be a great distraction.

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

My position is:

PHP is full of surprises everywhere: mysql_real_escape_string, E_ACTUALLY_ALL

> > PHP inconsistency: strpos, str_rot13

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

> > PHP eccentric: =. For ($foo as & $bar)

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

I can't explain why it falls into these categories on a single question, otherwise it will go on forever. I believe readers can think for themselves.

Don't talk to me about this stuff anymore.

I know a lot of favorable arguments. I have also heard a lot of rebuttal arguments. All this can only stop the conversation immediately. Stop talking to me about these things, I'm begging you. : (

Don't tell me that good developers can write good code in any language, or bad developers. Bar, bar, bar. It makes no sense. A good craftsman can drive a nail with a stone or a hammer, but how many craftsmen have you seen with 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 eccentricities. Yes, this is necessary in any system, because computers are stupid. This does not mean that the system can accept it crazily without an upper limit. There are only exceptions in PHP, which will not work. Once you wrestle with the language, it takes more effort to actually write the program. My tools don't play a positive role in creating applications for me.

Don't tell me, "that's how C API works." What is the purpose of the existence of high-level languages on this planet? all they can provide is some string helper functions and a bunch of C wrappers? If that's the case, use C! Here, there is even a CGI library for it.

Don't talk to me about making strange things. You deserve it. If there are two features, one day someone will find a reason to use them together. Again, this is not C; there is no specification, there is no need for undefined behavior.

Don't talk to me about the PHP that Facebook and Wikipedia use. That's no news to me! They can also be written in Brainfuck, but as long as they are wise enough to keep messing around with these things, they can always overcome platform problems. It is well known that development time may be halved or doubled if written in other languages; there is no point in taking out the data alone.

God bless you, don't talk to me about anything! If the list doesn't hurt your PHP, it doesn't matter, so please stop making pointless arguments online and continue to develop handsome and cool sites to prove me wrong.

To tell you secretly: I like Python very much. And I'd be happy to say something you don't like to hear about it, if you really want to. I don't want it to be perfect; I just want to build on my strengths and circumvent my weaknesses and sum up the best things I want.

PHP

Language core

CPAN is called "the standard library of Perl". This doesn't say much about Perl's standard library, but it contains the idea that a robust core can build powerful things.

basic principle

PHP was originally clearly designed for non-programmers (implication, non-professional programs); the roots are hard to get rid of. Selected conversations from PHP 2.0 documents:

Once you start to distinguish different operators for each type, you start to use the language more complicated. For example, you can't use'= 'for strings, you must use' eq'. 'now I don't see this, especially scripting languages like PHP, which are mostly fairly simple and in most cases, as non-programmers, only want a language that contains a few basic logical grammars and don't want to put too much effort into the learning curve.

PHP will do whatever it takes to keep moving forward. Everything 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 the "out" parameter; OO parts are designed like C++ and Java.

PHP draws a lot of inspiration from other languages, but it is still difficult for those who are familiar with other languages. (int) looks like C, but int doesn't exist. Namespaces use\. The new array syntax uses [key = > value], unlike any other language that defines hash literals.

Weak typing (for example, silent automatic conversion between strings/mumbers/, etc.) is so complex.

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

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

There is a long way to go, but it is far away. Think about the following code, picked from somewhere in the PHP document.

@ fopen ('http://example.com/not-existing-file', 'r')

What will it do?

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

Note that this has been removed in PHP 5.2.5.

If allow_url_fopen is disabled in php.ini, it will not work either. (why? There is no way to know.)

Due to @, non-existent file's warning will not be printed.

But if scream.enabled is set in php.ini, it will print again.

Or if you use ini_set to set scream.enabled manually.

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

If it is printed out, the exact direction depends on display_errors, once again in php.ini. Or in ini_set.

I can't tell you the behavior of this function call without looking at the compile-time flag, server-side configuration, and the configuration in my program. These are all the actions of the Internal Construction Bank.

The language is full of global and hidden states. Mbstring uses global character encoding. Functions such as func_get_arg look like normal functions, but only operate on functions that are currently being executed. Error/exception processing is global by default. Register_tick_function sets up a global function to run each tick (hook?)-what?!

> > there is no thread support. (not surprising, because it has been given above.) Coupled with the lack of built-in fork (mentioned below), parallel programming is extremely difficult.

Some parts of PHP will generate error codes 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 every time you use it.

> > if found at position 0, array_search, strpos, and other similar functions return 0, but if none are found. Will return false

Let's expand the last part a little bit.

In C, functions such as strpos return-1 if not found. If you do not check this situation, but try to use it below, it will probably hit junk memory and the program will crash. Maybe, this is C. Who knows the mud horse? I'm sure there are at least tools to deal with it.

In Python, the equivalent .index method throws an exception if the element is not found. If you do not check the situation, the program will crash.

In PHP, this function returns false. If you use FALSE as a subscript, or do something else with it, PHP will silently turn it to 0, except for = comparison. The program will not crash; it will execute the wrong logic without any warning unless you remember to include the correct template handling code in every place that uses strpos and other similar functions.

This is terrible! Programming languages are just tools; they serve me. Here, PHP set me a trap waiting for me to jump in, and I had to be wary of boring string manipulation and equality comparisons. PHP is a minefield.

I've heard a lot of stories about PHP parsers, whose developers come from all over the world. There are people who work on PHP core development, debug PHP core, and communicate with core developers. None of the stories are appreciated.

So I have to insert a sentence here, because it's worth repeating: PHP is a community of amateurs. Very few people design, work for it, or know what they are doing. Oh, dear reader, of course you are a great exception! Those who grow up and want to switch to other platforms bring down the average of the whole community. This, right here, is the biggest problem with PHP: absolutely blind leadership.

All right, come back and face it.

Operator

= = useless.

> "foo" = = TRUE, and "foo" = = 0. But, of course, TRUE! = 0.

> > = = will convert both sides into numbers, which means it will be converted to floats if possible. So large hexadecimal strings (for example, password hashes) may occasionally be compared to true, even though they are different. Even JavaScript wouldn't do that.

For some reason, "6" = "6", "4.2" = "4.20", and "133" = =" 0133 ". But note that 133! = 0133, because 0133 is octal.

Compare values and types. Except for the object, only both sides are actually the same object is true! For objects, compare values (or each attribute) and type, which in turn compares the behavior of any non-object type. Is it fun?

It is not much better to compare the size.

Even the behavior is inconsistent: NULL

< -1, 而 NULL == 0. 排序也因此不确定; 它依赖于在排序中比较元素的算法的顺序. >

The comparison operator tries to sort the array in two different ways: first by length, then by element. If they have the same number of elements but different keys, they are incomparable.

Object comparisons do more than other comparisons. Except for those objects that are neither smaller nor greater than.

For type-safe comparisons, we have. For a more secure type

< 比较, 我们有... 什么也没有. "123" < "0124", 通常, 不管你怎么做. 类型转换也无济于事. >

Although the above action is crazy, it explicitly rejects the string paris and arithmetic operator of Perl's. PHP does not overload +. + is the usual +, and. Is the usual connector.

> > [] the subscript operator can also be spelled {}.

> > [] can be used for any variable, not just strings and arrays. It returns null without error warning.

> > [] can only get a single element.

> > foo () [0] is a syntax error. (fixed in PHP 5.4)

Unlike (literally) similar operators in any other language,?: is left-associative. Therefore:

$arg = 'titled; $vehicle = (($arg = =' B')? 'bus': ($arg = =' A')? 'airplane': ($arg = ='T')? 'train': ($arg = =' C')? 'car': ($arg = =' H')? 'horse':' feet'); echo $vehicle

Print horse.

Variable

Cannot declare a variable. When used for the first time, variables that do not exist are created as null values.

Global variables need to be declared by global before they are used. This is based on the natural results above, so it's a perfect reason, but without the declaration shown, the global variable cannot even be read-PHP will quietly create a local variable of the same name to replace it. I have not seen other languages deal with scope problems in a similar way.

> > there is no reference. PHP's so-called reference is a real alias; this is undoubtedly a step backwards, unlike Perl references and no object identity passing like Python.

> > there is no obvious way to detect and dereference.

Citation makes variables different in the language. PHP is dynamically typed, so variables are usually untyped. In addition to references, it modifies function definitions, variable syntax, and assignments. Once a variable is referenced (it can happen anywhere), it is always a reference. There is no obvious way to detect and dereference the required variable values.

Well, I lied. Some "SPL types" also act on variables: $x = new SplBool (true); $x = "foo"; will fail. It's kind of like a static type. 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.

The constants defined by functions are called taking a string; before they do not exist. (this may actually be the act of copying Perl using constants.)

Variable names are case sensitive. The function and class name are not. It would be strange to use hump naming for the method.

structure

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

> > Array unpacking can be done using list ($a _ parcel) =. The operation is complete. List () is a class function syntax, just like an array. I don't know why I don't give a real special grammar, and I don't know why the name is so confusing.

> > (int) is obviously designed to be similar to C, but it is not a separate tag; in the language, nothing is called int. Try it: var_dump (int) does not work, it throws a parsing error because the parameter looks like a force transfer operator.

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

> > there is a (array) operator to convert to an array and (object) to convert to an object. This sounds sweet, but there is often a use case: you can use (array) to make a function parameter, either a single element or a list, be treated the same. But this is unreliable, because if someone passes a single object, converting it to an array will actually generate an array containing object properties. The conversion to an object performed a reverse operation.

Functions like include () are basically C # include: they transfer other file source code to your file. There is no modular system, even for PHP code.

> > there are no functions or classes like nested or locally scoped. They are all overall. Include a file whose variables are imported into the current function scope (giving the file the ability to access your variables), but functions and classes are stored in the global scope.

> > append array using $foo [] = $bar.

> > echo is not a function.

> > empty ($var) is so extreme that it does not appear as a function for anything but the variable e.g. Empty ($var | | $var2) is a parsing error. Why is there such a thing on earth, and why do parsers need to know about empty?

There are also some redundant syntax blocks: if (...):. Endif;, and so on.

Error handling

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

The PHP error does not provide a stack trace. You have to install a processor to generate them. (but not fatal errors-see below.)

PHP parsing errors usually only throw the parsing state, nothing else, making debugging very bad.

The parser of PHP refers to, for example. :: internally as a T_PAAMAYIM_NEKUDOTAYIM, while most error handling prints to the server log and prints a line of error log, which no one sees and keeps going.

E_STRICT looks like that, but it doesn't really have much protection, and there's no documentation showing what it actually does.

E_ALL contains all the error categories-- except E_STRICT.

It is odd and inconsistent about what is allowed and what is not allowed. I don't know how E_STRICT works here, but these are true:

> > attempt to access object properties that do not exist, such as $foo- > x. (warning)

Use variable as function name, or variable name, or class name. (silent)

An attempt was made to use an undefined constant. (notice)

> > attempt to access properties of non-object type. (notice)

> > attempt to use a variable name that does not exist. (notice)

> > 2

< "foo" (隐藏) >

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

But not the following:

> > attempt to access a class constant that does not exist, such as $foo::x. (fatal error)

Use string constants as function names, or variable names, or class names. (parse error)

An attempt was made to call a definition function. (fatal error)

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

Use list and other quasi-built-in macros as method names. (parse error)

Use subscript to access the return value of the function, such as: foo () [0]. (parse error; has been fixed in 5.4)

There are also a few good examples of other weird parsing errors elsewhere in the list

The _ _ toString method cannot throw an exception. If you try, PHP will. Er, throw an exception. (it's actually a fatal error that can be passed, except.)

PHP errors and PHP anomalies are completely different species. They cannot interact with each other.

> > PHP errors (internally, called trigger_error) cannot be caught by try/catch.

Similarly, an exception cannot trigger an error through an error processor installed by set_error_handler.

Instead, there is a separate set_exception_handler that handles uncaught exceptions, because wrapping your program entry in try blocks is impossible in the mod_pho module.

> > Fatal errors (for example, new ClassDoesntExist ()) cannot be caught by anything. A large number of completely harmless operations will throw fatal errors, forcing you to terminate your program for controversial reasons. The shutdown functions are still running, but they cannot get the stack trace (they run at the top), and it is difficult for them to tell whether the program ends with an error or the normal operation of the program.

Without finally structure, the wrapper code (register processor, run code, log off processor; monkeypatch, run test, unmonkeypatch) is ugly and difficult to write. Although OO and unusually large numbers of copies of Java's schema, this is intentional, because finally "in the context of PHP, only its shape is out of shape". Huh?

Function

> > function calls seem quite expensive.

Some built-in functions interact with reference-returning functions in, uh, a strange way.

As mentioned elsewhere, many things that look like functions or appear to be functions are actually part of the language and therefore do not work like normal functions.

> > function parameters can have type hints, which are basically static types. You can't ask a parameter to be int or string or an object or other "core" type, even if every built-in function uses this type, probably because int is not a thing in PHP. Check out the discussion about (int) above. Nor can you use special pseudo-types that are used by a large number of built-in functions: mixed, number, or callback.

> > therefore, the following:

Function foo (string $s) {} foo ("hello world")

Generate error the error:

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

You may notice that the Type hint does not actually exist; there is no string class in the program. If you try to test the type hint dynamically with ReflectionParameter::getClass (), you will get that the type does not exist, making it virtually impossible to get the type name.

The return value of the function cannot be inferred

> > passing the parameters of the current function to another function (dispatch, not uncommon) is done through call_user_func_array ('other_function', func_get_args ()). But func_get_args throws a fatal error at run time, complaining that it cannot be used as a function argument. Why is this a type error? (fixed in PHP 5.3)

Each variable that the closure needs to display is named closed-over. Why doesn't the parser find a way to solve it? (Okay, it's because using a variable ever, at all, creates it unless explicitly told otherwise.)

The Closed-over variable is passed through the same semantics as other function parameters. In this case, arrays, strings, and so on, will be passed to the closure by value. Unless you use &.

Because closure variables automatically pass parameters without nested ranges, closures cannot point to private methods, regardless of whether they are defined in the class or not. (may be fixed in 5.4? I don't know.

The function has no named arguments. It is actually rejected by devs because it "causes code to stink".

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?)

Passing extra arguments to the function is ignored (except for the built-in function, an exception is thrown). The missing parameter is assumed to be null.

The variable function requires func_num_args, func_get_arg, and func_get_args. There is no grammar for such things.

OO

> > the function part of PHP is designed to be similar to C, but object-oriented (ho ho) is designed to be similar to Java. I don't want to overemphasize how incongruous this is. I haven't found a global function with uppercase letters, important built-in classes are named using hump methods, and have getFoo's Java-style property accessors. It's a dynamic language, isn't it? Perl, Python, and Ruby all have some concepts of accessing "properties" through code; PHP only has clunky _ _ get and the like. The type system is designed around the low-level Java language. In the era of Java and PHP's, Java deliberately made more restrictions and copied Java, which puzzled me.

Class is not an object. Metaprogramming has to point to them by string names, just like functions.

The built-in type is not an object and (unlike Perl) cannot make it look like an object.

Instanceof is an operator, although it was added late, and most languages have built-in functions and syntax. Are you affected by Java? Class is not the first category? I don't know if they are.

> > but there is an is_a function. It has an optional parameter that specifies whether the object is actually 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). So, you need is_int and so on.

The right value must be a variable or literal quantity; it cannot be an expression. Otherwise it will lead to. A parsing error.

> > clone is an operator?!

OO is designed to be a monster that mixes Perl and Java.

> > the object property is via $obj- > foo, but the class property is $obj::foo. I've never seen any other language do this, or what's the use of it.

However, instance methods can still be called via static (Class::method). If called from other methods, it will be treated as a regular method call on the current $this. I think so.

New, private, public, protected, static, etc. Trying to win the hearts of Java developers? I know it's more of a personal taste, but I don't know why these things are necessary in a dynamic language-in C++, most of them are about assembly and compile-time naming decisions.

Private methods cannot be overridden by subclasses. The public method overridden by the subclass is also invisible, called separately, and the private method of the superclass. There will be problems, such as when testing mocks objects.

The method cannot be named, for example, list, because list () is a special syntax (not a function) and the parser is confused. The reason for being so ambiguous is not known, and the class works very well. ($foo- > list () is not a syntax error.)

If an exception is thrown when parsing constructor parameters (for example, new Foo (bar ()) and bar ()), the constructor will not be called, but the destructor will. (fixed in PHP 5.3)

Exceptions in _ _ autoload and parsing functions can cause fatal errors.

> > there is no constructor or destructor. _ _ construct is an initialization function, like Python's _ _ init__. Unable to request memory and create objects by calling classes.

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

> > OO brings an iterator interface, which is part of the language specification (such as. As.), but the interface actually has no built-in implementation (such as an array). If you want an array iterator, you must wrap it in ArrayIterator. There is no built-in way for iterators to work as first-class objects.

Classes can overload how they are converted to strings, but not how they are converted to numbers or any other built-in type.

Strings, numbers, and arrays all have string conversion methods; the language depends on it. Functions and classes are strings. However, if _ _ toString is not defined, trying to convert a built-in or custom object (or even a closure) to a string will result in an error, even echo.

Cannot overload equality or comparison operations.

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

Standard library

Perl "some needs compilation". Python is "batteries included". PHP is "kitchen sink, it comes from Canada, but all faucets are labeled with C".

Generalization

> > there is no type system. You can compile PHP, but you must specify what to load through php.ini, because the extension exists (injects their contents into the global namespace) or does not exist.

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

Some parts of the library are very inconsistent.

> > Ununderlined pair: strpos/str_rot13, php_uname/phpversion, base64_encode/urlencode, gettype/get_class

> > "to" pair 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 begin with array_. The rest is not.

The kitchen sink. Libraries include:

> > bind ImageMagick, bind GraphicsMagick (a derivative of ImageMagick), and a few functions can detect EXIF data (among which ImageMagick can already do so)

Parsing bbcode functions, 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 pile of things I don't recognize are omitted. Of course there will be some differences, and you are free to figure out the difference.

Bundled with two special credit card processors, SPPLUS and MCVE. What?

There are three ways to access MySQL databases: mysql, mysqli, and something abstracted by PDO.

C influence

It needs to have its own symbols. PHP is a high-level, dynamically typed language. Then parts of a large number of standard libraries are still just thin wrappers around C APIS, along with the following:

> > Out parameter, although PHP can return ad-hoc hash or multiple parameters effortlessly.

At least a dozen functions are used to get the last error in a subsystem (see below), although PHP has been storing exception handling for 8 years.

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

Global behavior is non-global (such as MySQL). Use multiple MySQL connections that need to be displayed to pass the connection handle to each function call.

The wrapper is really, really thin. For example, calling dba_nextkey instead of dba_firstkey will result in a segment error.

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

Genericism

If functions do two slightly different things, PHP comes up with two functions.

How do you reverse the 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 ().

> > 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, anything else?

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

> > there are many 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 currently given in the directory. Instead of (possibly beneficial) returning in the order of the return directory, the function returns a sorted list of files. There is an optional parameter that can be returned alphabetically. These are obviously not enough for sorting.

Str_split splits the string into blocks of equal length. Chunk_split splits the string into equal-length blocks and concatenates them with a delimiter.

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

> > because calling functions with parameter arrays is so call_user_func_array, there are some companions like printf/vprintf and sprintf/vsprintf. They do the same thing, but one with multiple parameters and the other with an array of parameters.

Text

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

The design of strtok is obviously equivalent to the C function and has been considered a bad idea for many reasons. PHP can easily return an array (which is awkward in C), and a lot of hack strtok (3) usage (modifying a string somewhere) cannot be used here.

> > parse_str parses the query string, but there is no sign from the function name. It will register_globals and dump the query string to the local scope variable, unless you pass an array to fill it. (return nothing, of course)

> > when an empty delimiter is encountered, explode refuses to split. Every other string splitting implementation should mean splitting a string into characters; PHP has a split function, which is confusingly called str_split but described as "turning a string into an array".

Format date, with strftime, just as C API deals with the local locale. Of course, there is also date, which has a completely different syntax and is only used for English.

> > "gzgetss-- get the line pointer to the gz file and remove the HTML tag." Knowing the concept of this series of functions, let me go to hell.

> > mbstring

It's all about multi-byte, solving the problem of character set.

Still dealing with ordinary strings. There is a single global default character set. Some functions allow you to specify a character set, but it depends on all parameters and return values.

Ereg_* functions are provided, but these are obsolete. Preg_* is lucky to use some PCRE-specific tags that understand UTF-8.

System and reflection

There are a lot of functions that focus on text and variables. Compression and extraction are just the tip of the iceberg.

There are several ways to make PHP dynamic, but at first glance there is no obvious difference or relative benefit. The class tool cannot modify the custom class; the runtime tool replaces it and can modify anything custom; the Reflection* class reflects most of the language; there are many unique functions for reporting functions and class properties. Are these subsystems independent, related, and redundant?

> > get_class ($obj) returns the class name of the object. Get_class () returns the name of the class in the called function. All that aside, the same function does something completely different: get_class (null). Act like the latter. So in the face of a random variable, you can't trust it. Surprise!

The stream_* class allows custom streaming objects to be used by fopen and other built-in things like file processing. Notification cannot be implemented for several internal reasons.

Register_tick_function can accept closure objects. Unregister_tick_function doesn't work; instead, it throws an error complaining that closures cannot be converted to strings.

Php_uname tells you about the current operating system.

Fork and exec are not built-in. They are from the pcntl extension, but are not included by default. Popen does not provide pid files.

Session_decode is used to read arbitrary PHP session strings, but only works if there is an active session. It dumps the result to $_ SESSION instead of returning its value.

Miscellaneous

Curl_multi_exec does not change curl_error when something goes wrong, but it changes curl_error.

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

Data manipulation

The program is nothing but chewing and spitting out data. A large number of languages are designed around data manipulation, from awk to Prolog to C. If language cannot manipulate data, it cannot do anything.

Figures

Integers is a signed 32-bit number on 32-bit platform. Unlike PHP's contemporaries, there is no automatic bigint promotion. So your math operations may result in different results due to the CPU architecture. The only way you can choose a large integer is to use GMP or BC wrapper functions. Developers may have proposed to add new, separate, 64-bit types. This is crazy.)

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

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

> > there is no power operator, only the pow function.

Text

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

This means that using the built-in string function to process UTF-8 text is 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 insert keys into variables, for example, "$foo ['key']" is a syntax error. You can't unquote it (this will generate warnings anywhere!), or use ${.} / {$.}

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

Array

Oh, Sao Nian.

This guy plays the list data type, manipulates hash, and sorts set, parses list, and occasionally has some strange combinations. How does it work? How do I use memory? Who knows? I don't like it. I have other options anyway.

> > = > is not an operator. It is a special structure that exists only in array (...). And foreach structure.

The negative index does not work, although-1 is the same legal key as 0.

Although this is a language-level data structure, there is no short syntax; array (...) It's a short grammar. (PHP 5.4brings "literals", [...].)

The structure is based on Perl, and Perl allows foo = > 1 without quotation marks. In PHP, you will be warned to do so; there is no way to create hash string keys without quotation marks.

Array handlers are often confusing or uncertain because they have to operate on lists, hashes, or a possible combination of the two. Consider array grouping, "calculate different parts of arrays."

$first = array ("foo" = > 123, "bar" = > 456); $second = array ("foo" = > 456, "bar" = > 123); echo var_dump (array_diff ($first, $second))

What will this code do? If array_diff treats parameters as hashes, they are obviously different; the same keys has different values. If you look at it in terms of list, they are still different; the order of values is different.

In fact, array_diff thinks they are equal because it is treated as sets: just comparing values, ignoring order.

Similarly, when array_rand randomly selects keys, it also has strange behavior, which is not helpful for most use cases that need to pick something from the list.

Although a lot of PHP code relies on the order of key:

Array ("foo", "bar")! = array ("bar", "foo") array ("foo" = > 1, "bar" = > 2) = array ("bar" = > 2, "foo" = > 1)

> > what happens if two arrays are mixed? I leave it to the reader to figure it out. (I don't know)

> > array_fill cannot create a 0-length array; instead, it issues a warning and returns false.

All of them (a lot of.) The sort function operates in place and returns nothing. There is no way to create a new copy of a sorted array; you have to copy the array yourself, sort it, and then use the array.

> > but array_reverse returns a new array.

A bunch of sorted things and some key-value pairs sounds like a powerful way to handle function parameters, but no way.

Non-array

The standard library contains hash structure OO implementations of Fast Hash and specific strong types. However, going deep into it, there are four types, each of which deals with a different combination of key-value pairs. It is not clear why the built-in array implementation cannot optimize these very common situations, nor is it clear how its relative performance is.

There is an ArrayObject class (which implements 4 different interfaces) that wraps an array to make it look like an object. Custom classes can implement the same interface. But there are only a limited number of methods, half of which are not like built-in array functions, and built-in array functions do not know how to operate on ArrayObject or other class array types.

Function

The function is not data. Closures are actually objects, but ordinary functions are not. You can't even reference them by their naked names; var_dump (strstr) will issue a warning and guess that you mean literal string, "strstr". There is no way to tell whether a string is a function reference.

Create_function is basically a wrapper for eval. It creates a function with a common name and installs it globally (so it will never be garbage collected-don't use it in a loop!). It actually knows nothing about the current context because it is not a closure. The name contains a NUL byte, so it never conflicts with a normal function (because if there is a NUL anywhere in the file, the PHP parser will fail).

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

Other

> > generate 1 using (+ +) for NULL. Use (- -) to generate NULL for NULL.

> > there is no generator.

Web framework

Execution environment

A single shared file php.ini controls most of the functions of PHP and weaves complex rules for what and when to overwrite. PHP software can be deployed on any machine, so some settings must be overridden to make the environment normal, which violates the use of mechanisms such as php.ini in large programs.

> > PHP basically runs as CGI. Each time the page is clicked, PHP recompiles the entire environment before execution. Even the development environment of Python toy framework will not be like this.

This has led to the formation of the entire PHP accelerator market, which can speed up PHP just once, just like other languages. Zend, the company behind PHP, uses this as their business model.

For a long time, PHP's errors have been output to the client by default-- to help the development environment, I guess. I don't think this is true, but I still see occasional mysql errors at the top of the page.

In the white space outside the tag, even in the library, PHP treats and parses the response as text (or causes a "headers already sent" error). A popular practice is to ignore? > close the tag.

Deployment

Deployment is often quoted as the most advanced part of PHP: just deploy the file directly. Yes, this is easier than Python or Rury or Perl that needs to start the entire process. But PHP leaves a lot of room for improvement.

I'd be happy to run Web applications as an application server and reverse proxy them. This has the lowest cost and many benefits: you can manage servers and applications separately, you can run more or less application processes according to the number of machines, without the need for multiple web servers, you can run applications with different users, you can choose web servers, you can remove applications without alerting web servers, you can deploy applications seamlessly, and so on. Soldering applications directly to web servers is absurd, and there is no good reason for you to do so.

Every PHP application uses php.ini. But there is only one php.ini file, which is global; if you are on a shared server and need to modify it, or if you run two applications that require different settings, you are unlucky; you have to apply to the organization for all the necessary settings and put them in the application, such as using ini_set or configuration files in Apache or settings in .htaccess. If you can do it. Maybe wow, you have a lot of places to check to find out how to get the set value.

Similarly, isolating PHP applications is not easy, it depends on the rest of the system. Want to run two applications, want different library versions, or different PHP versions themselves? Start building a copy of another person's Apache.

The "pile of files" solution, in addition to making the route look like a sick donkey, also means that you have to be careful with whitelists or blacklists to control what is accessible, because your URL level is the level of your code tree. Configuration files and other "local modules" need to be guarded by things like C to avoid direct loading. Files of the version control system (such as .svn) need to be protected. With mod_php, everything in the file system is a potential entry; with an application server, there is only one entry, and only URL controls whether it is called or not.

You cannot seamlessly upgrade the stack of files running in CGI-style unless you want the application to crash and undefined behavior when the user clicks on your site during the upgrade interval.

Although it is easy to configure Apache to run PHP, there are still some pitfalls. The PHP documentation suggests using SetHandler to make the .php file run as PHP. AddHandler looks good, but in fact there will be problems.

When you use AddHandler, you are telling Apache to "execute it as php", which is a possible way to deal with .php files. But! Apache doesn't think so about the file extension. It is designed to support files such as index.html.en. For Apache, files can have any number of extensions at the same time.

Guess that you have a file upload form that stores some files in a public directory. Make sure no one can upload PHP files, you just check that files cannot have a .php extension. All an attack needs to do is upload a file named foo.php.txt; your upload tool will not see the problem, Apache will think it is a PHP, and it will gladly execute.

The problem here is not "using the original file name" or "no better verification"; the problem is that your web server should be configured to run any old code, making PHP "easy to deploy". This is not a theoretical problem; I have found that many practical sites have similar problems.

Missing characteristics

I think all of this is about building a Web application. It seems reasonable to PHP, is one of its selling points, it is the "Web language" and should have them.

> > No module system. PHP is the template.

> > No XSS filter. Htmlspecialchars is not a XSS filter.

No CSRF protection. You must do it yourself.

> > Database API without general standard. Things like PDO have to wrap the API of each specific database, abstracting different parts.

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

There is no authentication or authorization.

> > there is no development server.

> > No interactive debugging mode.

There is no consistent deployment mechanism; just copy all files to the server.

Safety

Language boundary

PHP's poor security mechanism may be magnified because it takes data out of one language and restores it to another. This is a bad idea. "" it may mean nothing in SQL, but it is especially true in HTML.

To make matters worse, someone usually yells, "your input should be sterilized." That's completely wrong; you can't have any magic to make the block data completely dry and quiet. All you need to do is say to the language: SQL uses placeholders, process incubation uses parameter lists, and so on.

PHP openly encourages disinfection: there is a data filtering extension that can do that.

All addslashes, scripslashes, and other slashes related things are useless and useless.

I can only tell you so much that there is no safe incubation process. You can only execute strings through shell. Your choice is crazy escape, and you want the default shell to use the correct escape, or manual pcntl_fork_exec and pcntl_exec.

All escape commands and parameters have roughly the same description. Note that in Windows, the escape parameter does not work (because it is assumed to be Bourne shell), and the escape command simply replaces a bunch of punctuation with spaces, because no one can understand the escape behavior of the Windows command (it may silently destroy anything you try to do).

The original built-in MySQL binding, which is still widely used, cannot create a prepared statements.

To this day, suggestions on SQL injection in PHP documents are maddening, such as type checking, using sprintf and is_numeric, manually using mysql_real_escape_string everywhere, or manually using addslashes everywhere (this "might be more useful!") Such a practice. There is no mention of PDO or parameterization, except for some clues in user comments. At least two years ago, I complained specifically to PHP dev. He was alarmed, but the page never changed.

Insecure-by-default

> > register_globals. It was turned off by default and removed in 5.4. I don't care。

> > include accepts HTTL URLS. It's the same as above.

> > Magic quotes. So close to secure-by-default, and yet so far from understanding the concept at all.

Core

The PHP interpreter itself has some annoying security issues.

In 2007, the parser had an integer overflow vulnerability. The repair began with if (size > INT_MAX) return NULL; and has gone downhill since then. (for those who don't need to use C: once upon a time, INT_MAX was the largest integer for variables. I hope you can figure out the rest from here.

Recently, PHP 5.3.7 includes a crypt () function that allows anyone to log in with any password.

> > PHP5.4 is vulnerable to a denial of service attack because it requires a Content-Length header (anyone can set it) and attempts to allocate more memory. This is a bad idea.

I can dig more, but the point is not that there are a lot of X holes-- it's that the software has bugs, anyway. These are naturally astonishing. I'm not looking for these; but in the past few months, they have come to me.

Summary

Some comments will rightly point out that I have not come to any conclusion. Well, I don't have a conclusion. If you saw this all the way, I assume you agreed with me in the first place:)

If you only know PHP and are interested in learning other things, take a look at the Python tutorial and try Flask, the guy for web. I'm not a big fan of its template language, but it does do a good job. It divides your application into multiple parts, but they still look the same. I may write a post about this later; whirlwind introduction to the whole language and different from the web stack here.

Later or for larger projects, you may need Pyramid, a medium-sized framework, or Django, a complex framework for building sites, such as Django sites.

Is it helpful for you to read the above content? If you want to know more about the relevant knowledge or read more related articles, please follow the industry information channel, thank you for your support.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report