2

Take this line of PHP:

$foo["bar"] = 1;

I would like PHP to throw an exception if $foo doesn't exist. Right now, it doesn't throw an exception, or even print an error or warning even with display_errors set to 1 and error_reporting called with E_ALL. Instead, it creates an array $foo and sets $foo["bar"] to 1, even though the variable $foo did not exist beforehand.

Is there something like declare(strict_types=1); that will enable checking this?

The reason I want this is so that I can more easily detect typos when I accidentally misspell a variable name.

Flimm
  • 136,138
  • 45
  • 251
  • 267
  • what do you mean doesn't exist? does `$foo = null;` exists or not? – Ali Jul 28 '17 at 12:55
  • Given the number of folks who come here for "undefined variable" and "undefined index" warnings (I've personally closed dozens of posts as dupes of https://stackoverflow.com/questions/4261133/php-notice-undefined-variable-notice-undefined-index-and-notice-undef) it's very much possible. I'm inclined to think you messed up the `error_reporting` settings. – ceejayoz Jul 28 '17 at 12:55
  • 3
    the code `$foo["bar"] = 1;` will create an array called `$foo` and load a value into `$foo['bar']` So you would have to manually check FIRST if `$foo` existed or not – RiggsFolly Jul 28 '17 at 12:56
  • @Ali I mean there is no code declaring `$foo` anywhere ever. – Flimm Jul 28 '17 at 12:57
  • 4
    This line of code `$foo["bar"] = 1;` **will create the array and load data into that occurance** – RiggsFolly Jul 28 '17 at 12:57
  • 1
    @RiggsFolly Ah, I didn't realise PHP did that. Is there a way to turn off automatic creation of `$foo` then in this case, and instead complain? – Flimm Jul 28 '17 at 12:58
  • 5
    Yes, move to `C` – RiggsFolly Jul 28 '17 at 12:58
  • 1
    This is sounding like an XY problem now. – ceejayoz Jul 28 '17 at 12:58
  • So there isn't a way in PHP, then. If there isn't, I'll accept that as an answer. – Flimm Jul 28 '17 at 12:58
  • Whoever voted to close this question because it's "unclear what I'm asking", please explain how it could possibly be more clear! – Flimm Jul 28 '17 at 13:00
  • I could move to C. Or Python. Or Javascript. Or Perl 5 (in strict mode). Or Java. They all detect this. But I can't, I'm using PHP. – Flimm Jul 28 '17 at 13:23

4 Answers4

5

Unfortunately, you are setting up an array with the command. Why would php throw an exception if you are setting up this?

It's like assigning a value to a variable and then asking why did PHP assign the value to the variable?

$foo["bar"] = 1;

print_r($foo);
// This prints the following: 
// Array ( [bar] => 1 )

The correct way of checking would be:

if(isset($foo))
{
  $foo['bar'] = 1;
}
else
{
  // do something if $foo does not exist or is null
}

Hope this helps! In short the answer to your question is no: there isn't a way to make PHP throw an exception or print a warning in your example.

Flimm
  • 136,138
  • 45
  • 251
  • 267
veggito
  • 258
  • 3
  • 13
  • 2
    Presumably OP would like to catch typos and have PHP complain if they're trying to treat an undefined variable like an array. So `isset` doesn't help here. Unfortunately PHP is being "too helpful" here… – deceze Jul 28 '17 at 13:04
  • That's useful information. It doesn't technically answer the question: is there a way to make it throw an exception? Or is there a way to make it display a warning? If the answer is no, that's OK, I just want to know the answer. – Flimm Jul 28 '17 at 13:04
  • Unfortunately, PHP doesn't work like other languages and is very lenient. So in short the answer is No :) – veggito Jul 28 '17 at 13:05
  • Updated the answer now to answer your question. – veggito Jul 28 '17 at 13:08
  • 1
    why? its the same reason this throws an error: `unset($foo);$foo.='bla';` it gives `Notice: Undefined variable: foo in file.php on line 1` - it SHOULD do the same with arrays too, but doesn't. – hanshenrik Jul 28 '17 at 13:10
  • Great, thanks! I edited the question for a tiny thing, and accepted your answer. – Flimm Jul 28 '17 at 13:10
  • 1
    @hanshenrik PHP simply creates implicit arrays on assignment: `$foo = []; $foo['bar']['baz'] = 42;`. Works. It's a feature. Also works if `$foo` isn't event defined. – deceze Jul 28 '17 at 13:18
  • @deceze Perl 5 has auto-vivification, which is what you're talking about, but it also does detect missing variables (in strict mode). I wish there was a way to enable some sort of strict mode or warning mode, like there is in Perl 5. – Flimm Jul 28 '17 at 13:25
  • @Flimm I'm hearing you wish you were using Perl 5… – deceze Jul 28 '17 at 13:26
  • @deceze Heh. In actuality, I prefer strict mode always on, but next best is an option to turn on strict mode, next best is an option to turn on warning mode, and the worst is no errors or warnings. Every language has its pros and cons, I'm not going to compare all of PHP to all of Perl 5, but in this tiny example, I do prefer Perl 5's way of doing over PHP's way of doing it. – Flimm Jul 28 '17 at 13:28
0

Here is my small example of error reporting:

error_reporting(E_ALL);

$foo = $bar; //notice : $bar uninitialized

$bar['foo'] = 'hello'; // no notice, although $bar itself has never been initialized (with "$bar = array()" for example)

$bar = array('foobar' => 'barfoo');
$foo = $bar['foobar'] // ok

$foo = $bar['nope'] // notice : no such index

In PHP $bar=1 it is just a string, in your case you declared an array like $bar['foo']=1. In this case, you initiate the array you don't need to give before that.

Nawin
  • 1,653
  • 2
  • 14
  • 23
  • You're correct in pointing out that `$bar['foo'] = 'hello';` doesn't show a warning if `$bar` doesn't exist. My question is: is there a way to make it do so? – Flimm Jul 28 '17 at 13:16
  • @Flimm i edit my explanation Sorry for my English, if you have any queries i will explain you. – Nawin Jul 28 '17 at 13:21
-2

is isset close enough? if(!isset($foo)){throw new Exception('$foo is not set!');}

this will throw an exception if $foo is not set - OR if $foo is NULL.

alternatively, if(!array_key_exists('foo',get_defined_vars())){throw new Exception('$foo is not set!');}

this will throw an exception if $foo is not set. and unlike isset(), this 1 notice the difference between not set at all, and set to NULL.

hanshenrik
  • 19,904
  • 4
  • 43
  • 89
  • 1
    I want `$foo["bar"] = 1` to throw an exception if `$foo` isn't defined already by enabling some sort of strict mode, or to at least print a warning by enabling some kind of warning mode. A similar answer was already posted and deleted. – Flimm Jul 28 '17 at 13:03
  • 1
    @Flimm unfortunately PHP is idiotic when it comes to modifying arrays. if an array is undefined, it is __IMPLICITLY__ created upon modification, without any warnings. no strict modes changes this fact :( i don't like it either, but short of forking the php interpreter source code, and fixing it yoursself, there's no way to fix this, afaik – hanshenrik Jul 28 '17 at 13:04
  • 1
    I would reword that and not use the word "retarded". – ʰᵈˑ Jul 28 '17 at 13:05
  • @ʰᵈˑ which word would you choose? `idiotic` comes to mind. as does `stupid` – hanshenrik Jul 28 '17 at 13:06
  • Thanks. Your comment is the answer to my question, I just want to know if there is a way or if there isn't, and if there isn't, that's a shame, and I won't waste my time looking any further. – Flimm Jul 28 '17 at 13:12
-2

You can throw an exception anywhere and everywhere :D keep in mind that CAN is not neccesseraly RECOMMENDED :D

The thing is any exception trown needs to be in a try block and caught if you want it to be handled.

upgrading @veggito code to meet your requirement would look something like this:

try {
    if(isset($foo))
        $foo['bar'] = 1;
    else
        throw new Exception('Seems like $foo is not set');
} catch (Exception $e)
  // do something with the exception, like $e->getMessage() and etc, or execute any code you wish
}

Read up more about exceptions, theres plenty of info around the net, starting maybe with http://php.net/manual/en/language.exceptions.php

  • I don't want to throw an exception manually, I want to enable some sort of warning or strict mode to make PHP automatically show a warning or throw an exception in my example. – Flimm Jul 28 '17 at 13:18
  • Ahhh, i see. Cant help you there buddy:) – Arnas Veberis Jul 28 '17 at 13:20
  • Not every exception "needs to be in a `try` block"… If you don't want to handle the exception you don't need to. That's often the point of throwing an exception. – deceze Jul 28 '17 at 13:20
  • @deceze thanks for clarifying, but i did mention "to be handled" Edit: made it more clear:) – Arnas Veberis Jul 28 '17 at 13:22