I'm working on some PHP code (that I didn't write). Here and there inside functions there's stuff like this:
$foo;
if ($someCondition) {
$foo="some value";
}
return $foo;
Just checking: that first $foo; on a line by itself - it has no effect whatsoever, right?
This is debug code left over from PHP3 or PHP4. These versions generated an E_NOTICE for just mentioning a variable (it was implicitly a read access):
$undef; // E_NOTICE
PHP5 however does not treat it as variable access anymore. So it goes ignored.
PHP3: Warning: Uninitialized variable or array index or property (undef)
PHP4: Notice: Undefined variable: undef
PHP5: silence
Your right. Maybe original developer come from another language and "declare" used vars.
Another way to write this code snippet is
if ($someCondition) {
return "some value";
}
return null;
It would have some impact if it were:
global $foo;
But in the form you posted, it is irrelevant.
Right, no need for it at all. Some languages require a variable to be declared, not PHP.
In PHP, you can even concatenate into an undeclared variable. PHP is the loose hipster of the programming world. Anything goes, man.
I would guess it's lazy instantiation. I'd change the line to $foo = "", which should have the same effect;
I wonder if they think that its the equivalent to defining a variable to prevent errors when strict error reporting is enabled - although it actually doesn't (define the variable) when its written like that
Related
I have an extension in Magento that is causing a bug in the system.log
The error message is below. It is at the return statement after the foreach statement
Notice: Undefined variable: struct
The method is
public function getFeeList($id)
{
//some code here but no statement that contains $struct
foreach($result2 as $kk=>$vv)
{
$struct[$vv['magikfees_id']]['tax_apply']=$vv['tax_apply'];
$struct[$vv['magikfees_id']]['tax_type']=$vv['tax_type'];
....
}
return $struct;
}
To my understanding is that you do not need to declare the PHP variables. So one question is
is the scope of the $struct variable in this case only in the foreach? OR
the code never gets in the foreach statement so $struct is not initialized?
is declaring it before the foreach going to resolve this issue? How can I declare it?
is the code actually working regardless of this notice?
You do not need to declare PHP variables, but you will get a notice when you don't. You can declare it as $struct = array();.
The code will work, but as $struct wasn't declared, it is likely you made a mistake (maybe a typo). PHP warns you for that by sending a notice. Although it does work without the declaration, it is recommended to declare it anyways.
No, the scope is the method getFeeList(). Once you've defined the variable you can access it later in your code in that particular method. If the code doesn't enter the foreach, the variable will be null.
Yes it will remove the notice error. You can do that by adding $struct = array(); before your foreach. Another workaround is to remove E_NOTICE from your error_reporting setting in php.ini or set ini_set() in the beginning of your code.
This particular piece of code should be working just fine even if you haven't defined the variable.
Although in PHP you are not required to define your variables it's a better coding practice to define them.
I'm building my first application with Kohana, and using a basic templating system within that. In my templates I want to echo variables for the various contents of the page, but only if each variable is set, and I want to keep the code in the templates as short as possible, so something like this:
<?=$foo?>
works fine if the variable is set, but if it's not I get a notice. So I thought a ternary operator would do the trick nicely:
<?=$foo?:''?>
according to the PHP manual, from 5.3 it's ok to leave out the middle part and the above should output nothing if the variable isn't set, but I still get an error notice."Notice: Undefined variable: foo in /"
I can get the desired result with a slight alteration to suppress the notice:
<?=#$foo?:''?>
but I know that's generally not beset practice and would like a better solution if possible, while still keeping the code to a minimum in the template files.
the following works, but it's not as concise (mainly because my actual variables can be quite long):
<?=isset($foo)?$foo:'';?>
am I missing something or doing something wrong?
The ternary operation is not meant to replace checking with isset() - it needs it's variable defined or else you get a notice.
Template engines usually offer a way to use a default value instead, but they also do not use pure PHP code. You you are out of luck here: Either suppress the notice, or use the longer code variant. Or ensure that every variable is set, which enables you to consider any notice an error.
To avoid notices for undefined variables, you can create custom function that takes first parameter by reference
function tplvar(&$value, $default = '') {
return ($value !== null) ? $value : $default;
}
<?=tplvar($foo, 'bar');?>
Uninitialized variables passed by reference will be seen as nulls.
I want to use a global variable setup where they are all declared, initialized and use friendly syntax in PHP so I came up with this idea:
<?
error_reporting(E_ERROR | E_WARNING | E_PARSE | E_NOTICE);
$GLOBALS['debugger'] = 1; // set $GLOBALS['debugger'] to 1
DEFINE('DEBUGGER','$GLOBALS["debugger"]'); // friendly access to it globally
echo "1:" . DEBUGGER . ":<br>";
echo "2:" . ${DEBUGGER}. ":<br>";
echo "3:" . $GLOBALS['debugger'] . ":<br>";
if (DEBUGGER==1) {echo "DEBUG SET";}
?>
generates the following:
1:$GLOBALS["debugger"]:
Notice: Undefined variable: $GLOBALS["debugger"] in /home/tra50118/public_html/php/test.php on line 8
2::
3:1:
How can there be an error with 2: when clearly $GLOBALS["debugger"] IS defined? And then not generate a similar notice with the test at line 10?
I think what I am trying to do is to force PHP to interpret a string ($GLOBALS["debugger"]) as a variable at run time i.e. a constant variable variable
Disclaimer: I agree with the comments, globals are generally a bad idea.
That said, there's a few questions here that are worth answering, and the concept of indirection is useful, so here goes.
${'$GLOBALS["debugger"]'} is undefined. You don't include the leading '$' when using indirection. So, the correct version would be define('DEBUGGER', 'GLOBALS["debugger"]').
But, this doesn't work either. You can only access one level down via indirection. So you can access the array $GLOBALS, but you can't access keys in that array. Hence, you might use :
define('DEBUGGER', 'debugger');
${DEBUGGER};
This isn't useful, practically. You may as well just use $debugger directly, as it's been defined as a global and will be available everywhere. You may need to define global $debugger; at the start of functions however.
The reason your if statement is not causing notices is because you defined DEBUGGER to be a string. Since you aren't trying to use indirection in that line at all, it ends up reading as:
if ("$GLOBALS['debugger']"==1) {echo "DEBUG SET";}
This is clearly never true, though it is entirely valid PHP code.
I think you may have your constants crossed a bit.
DEFINE('DEBUGGER','$GLOBALS["debugger"]'); sets the constant DEBUGGER to the string $GLOBALS["debugger"].
Note that this is neither the value nor the reference, just a string.
Which causes these results:
1: Output the string $GLOBALS["debugger"]
2: Output the value of the variable named $GLOBALS["debugger"]. Note that this is the variable named "$GLOBALS["debugger"]", not the value of the key "debugger" in the array $GLOBALS. Thus a warning occurs, since that variable is undefined.
3: Output the actual value of $GLOBALS["debugger"]
Hopefully that all makes sense.
OK, thanks to all who answered. I think I get it now, I am new to PHP having come form a C++ background and was treating the define like the C++ #define and assuming it just did a string replace in the precompile/run phase.
In precis, I just wanted to use something like
DEBUGGER = 1;
instead of
$GLOBALS['debugger'] = 1;
for a whole lot of legitimate reasons; not the least of which is preventing simple typos stuffing you up. Alas, it appears this is not doable in PHP.
Thanks for the help, appreciated.
You can not use "variable variables" with any of the superglobal arrays, of which $GLOBALS is one, if you intend to do so inside an array or method. To get the behavior you would have to use $$, but this will not work as I mentioned.
Constants in php are already global, so I don't know what this would buy you from your example, or what you are going for.
Your last comparison "works" because you are setting the constant to a string, and it is possible with PHP's typecasting to compare a string to an integer. Of course it evaluates to false, which might be surprising to you, since you expected it to actually work.
Huh, don't know what to search for, therefore have no idea if this is a duplicate or not.
Example:
function foo($bar){
switch($bar)
case UNDEFINED:
return 'foo';
break;
case DEFINED:
return 'bar';
break;
default:
return 'no foo and no bar';
}
}
echo foo(DEFINED); # edited: had $ before function call
// bar
echo foo(OUTPUT);
// no foo and no bar
PHP (version 5.3) doesn't throw any errors, but are there any drawbacks to this?
Undefined constants are interpreted as strings. In your case these would be two strings "DEFINED" and "UNDEFINED". From the PHP manual:
If you use an undefined constant, PHP
assumes that you mean the name of the
constant itself, just as if you called
it as a string (CONSTANT vs
"CONSTANT"). An error of level
E_NOTICE will be issued when this
happens.
EDIT Ignoring E_NOTICE is considered to be bad style, this is from PHP documentation:
Enabling E_NOTICE during development
has some benefits. For debugging
purposes: NOTICE messages will warn
you about possible bugs in your code.
For example, use of unassigned values
is warned. It is extremely useful to
find typos and to save time for
debugging. NOTICE messages will warn
you about bad style. For example,
$arr[item] is better to be written as
$arr['item'] since PHP tries to treat
"item" as constant. If it is not a
constant, PHP assumes it is a string
index for the array.
This more a question about the why then 'how-to', yet it has been annoying me for some days now. Currently I am doing some work with CodeIgniter and going back to PHP temporarily from Ruby, bugs me about the following scoping magic.
<?php $query = $this->db->get('articles', 2);
if ($query->num_rows() > 0)
{
foreach ($query->result_array() as $row)
{
$data[] = $row; # <-- first appearance here
}
return $data; # <--- :S what?!
}
As you can see, I am not exactly a PHP guru, yet the idea of local scope bugs me that outside the foreach loop the variable is 'available'. So I tried this out inside a view:
<?php
if($a==1)
{
$b = 2;
}
echo $b;
?>
Which result in an error message:
Message: Undefined variable: b
The PHP manual tells about the local scoping, yet I am still wondering why this happens and if there are special rules I do not know about. And it scares me :)
Thanks for sharing ideas,
Only functions create a new local scope. Curly braces by themselves do not. Curly braces are just an auxillary construct for other language structures (if, while or foreach).
And whereever you access any variable in a local scope doesn't matter. The local scope is an implicit dictionary behind the scenes (see get_defined_vars). You might get a debug notice by accessing previously undefined variables, but that's about it.
In your specific example it seems, you are even just operating in the global scope.
foreach does not create any variable scope in PHP so it is natural if variable is available outside foreach
for the second question the $a is not equal to the 1 hence $b is not initialized and throw notice when you access outside. If you assign value 1 to $a and test it you will wonder the notices will gone.
Here is nothing like scope.
See: http://php.net/manual/en/language.variables.scope.php
In php curly braces don't necessarily define a new scope for variables. (your first example)
In your 2nd example, $b is only set on a specific condition. So it is possible to be 'undefined' if this condition is not met.
Shyam, you are using a scripting language, not C++. It is typical for scripting languages like PHP or JavaScript not to have different scopes for each code block. Instead there is one scope for the whole function. This is actually quite handy if you consider your first example, but you obviously need to be careful as can be seen in your second one.
is $a equals to 1? If not $b=2 will never be evaluated!
Actually your first method should be giving you an error too.
You're using a variable that hasn't been declared as an array. I can't understand why you didn't get an error for that.
PHP doesn't have block scope, so whether it's inside IF or FOREACH is irrelevant. If it's available inside the method, you can use it inside the method.