0

My Magento environment is set to error_reporting(E_ALL); and I'm debugging a bunch of warnings.

I have a loop and markup that looks like this:

foreach ( $vars as $key => $value) {
    $value  = is_array($value) ? $value: trim($value);
    ${$key} = ( !empty($value) ? $value: '' );
};
// echo $type; die(); <----- die() shows value correctly
echo $type; // <----- get notices

$fieldType = ( $type == 'money' ? 'number' : 'text' );
echo "<div class=\"input-box {$fieldType}\">";
... rest of code here

My end goal is to create a string and throw variables into it; so the checking should be done prior to that.

I am getting this error notice Undefined variable: type when trying to use the dynamically created variable. If I echo $type; die(); than I get a value just fine. If I check get_defined_vars() I see my $type variable in the array so I know it's there. I just can't get the variable to be pre-set inside of the initial loop.

I've tried something like ${$key} = ( !empty($value) ? $value: 'something' ); to no avail as well.

This is my var_dump

array(11) {
  ["title"] => string(23) "Name:"
  ["instructions"] => string(0) ""
  ["isrequired"] => string(1) "1"
  ["classnames"] => string(0) ""
  ["defaultval"] => string(0) ""
  ["page"] => string(1) "1"
  ["type"] => string(4) "text"
  ["id"] => string(6) "Field1"
  ["requiredstar"] => string(0) ""
 }
GregT
  • 508
  • 3
  • 15
  • 1
    So `$vars` is something like `['type'=>'something']`? – colburton Jul 19 '17 at 17:23
  • Array ( [title] => First Name: [instructions] => [isrequired] => 1 [classnames] => [defaultval] => [page] => 1 [type] => text [id] => Field1 – GregT Jul 19 '17 at 17:26
  • Possible duplicate of [PHP: "Notice: Undefined variable", "Notice: Undefined index", and "Notice: Undefined offset"](https://stackoverflow.com/questions/4261133/php-notice-undefined-variable-notice-undefined-index-and-notice-undef) – Qirel Jul 19 '17 at 17:26
  • Is `$type` used anywhere in the rest of the code? Are you sure the error is occurring in the snippet you've shown? – WheatBeak Jul 19 '17 at 17:35
  • @WheatBeak The error happens directly after the loop ends if I were to echo it; so it had no chance to be over written. The loop rest in a function so it's not contaminated by outside sources. – GregT Jul 19 '17 at 17:37
  • I think your environment is just haunted. – WheatBeak Jul 19 '17 at 17:43
  • 1
    Much like http://php.net/manual/en/function.extract.php except more code. – AbraCadaver Jul 19 '17 at 17:59

1 Answers1

0

Are you sure $type is always being set? Your code will only work so long as $vars has a key in it named type. If, for instance, $vars is an empty array, there will be no type key and you will get the error you are getting.

You could also try setting a default:

$type = '';
foreach ( $vars as $key => $value) {
    $value  = is_array($value) ? $value: trim($value);
    ${$key} = ( !empty($value) ? $value: '' );
};

$fieldType = ( $type == 'money' ? 'number' : 'text' );

From some of your comments, it sounds like this is related to an API call. I would suggest that you have some code design problems here. Your code implicitly assumes that the data should contain a key named type, and (as written), your program will encounter an error if that key is missing. You don't want that to happen. Rather, if this is a required parameter for an API call, you should be explicitly checking for its presence and then returning an API error if it is missing. It should not be possible for an input mistake to result in an actual error (or notice) in PHP. Always assume that someone is going to call your API wrong (or assume that the API you are calling will return data wrong). Never code under the assumption that everyone else always does things perfectly.

Another way to handle this would be to simply leave the data as an array. Is there a particular reason why you are trying to unpack this data array into variables? While PHP will allow you to work with variables by variable name, as you are doing (${$key}), it tends to cause confusion because now there is no longer a clear connection between a given variable and when it was last initialized/updated. In the case of a required parameter especially, I think you are better of manually unpacking it:

$type = $vars['type'] ?? '';
if ( !$type )
    // handle error here

Edit To add one more thought

This one is a bit of a stretch, but it's the only idea I have. I started this as a comment but moved it to my answer so that I would have more room.

I wonder if it is possible that you have an encoding error. The idea is that if the API was returning data in the wrong encoding, and you used that data to assign to a variable, it might be possible for a variable to be defined but to be effectively inaccessible for you because the character set in PHP's memory doesn't match the character set of your text editor. I've been bitten by this same basic bug in other contexts. It's the modern equivalent of typing a variable name with an uppercase 'o' when the actual name has a zero.

Again, it seems unlikely, but it is easy to check. What you should do is forget about your foreach loop. The key to good debugging is isolation anyway. Before you even get to your foreach loop, do a vardump on your $vars variable and then do these two lines of code:

if ( !isset( $vars['type'] ) )
    throw new \Exception( "Yup, encoding error (or other really weird bug)" );

If var_dump thinks the array has a type key, but isset doesn't think the array has a type key, then there is definitely something funky going on. If however isset() agrees with var_dump(), then I would say that you are dealing with a more run-of-the-mill error hiding in your code somewhere. In that case, I think your best next step is to ditch your foreach loop and use a more explicit array unpacking, as I discussed above.

Conor Mancone
  • 1,940
  • 16
  • 22
  • $type is always set no matter what from the API I'm getting the $vars from. Yes if I manually set any of the variables to ' '; above the loop it works fine; but I'd prefer setting the default in the loop. That's what the ${$key} = ( !empty($value) ? $value: '' ); was trying to accomplish. – GregT Jul 19 '17 at 17:32
  • If your `$vars` array has a key in it named `type` then the code you have listed should work fine with no errors or notices. Somewhere you are making an assumption that is incorrect. Unfortunately there isn't really enough code here for us to figure out what that wrong assumption is. The simple next debugging step is to dump your data: before the `$fieldType = ` line that is causing the crash, do a print_r on $vars. I don't think anyone other than you can solve this with the data you have provided. – Conor Mancone Jul 19 '17 at 18:19
  • I've added a var dump – GregT Jul 19 '17 at 19:00
  • @GregT I added some more thoughts to my answer. – Conor Mancone Jul 19 '17 at 20:08
  • I tracked down the issue. It was from another function that fed into the above markup; but did not have all of the same information, that was causing the issue. Thanks for your input and help! – GregT Jul 21 '17 at 21:05