An easier way to define these variables? - php

$access_community = 1;
$access_content = 1;
$access_tools = 1;
$access_administrator = 0;
$access_moderator = 0;
Just wondering if there's an easier way to write this using an array? This seems like overkill.
Thanks!

You could either do something like (sucks for readability):
$access_community = $access_content = $access_tools = 1;
$access_administrator = $access_moderator = 0;
Or as already been said, using an array:
$access = array('community' => 1,
'content' => 1,
'tools' => 1,
'administrator' => 0,
'moderator' => 0);

If you had more variables, then something like:
$access = array( 'community' => 1, 'content' => 1, ... );
foreach ($access as $k => $v) {
$real_name = 'access_' . $k;
$$real_name = $v;
}
Might work, but it's not that nice, and probably even more overkill than your code is now. I think that what you have isn't too bad, to be honest!
If you're interested, this uses indirect references or "variable variables" to actually define new variables. I'm not too sure about scope here, however.
Of course, if you can, try and just use the array directly, rather than relying on the variables being there - arrays can be changed and passed around, unlike variables.

Because you hardly can explain what are you doing and why, we can only guess.
It looks like some ACL.
So, the only sensible way to set these variables is to store it in the database. Especially if there will be dozens of them in the future.
http://phpgacl.sourceforge.net/ is probably what are you looking for
So, your variables will be assigned with values from database.
As for the answer you asked - no, there is no other way to initialize different variables with different values. You have to explicitly set every variable value. So, you have to define a variable name and a variable value somehow. So,
$variable = value
is the most plain and way convenient way.
You can make it more complicated way, but at the core it remains the same: "variable name - variable value" pairs

Related

Can't understand syntax error, unexpected '=' in eval()'d code

I've search different forms but didn't understand how to solve the problem first found here (first link, second link) but its giving me the error in eval. I can't figure it out how to solve in that code in foreach loop.
foreach($_POST as $key => $value) {
if(!strstr($key, 'removeFile')){
//initialize variables using eval
eval("$" . $key . " = '" . sanitize($value) . "';");
}
}
First, the issues I have with your code:
eval is very, very rarely needed, and extremely dangerous, use with caution. I've been developing in PHP for over 10 years, and never really encountered a situation that needed eval. This is no exception. Eval is not required
You're sanitizing the entire $_POST array. That's great, but there are special functions for doing that, like: filter_input_array, array_filter and many, many more... not to mention ready-made, open source projects and frameworks that already contain a solid request validation component.
Always check the return values of functions, which you seem to be doing with strstr, but be weary of functions that return different types (like strstr: it returns false if the needle isn't found, but returns 0 if the needle is found at the start of the haystack string). Your if statement might not work as intended.
You're assuming sanitize($value) values will not contain any single quotes. Why? Because if they do, you'll end up with a syntax error in your evaled string
Be that as it may, you could easily write your code using variable variables and add a simple check not to step on existing variables in scope:
$sanitized = array_filter($_POST, 'sanitize');//call sanitize on all values
foreach ($sanitized as $key => $value)
{
if (!isset($$key) && strstr($key, 'removeFile') === false)
$$key = $value;
}
But really, $_POST values belong together, they are part of the request, and should remain grouped... either in an array, or in an object of some sort. Don't assign each value to its own variable, because pretty soon you'll loose track of what variables are set and which are not. Using an unset variable creates that variable, assigning value null, so what you have now makes for very error-prone code:
//request 1: POST => id=123&foo=bar
foreach ($sanitized as $k => $v)
$$k = $v;
$query = 'SELECT x, y, z FROM tbl WHERE id = ?';//using posted ID as value
$stmt = $db->prepare($query);
$stmt->execute(array($id));
All is well, because $id was set, but never trust the network, don't assume that, just because $_POST is set, all the keys will be set, and their values will be correct:
//request 2: POST => foo=bar&page=2
foreach ($sanitized as $k => $v)
$$k = $v;
$query = 'SELECT x, y, z FROM tbl WHERE id = ?';//using posted ID as value
$stmt = $db->prepare($query);
$stmt->execute(array($id));//id is null
Now we have a problem. This is just one example of how your code might cause issues. Imagine the script grows a bit, and look at this:
//request 3: POST => id=123&foo=bar&page=2
foreach ($sanitized as $k => $v)
$$k = $v;
//$id is 123, $foo is bar and $page = 2
$query = 'SELECT x, y, z FROM tbl WHERE id = ? LIMIT 10';//using posted ID as value
//a lot more code containing this statement:
$page = someFunc();
$log->write('someFunc returned log: '.$page);
//more code
$offset = 10*($page-1);//<-- page is not what we expected it to be
$query .= sprintf(' OFFSET %d', $offset);
$stmt = $db->prepare($query);
$stmt->execute(array($id));
Now this may seem far-fetched, and idiotic, but believe me: all of these things happen, more than I care to know. Adding some code that accidentally overwrites an existing variable that is used further down happens all the time. Especially in procedural code. Don't just blindly unpack an array. Keep that single variable, and use the keys to avoid:
grey hair
sudden, dramatic baldness
loss of sanity
bleeding ulcers
In a work environment: catastrophic loss of data
Sudden loss of job
... because code like this makes unicorns cry, and bronies will hunt you down
As the first answer to the post you linked to, the problem is that when using double quotes PHP thinks your eval() code starts with a variable. As that is not the case you have two options. Use single quotes and remember to escape the single quotes declaring a string in the code or escape the dollar sign.
Bonus note
There exist more elegant solutions to the problem you are trying to solve. The best solution I can think of is using the extract function. This gives to two main benefits.
It works with all associative arrays
You can specify different flags that can help you distinguish the extracted variables apart and avoid variable injection.
One flag you can use is EXTR_PREFIX_ALL. This will prefix all the extracted variables with your own prefix. You would then access the variables with a prefix of 'PREFIX_' like the following:
$array = [
'variable1' => 'foo',
'variable2' => 'bar'
];
extract($array, EXTR_PREFIX_ALL, 'PREFIX_');
$value1 = $PREFIX_variable1; // Equals: foo
$value2 = $PREFIX_variable2; // Equals: bar
A little on code injection
Suppose you have some code:
$login = false;
The $login variable determines if a user is logged in or not.
Then somewhere you use the ´extract´ function with an array of the following without using any flags.
$array = [
'login' => true,
'foo' => 'bar'
];
extract($array);
Now your $login variable would be set to true and the user posting the data would have overwritten the initial setting and gained access to your website without a valid login. Bear in mind this is a over simplified example, but nonetheless valid.
To overcome this you can use the flag EXTR_SKIP or prefix them like I previously showed. The EXTR_SKIP flag will skip the array element if a variable with the same name already is defined. So now your code would not overwrite your $login variable.
extract($array, EXTR_SKIP); // Skip existing variables
// Or
extract($array, EXTR_PREFIX_ALL, 'prefix'); // Prefix them all.
Hope this can guide to the right choice for your needs.
Regards.

PHP variable variable name containing index

$arr[0]=123;
$a="arr[0]";
echo $$a;
gives me error
Notice: Undefined variable: arr[0]
on the last line.
What should I do to make it work?
EDIT:
Above is the simplification of what I want to do. If someone wants to know why I want to do this, then here's the explanation:
This is something like what I want to do:
if(condition){
$a=$arr1[0][0];
$b=$arr1[0][1];
$c=$arr1[0][2];
}
else{
$a=$arr2[0];
$b=$arr2[1];
$c=$arr2[2];
}
I can compact it like this:
if(condition)
$arr=$arr1[0];
else
$arr=$arr2;
$a=$arr[0];
$a=$arr[1];
$a=$arr[2];
But I wanted to try doing this using variable variable:
if(condition)
$arr="$arr1[0]";
else
$arr="$arr2";
$a={$$arr}[0];
$b={$$arr}[1];
$c={$$arr}[2];
Sure, we don't need variable variables as we can still code without them. I want to know, for learning PHP, why the code won't work.
Now that you said what you’re actually trying to accomplish: Your code doesn’t work because if you look at $arr1[0][0], only arr is the variable name; the [0] are special accessors for certain types like strings or arrays.
With variable variables you can only specify the name but not any accessor or other operation:
A variable variable takes the value of a variable and treats that as the name of a variable.
Your solution with the additional variable holding the array to access later on would be the best solution to your problem.
What you are trying to do just won't work - the code $arr[0] is referencing a variable called $arr, and then applying the array-access operator ([$key]) to get the element with key 0. There is no variable called $arr[0], so you cannot reference it with variable-variables any more than you could the expression $foo + 1 .
The real question is why you want to do this; variable variables are generally a sign of very messy code, and probably some poor choices of data structure. For instance, if you need to select one of a set of variables based on some input, you probably want a hash, and to look up an item using $hash[$item] or similar. If you need something more complex, a switch statement can often cover the cases you actually need.
If for some reason you really need to allow an arbitrary expression like $arr[0] as input and evaluate it at runtime, you could use eval(), but be very very careful of where the input is coming from, as this can be a very easy way of introducing security holes into your code.
FROM PHP DOC
In order to use variable variables with arrays, you have to resolve an ambiguity problem. That is, if you write $$a[1] then the parser needs to know if you meant to use $a[1] as a variable, or if you wanted $$a as the variable and then the [1] index from that variable. The syntax for resolving this ambiguity is: ${$a[1]} for the first case and ${$a}[1] for the second.
Use
echo ${$a}[0]; // 123
Edit : Based on your edit you can simply have
list($a, $b, $c) = (condition) ? $arr1[0] : $arr2;
Or
$array = (condition) ? $arr1[0] : $arr2;
$a = $array[0];
$b = $array[1];
$c = $array[2];
As pointed out you don't need variable variables. To get a PHP variable variable name containing index (a key) use array_keys() or array_search() or other array parsers. From php's site:
$array = array(0 => 'blue', 1 => 'red', 2 => 'green', 3 => 'red');
$key = array_search('green', $array); // $key = 2;
$key = array_search('red', $array); // $key = 1;
You could also use the following (using $var= instead of echo):
$arr[0]=123;
$arr[1]=456;
foreach ($arr as $key => $value) {
echo "arr[{$key}] = {$value} \r\n";
}
Which outputs:
arr[0] = 123
arr[1] = 456
But I don't see why you'd do that, since the whole point of the array is not doing that kind of stuff.

define multiple results all at the same time in php

I have $config variable that have arrays inside it. In smarty I assign the variable like this:
$smarty->assign('config', $config);
when I call it, I used this : {$config.wateverarrayyouwant}
now I want to do the same thing with php. I want to define them in the same manner. How can I define all the arrays in $config in just one line?
I only know how to define a variable one at a time by using this :
define('wateverarrayyouwant', $config['wateverarrayyouwant']);
I tried changing wateverarrayyouwant to a variable because it can be any array :
define('$wateverarrayyouwant', $config[$wateverarrayyouwant]);
but the code above does not work. what is a good way to achieve what I want?
If you want to create a define for each key value pair in the array you can use:
<?php
foreach($config as $key => $value) {
define($key, $value);
}
I will note however that you cannot define array values, all define's must be scalar:
The value of the constant; only scalar and null values are allowed. Scalar values are integer, float, string or boolean values.
If you check the OP's answer for further explanation of what he's trying to achieve, it can be done with:
<?php
foreach($config as $key => $value){
$$key = $value;
}
?>
This question cannot be done. because I am trying to define a variable as a constant. I was just thinking about how can I reduce the letters for variables and never though that I better leave them alone. Logically, why do somebody need to change $config[$wateverarrayyouwant] to wateverarrayyouwant. I was only thinking about maintaining a neat code. but now I am thinking about it.. it is better to leave it as it is : $config[$wateverarrayyouwant]
This can be done with:
foreach($config as $key => $value){
$$key = $value;
}
You may not even want to use define here. define is used to create constants not plain variables and that carries with it certain connotations:
they are immutable for the life of the script
they must be scalar
If you just want an array variable then define it like normal with:
$whatever = array(
'key1' => 'value1'
);

Have I understood sessions/multi-dimensional arrays properly?

Am I doing the following correctly?
I have an array, which I want to save to a session, so I can use it later in my web application:
$data = array(
"id" => $_POST["id"],
"r1" => $_POST["r1"],
"r2" => $_POST["r2"],
"r3" => $_POST["r3"]);
I save it to a session like this:
$_SESSION['settings'] = $data;
Now, I am not sure how to make use of this later in my application.
Do I do the following
$id = $_SESSION['settings']['id'];
$r1 = $_SESSION['settings']['r1'];
or do I do the following
$data = $_SESSION['settings'];
$id = $data['id'];
$r1 = $data['r1'];
or do I do something else?
Both those methods are perfectly valid ways of doing it. It's probably worth putting some defensive coding in there however.
eg.
$id = "";
if (ISSET($SESSION["settings"]) && ISSET($SESSION["settings"]["id"])
{
$id = $SESSION["settings"]["id"];
}
You can do both as $_SESSION['settings'] points to an array, the two expressions will be identical:
// The expression...
$val = $_SESSION['settings']['id'];
// ... is an internal shorthand for ...
$tmp = $_SESSION['settings']; // $tmp never exist - just to aid explanation.
$val = $tmp['id'];
Don't forget to use session_start(); before setting/using variables.
Then set the variables as you did. Not 100% sure, but both ways should work.
When you finish working with session, dont forget to destroy it session_destroy();.
Do whatever you need to solve your problem. In your case, both ways are acceptable of working with sessions. If I were you, I would choose the first example when only need to acces 1 or 2 elements from the session and the secon example to access more than 2 (in order to type less ).

Dynamically create variables in PHP

I want to create 1 variable name, but part of the name is the value stored in $i. Same for the GET result:
$Site.$i = $_GET['site'.$i]; // Should look something like $Site1 = $GET['site1'];
Please help me understand how to do this.
If you want a set of related variables, use an array:
$site[ $i ] = $_GET['site'.$i];
Even better, your GET parameters can also be an array
HTML
<input name="site[foo]" value="bar" />
PHP
$site = $_GET[ "site" ];
print_r( $site );
output
$site = array(
"foo" => "bar"
)
If you want the indexes for the array to decided automatically then you can do
<input name="site[]" value="foo" />
<input name="site[]" value="bar" />
<input name="site[]" value="baz" />
and get $_GET[ "site" ] out as
$site = array(
0 => "foo",
1 => "bar",
2 => "baz"
);
Direct Answer to Question
This is how you can do it. Not the best idea however.
$var = "$Site$i";
$$var = $_GET['site'.$i];
This makes use of variable variables.
Alternative Maintaining Current URL Structure
Alternatively perhaps something like this might work for you:
$vars = array();
foreach($_GET as $key => $value) {
if(0 === strpos($key, 'site')) { // Only grab value if the key is prefaced by the string 'site'
// You must sanitise the value some way here eg:
// $value = filter_var($value, FILTER_SANITIZE_STRING);
$vars[] = $value;
}
}
See filter_var() man page for more information on PHP filters and sanitisation/validation.
Revised URL Structure
I think this probably best solved however by making use of HTML arrays at the point your URL is generated. For more information on HTML arrays please see the PHP man page.
This allows you to access your information like the following:
$site1 = $_GET['site'][0];
$site2 = $_GET['site'][4];
This is the most logical method of dealing with this situation.
Update also see #Mat's answer for more information on this.
This is a bad idea for several reasons:
You have to loop through $_GET to find all variables (there's no language construct to pattern-match them)
Dynamic variables names are confusing, and may open security holes.
You will find that using an array will solve the second point, and also make it a lot easier to work with the code.
The first point can be solved by only using variable names you know. Send a variable containing a count how how many "sites" there are, for example:
site1=example&site2=example2&sitecount=2
This way you know that you only need to read site1 and site2, and you donät need to examine any other GET variables.
you van use $ as $_GLOBAL like this.
${'Site' . $i} = $_GET['site' . $i];
or you can use extract
please read the warnings about exract.
You can use variable variables like this:
$varname = $Site.$i;
$$varname = $_GET['site'.$i];
Doing this is discouraged however, because this is a huge security risk. You may write classes with fields representing your values from $_GET and validating them within the class.

Categories