Common PHP mistakes and solutions

PHP is such a flexible and powerful language. However, it’s easy to make mistakes, especially if you’re a beginner.

Parse errors

Are you tired of getting parse errors?

For example:

Parse error: syntax error, unexpected ‘,’

Use modern editors such as VS code. You’ll find useful plugins to easily install a syntax highlighter. Stupid typos will be highlighted in red, making your life easier.

Don’t waste your time spotting typos.

Do you sleep at night?

There may be many forms of this one, but here is a classic oversight:

if (defined("MY_CONST")) {
    define("MY_CONST");
}

If you look at this carefully, you’ll see it misses an essential element. Maybe you can handle it after a well-deserved sleep, or at least after a short break.

The correct version is:

if (!defined("MY_CONST")) {
    define("MY_CONST");
}

You want to define the constant only if it’s not defined before.

Don’t be so negative!

function isNotEligible(int $age, int $score, string $team): bool {
    return $age < 18 || $score < 9999 || $team === "admin"; 
}

The above function works, but it’s not good practice to use this “negative” approach, as it’s less readable and thus, harder to use.

For example, to check if someone is eligible:

if (!isNotEligible()) {}

It overcomplicated and it does not feel right. Instead, write:

function isEligible(int $age, int $score, string $team): bool {
    return $age >= 18 && $score >= 9999 && $team !== "admin"; 
}

and use it like that:

if (isEligible()) {
    // some code
} 

or:

if (!isEligible()) {
    // some code
}

There’s no escape!

echo $_GET['s'];// "s" would be a search keyword

Not escaping GET params is always wrong. Full stop.

A quick and dirty fix would be:

if (isset($_GET['s'])) {
    echo htmlentities($_GET['s'], ENT_QUOTES, 'UTF-8');
}

Does it exist?

This one is a classic misunderstanding.

Developers often use method_exists() like that:

$directory = new Directory('.');
var_dump(method_exists($directory,'read'));

Source: PHP documentation, method_exists()

In the above example, the method exists and you can use it.

What if the method is protected or private? If you aren’t in the scope (respectively not in a child class or not in the class itself), you get a fatal error, even if method_exists() returns true.

You’d better use is_callable() to check if you really can call and use the method in your context:

$myClass = new MyClass();
var_dump(is_callable([$myClass, 'myMethod']);

You must know the difference to use the appropriate function in your conditions.

The anonymous stdClass

PHP provides a built-in empty class called stdClass. It creates an anonymous object.

Don’t be confused if you come from another programming language. It’s not like JavaScript or Ruby. You don’t have a mother class at the top of the chain and all objects extending it.

You can consider stdClass as an alternative to associative arrays. To use it, you don’t have to formally define a new class, you can directly assign properties dynamically.

If you look at another built-in function called json_decode(), it uses stdClass:

$string = '{
    "text": "coucou"
}';
print_r(json_decode($string));

The result is:

stdClass Object
(
    [text] => coucou
)

When you cast an array as an object, you get an stdClass Object:

$them = (object) ["Ava", "Iris", "Delta",];
print_r($them);

See the print:

stdClass Object
(
    [0] => Ava
    [1] => Iris
    [2] => Delta
)

Source: PHP documentation - reserved classes

References vs. values

This confusion happens a lot:

$numbers = range(1, 7);
foreach ($numbers as &$value) {
    // some code
}
foreach ($numbers as $value) {
    // some code
}
print_r($numbers);

Look at the results after the second loop:

Array
(
    [0] => 1
    [1] => 2
    [2] => 3
    [3] => 4
    [4] => 5
    [5] => 6
    [6] => 6
)

What the…

The first loop passes $value by reference, then the second loop passes $value by value. The problem is that the script still holds the reference from the last pass (of the first foreach).

To fix that, you can clean $value:

$numbers = range(1, 7);
foreach ($numbers as &$value) {
    // some code
}

unset($value);// clean $value

foreach ($numbers as $value) {
    // some code
}
print_r($numbers);

Now, as probably expected, you get “7”:

Array
(
    [0] => 1
    [1] => 2
    [2] => 3
    [3] => 4
    [4] => 5
    [5] => 6
    [6] => 7
)

Wrap up

PHP has powerful built-in functions, but it’s easy to get confused.

There are specific rules you must know to prevent nasty bugs, and it’s better to look at things with a fresh eye.

Photo by Quino Al on Unsplash