Is this bad practice/can cause problems?
$_SESSION['stuff to keep']
As opposed to calling str_replace() on the indices.
This is bad practice, but not because of the space.
// file foo.php
$_SESSION['stuff to keep'] = 42;
// file bar.php
if ($_SESSION['stufft o keep'] == 42) frobnicate();
Here, your code is silently misbehaving, and the bug can take a while to be found. Good practice is to use a PHP-enforced name, such as a class constant:
$_SESSION[Stuff::TO_KEEP] = 42;
if($_SESSION[Stuff::TOO_KEEP] == 42)
// error: no constant TOO_KEEP in class Stuff
You may then define that constant to any constant you find interesting or readable, such as "stuff to keep" (with spaces). Of course, extract() and casting to object won't work anymore, but you shouldn't be doing that anyway with your session.
Allowing user-entered text into session keys is, of course, a blatant security fault.
You can do that, it'll work -- and even if I don't generally do it when I set the keys of my arrays "by hand", it sometimes happens when I get the keys from a file (for instance), and I've never had any problem with this.
Maybe this could cause some kind of a problem if you are using the extract functions, though. If it creates variables with spaces in their names (don't know if it will) it'll be difficult (but not impossible) to access your variables.
It won't cause a problem, but array keys are usually considered like variable names so should be chosen with the same considerations
Seems like adding unnecessary whitespace in my opinion... I don't usually use spaces. If you do, though, make sure you quote the array keys.
Related
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.
I have many session vars. Should I use this
$_SESSION[SessionHelper::ROUTING] = SessionHelper::MODULE_A;
class SessionHelper {
const ROUTING = 'SessionHelper.routing';
const MODULE_A = 1;
const MODULE_B = 2;
}
or this?
$_SESSION['routing'] = 1;
The first seems to be maintenanable but hard to read in some case. For example:
if(isset($_SESSION[SessionHelper::ROUTING]) &&
$_SESSION[SessionHelper::ROUTING] = SessionHelper::MODULE_A) {
....
The second is quite short but if there is a change, we must change everywhere the "routing" exist. Further more, it can pollute the session scope because the 'routing' string is so common.
If you really need a session helper (say: if you really need a class abstracting a PHP session), then use the $_SESSION superglobal only inside that class (and not outside). So you have the superglobal encapsulated and you can replace it with test-doubles.
Next to that, this depends on the use of the session store. I bet it's highly dynamic, so I don't see much value in specifying array keys as constants first w/o any futher use (e.g. valid/invalid key checks aren't done).
I hope this does not sound harsh, because it's not meant so. Please ask if something is unclear or you have further questions. As jprofitt wrote in his answer, preventing magic numbers is something very useful, but I'm not totally convinced, that you actually introduce them here or if it isn't just dynamic properties (especially if you create a session store class).
Magic strings and numbers are evil -- even if you're the only one who would need to use them. All it takes is forgetting to update them in one place and your entire application could malfunction.
As you mentioned with the maintainability of using constants, they can make implementing updates a lot simpler. Another benefit is you can document them and a lot of IDEs will pick that up and give help in case you forget what MODULE_A or MODULE_B is referring to (for example). While it might make you type in some extra characters, it's better than misspelling 'routing' somewhere and having to dig through your code to figure out why you're getting an error.
I have a string that stores some variables that must be executed to produce a result, for example:
define('RUN_THIS', '\$something.",".$somethingElse');
Which is then eval()-uated:
$foo = eval("return ".RUN_THIS.";");
I understand that eval is unsafe if the string that gets evaluated is from user input. However, if for example I wanted to have everything run off Facebook's HipHop which doesn't support eval() I couldn't do this.
Apparently I can use call_user_func() - is this effectively the same result as eval()? How is deemed to be secure when eval() isn't, if that is indeed the case?
Edit:
In response to the comments, I didn't originally make it clear what the goal is. The constant is defined in advance in order that later code, be it inside a class that has access to the configuration constants, or procedural code, can use it in order to evaluate the given string of variables. The variables that need to be evaluated can vary (completely different names, order, formatting) depending on the situation but it's run for the same purpose in the same way, which is why I currently have the string of variables set in a constant in this way. Technically, eval() is not unsafe as long as the config.php that defines the constants is controlled but that wasn't the point of the question.
Kendall seems to have a simple solution, but I'll try to answer your other question:
Apparently I can use call_user_func() - is this effectively the same result as eval()? How is deemed to be secure when eval() isn't, if that is indeed the case?
call_user_func is actually safer than eval because of the fact that call_user_func can only call one user function. eval on the other hand executes the string as PHP code itself. You can append '; (close the string and start a new "line" of code) at the end of the string and then add some more code, add a ;' (end the line of code and start another string so that there is no syntax error), thus allowing the constant RUN_THIS to contain lots of PHP code that the user can run on the server (including deleting all your important files and retrieving information for databases, etc. NEVER LET THIS HAPPEN.
call_user_func doesn't let his happen. When you run call_user_func_array($func, $args) the user can only run a restricted set of functions because: (a) the function has to be user defined (b) you can manipulate $func to ensure the user isn't able to run any function he/she wants either by checking that $func is in a list of "allowed functions" or by prefixing something like user_ to the function names and the $func variable itself (This way the user can run only functions beginning with user_.
I can't see any reason why you can't just use double-quote string building.
$foo = "\$something,$somethingElse";
I just started using php arrays (and php in general)
I have a code like the following:
languages.php:
<?php
$lang = array(
"tagline" => "I build websites...",
"get-in-touch" => "Get in Touch!",
"about-h2" => "About me"
"about-hp" => "Hi! My name is..."
);
?>
index.php:
<div id="about">
<h2><?php echo $lang['about-h2']; ?></h2>
<p><?php echo $lang['about-p']; ?></p>
</div>
I'm using hypens (about-h2) but I'm not sure if this will cause me problems in the future. Any suggestions?
Between camel case and underscores it's personal taste. I'd recommend using whatever convention you use for regular variable names, so you're not left thinking "was this one underscores or camel case...?" and your successor isn't left thinking about all the ways they could torture you for mixing styles. Choose one and stick to it across the board.
That's why hyphens is a very bad idea - also, rarely, you'll want to use something like extract which takes an array and converts its members into regular variables:
$array = array("hello" => "hi", "what-up" => "yup");
extract($array);
echo $hello; // hi
echo $what-up; // FAIL
Personally, I prefer camel case, because it's fewer characters.
I'm actually surprised no one said this yet. I find it actually pretty bad that everyone brings up variable naming standards when we are talking about array keys, not variables.
Functionally wise, you will not have any problems using hyphens, underscores, camelCase in your array keys. You can even use spaces, new lines or null bytes if you want! It will not impact your code's functionality^.
Array keys are either int or string. When you use a string as a key, it is treated as any other string in your code.
That being said, if you are building a standardized data structure, you are better off using the same standard you are using for your variables names.
^ Unless you are planning to typecast to a (stdClass) or use extract(), in which case you should use keys which convert to valid variable names in order to avoid using ->{"My Key Is"} instead of ->myKeyIs. In which case, make sure your keys conform to [a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*.
You can use what ever feels most compfortable, however, I would not recommend using hypehens.
The common approach is to use camelCase and that is what a lot of standards in frameworks ask for.
I recommend using this.
$thisIsMyVariable
$this-is-not-how-i-would-do-it
Also, you can find that using hyphens could make your variables appear like subtracting. So you have to then use
$object->{”Property-Here”}
Its just not nice. :(
Edit, sorry I just saw that you asked about the question in Array, not variables. Either way, my answer still applies.
I would append all into one word. If not appending it all together, I would either shorten it or use _.
In the long run, whatever you decide to choose just be consistent.
Many folks, including Zend, tell programmers to use camel case, but personally I used underscores as word separators for variable names, array keys, class names and function names. Also, all lowercase, except for class names, where I will use capitals.
For example:
class News
{
private $title;
private $summary;
private $content;
function get_title()
{
return $this->title;
}
}
$news = new News;
The first result in Google for "php code standards" says:
use '_' as the word separator.
don't use '-' as the word separator
But, you can pretty much do whatever you want if you don't already have standards to follow. Just be consistent in what you do.
When looking at your code: Maybe you can even avoid some work with arrays and keys if you use something like gettext http://de2.php.net/manual/en/intro.gettext.php for your internationalization efforts from the very beginning.
This will finally result in
<h2><?php _("About me..."); ?></h2>
or
<?php
$foo = _("About me...");
...
?>
I strongly recommend using underscore to separate words in a variable especially where the language is case sensitive.
For non case sensitive languages like vb, camelCase or CamelCase is best.
Is it okay to use array without single or double quotion like $array[key]? I thought it is bad because PHP look for constant first if I don't use single or double quotation. One of my colleagues told me that it does not matter.
What do you guys think?
It is not considered as OK -- even if it will work in most cases.
Basically, when PHP sees this :
echo $array[key];
It will search for a constant, defined with define, called key -- and, if there is none, if will take the 'key' value.
But, if there is something like this earlier in your code :
define('key', 'glop');
It will not take
echo $array['key'];
anymore ; instead, it'll use the value of the key constant -- and your code will be the same as :
echo $array['glop'];
In the end, not putting quotes arround the key's name is bad for at least two reasons :
There is a risk that it will not do what you expect -- which is very bad
It might, today...
But what about next week / month / year ?
Maybe, one day, you'll define a constant with the wrong name ;-)
It's not good for performance :
it has to search for a constant, before using 'key'
And, as said in a comment, it generates notices (even if you disable error_reporting and display_errors, the notices/warnings/errors are still generated, even if discarded later)
So : you should not listen to that guy on this point : he is wrong : it does matter.
And if you need some "proof" that's "better" than what people can tell you on stackoverflow, you can point him to this section of the manual, as a reference : Why is $foo[bar] wrong?
This is not okay and to add to what others have said, it will trigger an error in most cases:
8 Notice Use of undefined constant key - assumed 'key' in file: 'index.php' on line 46
See the section in the PHP Manual for "Why is $foo[bar] wrong?" under "Array do's and don'ts" on this page: http://php.net/manual/en/language.types.array.php
This is wrong and will auto-define a constant:
$var = $array[bar];
This usage however is correct:
$var = "string $array[bar] ...";
For compatibility with PHP2 this old syntax is still allowed in string context. Quoting the key would lead to a parse error, unless you also use { curly braces } around it.
From the PHP Manual - Why is $foo[bar] wrong?
Always use quotes around a string literal array index. For example, $foo['bar'] is correct, while $foo[bar] is not. But why? It is common to encounter this kind of syntax in old scripts:
<?php
$foo[bar] = 'enemy';
echo $foo[bar];
// etc
?>
This is wrong, but it works. The reason is that this code has an undefined constant (bar) rather than a string ('bar' - notice the quotes). PHP may in future define constants which, unfortunately for such code, have the same name. It works because PHP automatically converts a bare string (an unquoted string which does not correspond to any known symbol) into a string which contains the bare string. For instance, if there is no defined constant named bar, then PHP will substitute in the string 'bar' and use that.
There is some more examples in the manual for you to check out.
Unless the key actually is a constant, there is no reason for you not to be putting quotes around the key.
The way PHP works is it looks for the constant value of what you've put, but it takes the string representation of it if the constant cannot be found.
If someone were to edit your code down the road and add a constant with that key name, it would just cause more headaches.
It's bad practice to not quote key values, for a number of reasons:
Potential collisions with meaningful symbol names, such as define'd constants.
Some keys can't be expressed without quoting (for instance, the key "]").
Bad habits can bite you later on (namely in regards to #1 and #2).
Performance - searching for define's takes time.
If you're wanting to avoid typing quotes around names that are just standard elements of a thing you're passing around a lot, perhaps you might want to use objects instead, which take a object->property syntax instead of an $array["element"] syntax.