Is it possible to parse the contents of a constant in PHP?
For example,
define('WHO_AM_I', 'My name is $_SESSION['who_am_i'].'); // setup the constant string
echo eval(WHO_AM_I); // something like this -- but the eval() returns an error
Please note that I do not know the value of the _SESSION var until I actually use the constant later in the script stream.
Thanks.
AMENDED WITH REASON FOR WANTING TO DO THIS
I want to pull "hard coding" out of my script and give the user the ability to configure certain taxonomy in their site. So while I was doing this I also wanted to create a quasi-dynamic constant that I thought I might be able to parse later in the script.
If it can't be done...then it can't be done.
Don't shoot me for asking the question though.
A FINAL COMMENT TO AVOID ALL THIS CONFUSION
The purpose of my question has nothing to do with the eval() function. I am actually regretting having put it in there in the first place.
I put the eval() in the question simply to demonstrate to stackoverflow members that I did a bit if prep on my question rather than asking an open ended -- hey give me a solution without having offered any stab at it myself. So please disregard the eval().
All I want to know is can I somehow craft a define() in an way that makes the assigned value parse-able later in my script. That's it, that's all.
AMENDMENT C
I know I can do the following although I don't want to do it this way:
define('PARSE_ABLE_CONSTANT_PART_A', 'My name is ');
define('PARSE_ABLE_CONSTANT_PART_B', '.');
...later down the script road...
echo PARSE_ABLE_CONSTANT_PART_A . $_SESSION['who_am_i'] . PARSE_ABLE_CONSTANT_PART_B;
I just don't want to do it this way if I can make it slicker using an embedded var in the constant.
This seems really fishy, as other users have pointed out. You could do something like this if you wanted:
define('WHO_AM_I', 'echo \'My name is \'.$_SESSION[\'who_am_i\'];');
eval(WHO_AM_I);
This will always just echo the variable. You need to eval an expression afaik.
Just read your edit. I think you would be better suited with an .ini file, or maybe a static class with static properties. Makes it much more flexible, and you avoid the eval. You are talking user-generated content from what I can see - subjecting that to an eval call seems highly insecure.
A quick example of a static class you could use:
<?php
class myConstants{
public static function _($key){
switch($key){
case "WHO_AM_I":
return "My name is ".$_SESSION['who_am_i'];
break;
case "OTHER_CONSTANT":
// does some other evaluation and returns a string
break;
}
throw new Exception("Constant isn't defined");
}
}
?>
Then you can just echo myConstants::_('WHO_AM_I');
Constants by definition don't allow you to set it with dynamic content.
Here is a quote from the php manual:
As the name suggests, that value cannot change during the execution
of the script
You can see more by going here
You might be thinking of magical constants
Related
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've been going through the code of a Wordpress plugin and found the following:
eval( '?>' . $foo . '<?php ' );
I'm curious if there is some specific situation I'm unaware of that this would be the right way to output the $foo variable. Is this just a case of the plugin author being wacky or is there something I should know? I would have just used echo...
UPDATE:
Thanks for all the great feedback. I'm face palming now that I didn't think of the template scenario. Specifically, this happens in the WP Super Cache plugin. I guess I'll have to have a closer look to see if it's necessary. I thought Super Cache cached the html output by Wordpress after all the PHP had already been processed...
In this instance, $foo is a string that (presumably) can contain in-lined PHP code. As such, to execute this PHP code, the string needs to be eval'ed.
That said, the use of eval is generally frowned upon, apart from in a very narrow set of circumstances, as it can lead to the execution of malicious code. (i.e.: If there's any possibility that $foo is a user-provided string, then use of eval could lead to disastrous consequences.)
See the existing When is eval evil in php? question/answers for more information.
That's not outputting the variable. $foo most likely contains a template, with other <?=$code();?> snippets embbeded.
The closing and opening PHP marker are used in this eval to switch from inline code, back to HTML mode. This eval() more or less amounts to:
include("data:,$foo"); // treat $foo string as if it was include script
Let me repeat it again: c.r.a.p
If eval() is the answer, you're almost
certainly asking the wrong question.
Rasmus Lerdorf
My goal just debug
function dbg($var){
echo "you have passed $var";
}
call dbg($test)
output:
you have passed test
call dbg("var")
output:
you have passed "var"
In php .anyone could help me to do that?
Try this if $var is a global variable:
function dbg($var){
echo "you have passed {$GLOBALS[$var]}";
}
Well, the second case is fairly straightforward - you're passing a string and you want to display the string. No worries.
But for the first case, I'm afraid the answer is: No you can't.
Once inside the function, PHP doesn't know anything about the variable that was passed into it other than the value.
I can't really see that it would be of much value though. It would be trivial to change your code to pass in a name and a value -- ie something like this:
function dbg($name,$value) {
print "You passed $name, and the value was $value";
}
dbg('test',$test);
That's not really all that great either though -- you may as well just use print_r() and friends.
If you really want more powerful debugging tools, you should look into xDebug. It's a proper debugging tool for PHP, which allows you to step through the code line-by-line, and see the contents of variables at any point during the program run (among many other good features). It also integrates nicely with several popular IDEs.
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 am not really clear about declaring functions in php, so I will give this a try.
getselection();
function getselection($selection,$price)
{
global $getprice;
switch($selection)
{
case1: case 1:
echo "You chose lemondew <br />";
$price=$getprice['lemondew'].'<br>';
echo "The price:".$price;
break;
Please let me know if I am doing this wrong, I want to do this the correct way; in addition, php.net has examples but they are kind of complex for a newb, I guess when I become proficient I will start using their documentation, thank you for not flaming.
Please provide links that might also help me clear this up?
Your example seems valid enough to me.
foo('bar');
function foo($myVar)
{
echo $myVar
}
// Output: bar
See this link for more info on user-defined functions.
You got off to a reasonable start. Now all you need to do is remove the redundant case 1:, close your switch statement with a } and then close your function with another }. I assume the global array $getprice is defined in your code but not shown in the question.
it's good practice to declare functions before calling them. It'll prevent infrequent misbehavior from your code.
The sample is basically a valid function definition (meaning it runs, except for what Asaph mentions about closing braces), but doesn't follow best practices.
Naming conventions: When a name consists of two or more words, use camelCase or underscores_to_delineate_words. Which one you use isn't important, so long as you're consistent. See also Alex's question about PHP naming conventions.
Picking a good name: a "get" prefix denotes a "getter" or "accessor"; any method or function of the form "getThing" should return a thing and have no affects visible outside the function or object. The sample function might be better called "printSelection" or "printItem", since it prints the name and price of the item that was selected.
Globals: Generally speaking, globals cause problems. One alternative is to use classes or objects: make the variable a static member of a class or an instance member of an object. Another alternative is to pass the data as an additional parameter to the function, though a function with too many parameters isn't very readable.
Switches are very useful, but not always the best choice. In the sample, $selection could easily hold the name of an item rather than a number. This points to one alternative to using switches: use an index into an array (which, incidentally, is how it's done in Python). If the cases have the same code but vary in values used, arrays are the way to go. If you're using objects, then polymorphism is the way to go--but that's a topic unto itself.
The $price parameter appears to serve no purpose. If you want your function to return the price, use a return statement.
When you called the function, you neglected to pass any arguments. This will result in warnings and notices, but will run.