69

Other languages with automatic variable declaration - like Perl - have a strict mode.

By activating this strict mode, variable declaration is required, and Perl throws an error as soon as you try to use an undeclared variable.

Does PHP offer a similar feature?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
jantimon
  • 36,840
  • 23
  • 122
  • 185
  • 3
    Since version 7 [PHP does support strict mode](http://php.net/manual/en/migration70.new-features.php), just put `declare(strict_types=1);` at the top of each (and every) script file, before the namespace declaration. – Code4R7 May 23 '17 at 09:05
  • 3
    @Code4R7 That's a different kind of strict mode then the one asked about in the question. – Flimm Jul 03 '17 at 16:59
  • 1
    True. Revert to `error_reporting(E_STRICT);`. – Code4R7 Jul 04 '17 at 09:03

13 Answers13

70

Kind of. You can activate the E_NOTICE level in your error reporting. (List of constants here.)

Every instance of usage of an undeclared variable will throw an E_NOTICE.

The E_STRICT error level will also throw those notices, as well as other hints on how to optimize your code.

error_reporting(E_STRICT);

Terminating the script

If you are really serious, and want your script to terminate instead of just outputting a notice when encountering an undeclared variable, you could build a custom error handler.

A working example that handles only E_NOTICEs with "Undefined variable" in them and passes everything else on to the default PHP error handler:

<?php

error_reporting(E_STRICT);

function terminate_missing_variables($errno, $errstr, $errfile, $errline)
{                               
  if (($errno == E_NOTICE) and (strstr($errstr, "Undefined variable")))
   die ("$errstr in $errfile line $errline");

  return false; // Let the PHP error handler handle all the rest  
}

$old_error_handler = set_error_handler("terminate_missing_variables"); 

echo $test; // Will throw custom error

xxxx();  // Will throw standard PHP error

 ?>
Top-Master
  • 7,611
  • 5
  • 39
  • 71
Pekka
  • 442,112
  • 142
  • 972
  • 1,088
  • yes it is kind of but not as a whole like other strict-type languages. – Sarfraz Jul 07 '10 at 08:30
  • 1
    @sAc yup, there are other things that are output as notices too, so they will come up as well when you turn this on. (And obviously, it's not as strict as in a strongly typed language.) – Pekka Jul 07 '10 at 08:31
  • Thanks your code works excellent! I changed `die` into `throw` to redirect the output to the Zend Error Trace view. – jantimon Jul 07 '10 at 13:30
  • This works well, but I don't get a stack trace in these cases. Any suggestions on how to modify this to get stack traces? – Karl Bartel Sep 20 '11 at 14:00
  • Does `error_reporting(E_STRICT)` only affect code within the file, or does it globally set a setting for all code? – Flimm Jul 03 '17 at 17:01
  • @Flimm only within the current file (or rather, script being run, which could be scattered across multiple files that get `include()`d.) – Pekka Jul 03 '17 at 21:46
  • 2
    This only outputs messages with `E_STRICT` priority (see PHP's source code). As @full mentions and you only tagges #php, PHP has since 7.0 or 7.1 (not sure!) a real strict mode. Please see his answer for details. – Roland Jul 26 '18 at 10:43
  • But only at runtime, not parse time (if there is such a thing)? Perhaps be explicit about that? Perl can be made to complain at compile time. – Peter Mortensen Apr 22 '20 at 18:43
  • *"[In PHP, you can only know a variable doesn't exist when you try to access it.](https://stackoverflow.com/questions/3564744/php-and-undefined-variables-strategy/3564768#3564768)"* – Peter Mortensen Apr 22 '20 at 20:03
  • @Roland has a good point here. If you enable this (on PHP 7.4), you will _not_ get any `E_NOTICE` messages any more, for example. – Per Lundberg Sep 18 '20 at 08:18
41

Use

error_reporting(-1);

to show every possible error, including E_STRICT and even when new levels and constants are added in future PHP versions.

(Reference)

Gottlieb Notschnabel
  • 9,408
  • 18
  • 74
  • 116
Gordon
  • 312,688
  • 75
  • 539
  • 559
  • 2
    Is error_reporting(-1) the same as error_reporting(E_STRICT) ? – Pacerier Jun 06 '13 at 14:16
  • @Pacerier no, -1 enables all current and future error reporting. See the *Tip* at the bottom of the PHP Manual page. – Gordon Jun 08 '13 at 15:53
  • 5
    The constants E_STRICT and so on are bitmasks. By combing them with an OR you set the bits. -1 will set every bit. Example: A = 1; b(00000001) B = 2; b(00000010) A OR B = 3 (00000011); -1 = b(11111111) – Markus Zeller May 04 '16 at 07:50
  • Is it by [two's complement](https://en.wikipedia.org/wiki/Two%27s_complement) of -1 (how many bits) or because it is negative? – Peter Mortensen Apr 22 '20 at 19:22
  • Why not use `E_ALL`? It seems to be decimal 32767 (0x7FFF, 15 ones - binary 111111111111111). – Peter Mortensen Apr 23 '20 at 09:26
  • @PeterMortensen see https://www.php.net/manual/en/function.error-reporting.php. `E_ALL` only includes `E_STRICT` as of PHP 5.4. So "all" didn't mean "all" back when the question was asked in 2010. – Gordon Apr 23 '20 at 15:30
10

After some years, PHP 7.0.0 has gained declare(strict_types=1).

nice_dev
  • 17,053
  • 2
  • 21
  • 35
Full
  • 455
  • 4
  • 13
  • 3
    While it's named "strict mode", it's not what the strict mode in e.g. Perl is. This does strict type checking, that is, if your function expects a string and is given an int, not silent conversion will happen, but an error will be thrown. The strict mode OP asked about is basically that you need to say `$var = 1` before you can use `$var`, so you don't WILL catch typos in var names immediately, not just when some if condition makes the code with the typo run. – janh Aug 09 '18 at 21:45
  • 1
    The new link is https://www.php.net/manual/en/language.types.declarations.php#language.types.declarations.strict – Roland Dec 15 '20 at 20:15
  • it can be done in php.ini for all my projects? – Luis Alfredo Serrano Díaz Sep 19 '21 at 15:34
4

Yes, type error_reporting(E_STRICT|E_ALL); in the beginning of your script.

chelmertz
  • 20,399
  • 5
  • 40
  • 46
  • Only prior PHP 5.4.0, you need `E_STRICT` explicitly. See http://php.net/manual/en/function.error-reporting.php where `E_STRICT` became part of `E_ALL` since 5.4.0. – Roland Oct 27 '17 at 13:01
  • But only at runtime, not parse time (if there is such a thing)? – Peter Mortensen Apr 22 '20 at 18:43
  • @PeterMortensen yeah, like most things in PHP, runtime it is. `error_reporting()` can be adjusted multiple times, so it only affects what's being executed when the error_reporting level is set high enough. PHP includes everything in runtime, common template logic (a.k.a. all PHP code) depends on referring to unset variables, which are then set through another script that requires the "template", thus setting the variables (some simplified/ad hoc terms here but you get the idea). – chelmertz Apr 22 '20 at 22:27
2

You may check error_reporting, and don't forget to set display_errors as well. Note, that there are multiple levels of error reporting.

gblazex
  • 49,155
  • 12
  • 98
  • 91
1

PHP is warning about undeclared variables by default; you just need to turn the error reporting level up so you'll see the notices. Note though that since there's no special syntax to declare a variable in PHP and you simply declare one by assigning to it, it can only warn you when you try to use the value of an undeclared variable. Contrary to other languages, "assignments to undeclared variables" do not exist, so PHP can't warn you there.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
deceze
  • 510,633
  • 85
  • 743
  • 889
1

Use

error_reporting(E_ALL);

at the beginning of your PHP code.

Or set the error_reporting setting in your php.ini file, to set it for all PHP files.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
JochenJung
  • 7,183
  • 12
  • 64
  • 113
1

You can implement your own error handling function with set_error_handler().

Then you can react to certain error levels as you wish.

For example, instead of just showing and logging an error message, you could terminate the script if a variable is not declared properly or if any condition is met that you don't like.

That way you can enforce a very strict policy for any code that runs on your PHP interpreter instance.

selfawaresoup
  • 15,473
  • 7
  • 36
  • 47
1

Yes, you can from PHP 7.X onwards,

declare(strict_types=1);

This will enforce all the scalar type declarations to be strict with types.

But if you enable this globally, it can affect other third-party modules (for example, PHP Composer libraries) which are relying in weak mode, so make sure to enforce it in relevant classes/files.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
M_R_K
  • 5,929
  • 1
  • 39
  • 40
0

Yes, you do that with error reporting.

http://www.php.net/manual/en/function.error-reporting.php

Palantir
  • 23,820
  • 10
  • 76
  • 86
0

I would suggest that the requirements for reporting and handling errors differ within your development environment and your live production environment (WWW, company intranet, etc.). During development you will want to see as much detail as possible to find and fix problems.

In the live environment, I don't think that you want to show PHP error messages to the users, but rather allow the script to continue with reduced functionality (for example, a message like "Sorry we cannot update your profile at the moment", or redirect the user to the home page, etc.). A way to achieve this would be through the use of custom error handlers for each environment.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
0

Use:

error_reporting(E_STRICT);

I think you need to try this above.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
0

An improvement to @pekka's answer that also detects undefined array keys and offsets and undefined constants:

error_reporting(E_STRICT);

function terminate_undefineds($errno, $errstr, $errfile, $errline)
{ // $errno: E_NOTICE, etc.

    $errstr = strtolower($errstr);
    
    if (
            (strstr($errstr, "undefined variable")) ||
            (strstr($errstr, "undefined index"))    || // Such as $GLOBALS['some_unknown_var']
            (strstr($errstr, 'undefined constant')) || // Such as echo UNKNOWN_CONST
            (strstr($errstr, "undefined offset"))
            )
        die("$errstr in $errfile line $errline");
    else
        return false; // Let the PHP error handler handle all the rest
}

set_error_handler("terminate_undefineds"); 

As above code also restricts access to unknown $_GET and $_POST keys, you can define a similar method with related row commented and use set_error_handler before checking $_GET and $_POST keys. Also instead, you can use below methods to receive $_GET, $_POST and etc keys:

// Could be used in strict mode
function get_($what, $key) {
    switch (strtolower($what)) {
        case 'get':
            return isset($_GET[$key]) ? $_GET[$key] : null;
        case 'post':
            return isset($_POST[$key]) ? $_POST[$key] : null;
        case 'session':
            return isset($_SESSION[$key]) ? $_SESSION[$key] : null;
        case 'server':
            return isset($_SERVER[$key]) ? $_SERVER[$key] : null;
    }
}