📜 ⬆️ ⬇️

Mad PHP. Fury code


A collection of PHP is not normals or what you need to know so as not to go crazy and not shoot yourself something


I read the mnv article: " Type casting in PHP == a stool with two legs? " And I wanted to add a few additions in the comments, but ... But then I saw a comment and realized that I would better add the article to the fact that very few people write and where it is not in a centralized form. It seems to be a well-known topic, and yet someone is new. This is not exactly about casting, but they also exist. This is about the features, knowing that you can make fewer mistakes. If interested, go under the cat, I created!

PHP is not bad and not good. He is for his tasks and he copes with them. At the same time, this programming language has many different bugfits. You can complain and resent them. And you can just know about them and be able to circumvent or use them. No, no, I don't call for writing like that, I'm just saying that if you want, then ...

Before we judge, let's agree!


Let's view this post as entertaining. Those. This is not a task for interviews and not for production. These are just examples of tasks for the Olympiad, where you can get the title " I am a PHP interpreter! ".

Think like PHP ... Feel like PHP ... Be PHP!


The puzzles are taken from our quest, which we did on " Developer's Day ", celebrated in our company. Our colleague even wrote a detailed article about how Tutu.ru commemorates the work of IT people in the article “ How to celebrate a programmer’s day at work and make everyone happy? ”. So again, this is not for production and not for an interview. This is for fun!
')

About numbers


Numbers in PHP, the thing is good. They have already spoken so much about them that everything seems to be clear. But if we talk about PHP, there are a couple of add-ons, so I will not load it, but simply add a couple of examples.

What is the result of concatenating the next lines? (yes, they don’t write like that, but we have the same Olympiad):

<?php { print "a" . 2; print "a".2; } 

What will happen?
The last line of PHP will try to cast the entry to a floating point number. But this will lead to an error.
PHP Parse error: syntax error, unexpected '.2' (T_DNUMBER) in Command line code on line 1

Search string in array

This is quite a combat situation. This can occur in the code of some CMS or real projects.

 <?php $a = ['7.1']; in_array('7.1', $a); in_array('7.1abc', $a); in_array('7.10', $a); in_array('7.100000000000000009123', $a); 

We recall about the PHP chip and get the correct answer:
in_array ('7.1', $ a); // true
in_array ('7.1abc', $ a); // false
in_array ('7.10', $ a); // true
in_array ('7.100000000000000009123', $ a); // true

To avoid errors, use the 3rd argument: an indication of the type of comparison.

bool in_array (mixed $ needle, array $ haystack [, bool $ strict = FALSE])

Although there is a flag indicating the ability to compare strictly, in reality I rarely saw it used somewhere. So there are a lot of errors of this kind on the Internet.


How in PHP to override TRUE?


A question on backfill and for the sake of academic interest. If you really want, then:
 <?php //        // PHP Notice: Constant true already defined in ... namespace { define('true', false); } //     -  namespace Hack { define('Hack\\true', false); var_dump(true === false); // true } 

If we talk about PHP7, then such code will not work there and it will be impossible to override these constants.

Is the script valid?


 <?php $ = 1; $  = 2; $   = $  + $ ; var_dump( $   ); //EOF// 

Yes
The character with a decimal index 160 is included in the table of allowed characters for naming variables in PHP. In Windows, you can dial it as Alt + 0160.

Run at any cost


This is just a task to think about. Again about casting. Just a puzzle.

 <?php if ( $x == false && $y == true && $x == $y ) { echo "Yuo crazy developer!"; } 

One of the options
$ x = 0;
$ y = 'x';

Crazy logic


And here is another cool example of the features of the interpreter. Let's answer the question, what will happen?

 $a = 1; var_dump( $a + $a++ ); 

And if you complicate?

 $a = 1; var_dump( $a + $a + $a++ ); 

If you answered the first 2 questions, then you will not be difficult to interpret this task:

 <?php $a = 1; $b = 1; var_dump( ($a + $a + $a++) === ($b + $b++) ); 

The answer is in the next paragraph.

Something went wrong, right?
And in the 1st, and in the 2nd case, the answer is 3, which means that the 3rd example will give true.

How does the first example work?
The operation of addition is left-associative - the analysis of the arguments begins from left to right. Moving in this way, the parser sees an expression in which there are two operations — addition and postincrement — for a postincrement, the priority is higher; therefore, it is calculated first by returning “1” as the value and increasing the variable by one. Then the operation of addition is calculated, adding the resulting unit with a two (since the post-increment increased the value of the variable by one). It turns out "three".

In a similar way, multiplication is processed along with addition: 2 + 2 * 2 = 6, not 8, because multiplication has a higher priority.

In the second case, everything happens in a similar way, but a little differently - the parser, processing the left-associative addition, takes the first two arguments, adds them, gets a “two”, moves on, sees the two, the addition and post-increment of the variable. The post-increment is more priority, it calculates it earlier, returning “one” to addition, the value of the variable increases, but no one uses it - the numbers “2” (from the previous addition) and “1” (returned post-increment) are added. It turns out "three".

More details and picture
In bytecodes, all of the above is as follows:

Here, the second example starts from the eighth line (though I omitted the assignment of a unit in the second example - as you see, there is no second ASSIGN operation).

A source


But in fact it is not logical. So do not break your head, everything works correctly. But not the way you expected. In other languages, for example, Javascript, the answer will be different. Check it out. The 2nd version behaves the same with the same JS. But here is the 1st issue of questions, if you look at the results in different programming languages.

Poorly iterate the string?


There is a task to iterate the line:

 <?php $s = 'Iteration'; // <-   for ($i = 0; $i < 10; $i++) { // echo ???, "\n"; } //EOF// 

The output requires the following result:

 Iteration 0 Iteration 1 Iteration 2 Iteration 3 Iteration 4 Iteration 5 Iteration 6 Iteration 7 Iteration 8 Iteration 9 


Your options?
And here is my version
 <?php $s = 'Iteration 0'; for ($i = 0; $i < 100; $i++) { echo $s++, "\n"; } //EOF// 

If at the end there is 1 digit, then the iteration will be repeated from 0 to 9 during the cycle. If you want to get from 0 to 99, then you need to put 2 numbers: "Iteration 00". And what if you want to deduce the alphabet? Then we put the letter a at the end if we want to put everything in order:

 Iteration a Iteration b Iteration c Iteration d Iteration e Iteration f Iteration g Iteration h Iteration i Iteration j Iteration k Iteration l Iteration m Iteration n ... 

In PHP7, nothing changes. this behavior persists. Given the fact that this behavior has existed for a long time, this approach can be used somewhere on hackathons. Well, or again, just 4 fan. Play with it, there are still surprises, I do not want to paint. But if you continue to iterate, you will be surprised at the logic.

Values ​​by reference


Links in PHP, the thing is good! But there are nuances. There is no $ foo array defined anywhere. This should cause an error ...

 <?php function getCount(&$a) { return count($a); } $cnt = getCount( $foo ); var_dump($cnt); //     $cnt = getCount( $foo['bar'] ); var_dump($cnt); 

But everything will be ok. The error will be only if you remove the ampersand, then we get:
PHP Notice: Undefined variable: foo in /www/sites/majorov.su/***/a.php on line 8
int (0)
PHP Notice: Undefined variable: foo in /www/sites/majorov.su/***/a.php on line 14
int (0)

Non-existent valid code


Let's fantasize. You have a powerful project with a 10 year history. And you have the task of refactoring and reengineering the old code.

And here you rule the code and go crazy. Why? Well, because, let's say, you do not understand why what should not work for you.

 <?php class Bar { public $foo = 1; } $Obj1 = new Bar( Foo.bar() ); // Foo   !     $Obj2 = new stdClass( getFoo( $Obj1 ) ); // getFoo()  ,   ? 

If there is no constructor, then the code passed to the constructor does not cause errors. It is parsed, but not executed, because the optimizer ignores these lines. This saves us processing time. After all, to show an error, you need to know what error (code, type, line number ...). And here it just goes missing part of the code, since there is no sense in it. It's great, really. But you need to know about it, otherwise you will blow it up the brain.

ACL, MD5 and ... Collision?


Imagine that you have a CMS. And here there is something like this (believe, there are many such codes (not exactly this, but working according to this principle, can be found in Runet).

 <?php //    admin //    QNKCDZO $_POST = ['pass' => 'QNKCDZO']; $userPass = md5($_POST['pass']); //       240610708 $actualPassInDb = md5('240610708'); $autorizied = false; //   if ( $userPass == $actualPassInDb ) { //   $autorizied = true; } else { /*header*/var_dump("location: /error/"); die; } 

And what is wrong? It seems everything is ok. Passwords are different. Is not it so?
Let's take a look at md5 () password hashes:

Do you understand? PHP sees 0 and thinks it is a number. More precisely, PHP sees 0e [0-9] + and thinks that it is a float number that is reduced to 0. For more information, see the link: https://blog.whitehatsec.com/magic-hashes/

And he deeply purple that there is a line, if that. So the code can be valid, but we use verification not only by value, but also by type. Otherwise, the trouble.

Foreach and Key Links


Lastly, I remind you that you need to be careful with the links.
Here is an example of how to get what was not expected:

 <?php $array = ['foo', 'bar']; foreach ($array as $k => &$foo){ $foo .= $k; } var_dump($array); foreach ($array as $foo) { var_dump($foo); } 

What do we expect? And what do we get?

And we get this:

 array(2) { [0]=> string(4) "foo0" [1]=> &string(4) "bar1" // ,   ! } string(4) "foo0" string(4) "foo0" 

Because of the hidden pointer, the next iteration gives us access to another value.

Actually this is my entire commentary on the article that I wanted to add. Learn the features of the language. Teach them not to throw at interviews. Teach them to not get into such a hole. Do not hesitate. You do not write like that, others can write like that. And who will explain to them why not and what is wrong? And how to explain what you do not know?

Peace to you, developers. I’ve been writing in PHP for 12 years, and now it's been 3 years since I’ve been in front-end development, I’m crazy with JavaScript, but that's another story. But sometimes you want to touch this PHP itself.

I also recommend reading the article from AlexLeonov We are preparing for an interview in PHP: the key word“ static ”” , there are interesting points that I did not describe.

PS: The picture shows PHP MV 9. The PHP pistol (Prvi Hrvatski Pistolj is the first Croatian pistol) was urgently developed in Croatia, which had separated from the allied Yugoslavia of Croatia in the early nineties of the 20th century, when the country desperately needed weapons because of the emergence of the Yugoslavia of war. The gun, which absorbed the features of such well-known and quite successful samples like the Beretta 92 and Walther P38, came out much less successful and had problems with reliability. Its release was rather short and later it was replaced by the Croatian army with a much more successful HS 2000 pistol.

The PHP pistol uses automatics with a short stroke, the locking is done with the help of a swinging larva located below the barrel. Return spring is located under the barrel. Trigger trigger, double action (self-cocked). On the left of the handle is a lever for the safe descent of the hammer from the platoon. Shop double row, with a capacity of 15 rounds.

Be careful not to shoot yourself anything!

UPD: in the comments the user smart gave good links to the documentation, for those who want to understand the details

Source: https://habr.com/ru/post/259865/


All Articles