Using extract - php

I'm new to OOP and want to revamp this function to get rid of using globals.
function CatchListing() {
$parseform = array('itemnum','msrp','edprice','itemtype','box','box2','box25','box3','box4','box5','box6','box7','itemcolor','link');
foreach ($parseform as $globalName) {
$GLOBALS[$globalName] = mysql_real_escape_string($_POST[$globalName]);
}
}
I was told to use array_map & then extact, but I am not sure of how to structure this.
function CatchListing() {
$_POST['listing'] = array_map('mysql_real_escape_string', $_POST);
$nst = extract($_POST['listing']);
}
(listing is the form name btw)
Thanks

Be VERY careful about using extract with externally inputted values as from $_GET and $_POST.
you're much better off extracting the values manually to known values.
It's far too easy for an extract from _GET or _POST to clobber existing variables.

There are so many things to say and Jonathan makes a very good start. Every time the user has the opportunity to play with your internal data and you don't check them, there is a huge "opportunity" (depends on the view..) that something goes wrong. Here is another approach on how to "maybe" get where you want to go:
<?php
function Sanitize($string){
return mysql_real_escape_string(trim($string));
}
function CatchListing(){
foreach($_POST as $key => $value) {
$key = Sanitize($key);
$value = Sanitize($value);
if($key && $value && !$GLOBALS[$key]){ /* prevent overwriting existing globals*/
$GLOBALS[$key] = $value;
}
}
}
global $nice;
$nice = "working";
CatchListing();
print_r($GLOBALS);
?>
To be honest, it still has not really anything to do with OOP and furthermore should be seen as a procedural approach. Personally I would use an additional and reusable function to "sanitize" the input, because you never know, if someday you want to change your database or the "escape" function and then you exactly know where to look for possible changes. Ah one more thing: Are you certain that you don't know all the possible names of all the variables you have to expect? Maybe you can predetermine them and put them in another array and check each user supplied argument with in_array.

To completely get rid of the usage of globals in your code, and also to make it much better overall, you can do something along these lines:
stop using $_POST, as it's a superglobal. When code needs values from superglobals, pass them as parameters
don't store values into $GLOBALS. If you need to return more than one value, consider returning an object or an array
Here's how I think I would modify your code to improve it:
function CatchListings($listings) {
$filteredListings = array_map('mysql_real_escape_string', $listings);
//I assume you only need the values in the array in the original snippet,
//so we need to grab them from the parameter array and return only that
$requiredListings = array();
$requiredKeys = array('itemnum','msrp','edprice','itemtype','box','box2','box25','box3','box4','box5','box6','box7','itemcolor','link');
foreach($requiredKeys as $key) {
$requiredListings[$key] = $filteredListings[$key];
}
return $requiredListings;
}
To use this function, you simply do $result = CatchListings($_POST);. Same result, no globals used.
There is one thing to consider, though. It may not be best possible form to just pass a randomly filled array (ie. $_POST) to the function, and expect it to contain specific keys (ie. $requiredKeys array). You might want to either add logic to check for missing keys, or process the post array before passing it.

Related

How to define while loop result in a global variable and use it in another function to process another task

I am trying to get first name and last name from a text file with while loop and store it in a global variable to which i want to access from any other function to echo all the first and last name in two different keys.
Here is my full code.
<?php
OutputNames();
function ReadNames()
{
$myFile = new SplFileObject("all/names.txt");
while (!$myFile->eof()) {
$row = str_getcsv($myFile->fgets());
$first = $row[0];
$last = $row[1];
}
}
function OutputNames()
{
echo $first." ".$last;
}
?>
Your code (or at least the part you've shown) really makes very little sense.
You're not actually using any global variables at all, so the $first and $last variables in each function are only in scope within those functions.
You never call ReadNames() anywhere, so it's not clear if it's ever being executed at all.
ReadNames() never returns any values, so the $first and $last variables simply cease to exist when the function ends.
The while loop in Readnames overwrites the $last variable every time it loops, instead of appending to it. But even then it wouldn't make sense because you'd end up with a list of first names and a list of last names, with no link between the first/last names which originally belonged together. A multidimensional associative array would make more sense to store the data (prior to displaying it).
Globals are generally a poor way to transfer information around your application - it's easy to get confused, have scoping issues, have things get overwritten, or cause conflicts between different parts of the code. Returning values from functions, and/or encapsulating functionality and data structures within objects are more reliable, testable and maintainable approaches.
It's not clear what actual flow you wanted / intended, but maybe something like this makes more sense?
OutputNames();
function ReadNames()
{
$myFile = new SplFileObject("all/names.txt");
$data = array();
while (!$myFile->eof()) {
$row = str_getcsv($myFile->fgets());
$data[] = array ("first" => $row[0], "last" => $row[1]);
}
return $data;
}
function OutputNames()
{
$results = ReadNames();
foreach ($results as $result) {
echo $result["first"]." ".$result["last"]."<br/>";
}
}
It depends at what point in the process you actually want to do the reading from the CSV file, and whether you want to do it once and then re-use the results repeatedly, or what. If the code above doesn't resolve the issue fully, you'll need to clarify the exact requirements.

What is the proper way to clear super-global variable in PHP? [duplicate]

I want clear $_POST array content fully, all examples what I see in internet, looks like this:
if (count($_POST) > 0) {
foreach ($_POST as $k=>$v) {
unset($_POST[$k]);
}
}
Tell please, this variant will be not more better? (Point of view as saving resources)
if (count($_POST) > 0) {
$_POST = array();
}
or not ?
Yes, that is fine. $_POST is just another variable, except it has (super)global scope.
$_POST = array();
...will be quite enough. The loop is useless. It's probably best to keep it as an array rather than unset it, in case other files are attempting to read it and assuming it is an array.
To unset the $_POST variable, redeclare it as an empty array:
$_POST = array();
The solutions so far don't work because the POST data is stored in the headers. A redirect solves this issue according this this post.
How to delete $_POST variable upon pressing 'Refresh' button on browser with PHP?
It may appear to be overly awkward, but you're probably better off unsetting one element at a time rather than the entire $_POST array. Here's why: If you're using object-oriented programming, you may have one class use $_POST['alpha'] and another class use $_POST['beta'], and if you unset the array after first use, it will void its use in other classes. To be safe and not shoot yourself in the foot, just drop in a little method that will unset the elements that you've just used: For example:
private function doUnset()
{
unset($_POST['alpha']);
unset($_POST['gamma']);
unset($_POST['delta']);
unset($_GET['eta']);
unset($_GET['zeta']);
}
Just call the method and unset just those superglobal elements that have been passed to a variable or argument. Then, the other classes that may need a superglobal element can still use them.
However, you are wise to unset the superglobals as soon as they have
been passed to an encapsulated object.
You can use a combination of both unset() and initialization:
unset($_POST);
$_POST = array();
Or in a single statement:
unset($_POST) ? $_POST = array() : $_POST = array();
But what is the reason you want to do this?
To answer "why" someone might use it, I was tempted to use it since I had the $_POST values stored after the page refresh or while going from one page to another. My sense tells me this is not a good practice, but it works nevertheless.

How get size_of $_GET

I want to get the number of values that were submitted via my $_GET. I'm going to be using a for loop and every 7 are going to be saved to a class. Does anyone know how to find the Size_of the $_GET array? I looked through this info $_GET Manual, but don't see what I'm looking for.
This is a code snippet that I started in the class that I go to after the submit.
for($i=0;$i<$_GET<size>;$i++) {
$ID = $_GET["ID"][$i];
$Desc = $_GET["Desc"][$i];
$Yevaluation = $_GET["Yevaluation"][$i];
$Mevaluation = $_GET["Mevaluation"][$i];
$Cevaluation = $_GET["Cevaluation"][$i];
$Kevaluation = $_GET["Kevaluation"][$i];
$comment = $_GET["comment"][$i];
//saving bunch to class next
}
$_GET is an array. Like any other array in PHP, to find the number of elements in an array you can use count() or its alias sizeof().
count($_GET["ID"])
could work. However, then you have to be sure that each index contains the same number of elements.
More secure would be
min(count($_GET["ID"]), count($_GET["Desc"]), ...)
With array_map this can probably be shortcut to something like:
min(array_map(count, $_GET))
Try thinking through the last one, if it seems difficult to you. It's called functional programming and it's an awesome way to shortcut some stuff. In fact array_map calls another function on each element of an array. It's actually the same as:
$filteredGet = array();
foreach ($element in $_GET) { // this is the array_map part
$filteredGet[] = count($element);
}
min($filteredGet);
Even better would be a structure where $i is the first level of the array, but I think this is not possible (built-in) with PHPs $_GET-parsing.

PHP Variables made with foreach

I have several variables coming from an array in $POST_['array'] i wish to make some kind of loop for example foreach that makes, for every value in the variable a variable name of it and assigns the value for it.
For example if i have
$POST_['name'];
$POST_['last'];
$POST_['age'];
$POST_['sex'];
I want the loop to create each variable from the array inside the $_POST with the name of the variable like the following:
$name = 'John';
$last = 'Doe';
$age = '32';
$sex = 'male';
NOTE - The array is coming from a serialized jquery string that puts together all the variables and values in a form into one big string.
Is this possible?
You don't need a loop, you want extract:
extract($_POST); // But use caution, see below
Cautions and best practices
As noted in the comments this forces all parameters in the $_POST array into the current symbol space.
In global space
<?php
extract($_GET);
var_dump($_SERVER); // Can be overwritten by the GET param
?>
The code above illustrates the problem as shown in this answer — some pretty dangerous things can be overwritten in the global space.
Inside a function
function myFunc() {
// (Mostly) empty symbol space! (excluding super globals)
extract($_POST);
}
Inside a function, as the first line, no harm done.
Important note: You might think since $_SERVER is a super global, that this exploit could happen inside a function as well. However, in my testing, on PHP Version 5.3.4, it is safe inside a function — neither $_SERVER, $_POST, $_GET, $_SESSION, or presumably other superglobals, could be overwritten.
With options
You can also use extract with extract_type options that do not overwrite.
The best option to use, in my opinion, is simply to prefix all variables from extract:
// $_GET = test=1&name=Joe
extract($_GET, EXTR_PREFIX_ALL, "request_get");
echo $request_get_test; // 1
echo $request_get_name; // Joe
That way you don't have the overwrite problem, but you also know you got everything from the array.
Alternate - looping w/ conditional
If you wanted to do this manually (but still dynamically), or wanted to conditionally extract only a few of the variables, you can use variable variables:
foreach ($_POST as $key => $value) {
if (isset($$key)) continue;
$$key = $value;
}
(The example condition I've used is an overwrite prevention.)
Try not to use extract() when using $_POST. You may overwrite variables you want which will result in unpredictable behaviour. It is a bad habit to get into and while is dynamic may not be the best solution.
You can do something like this:
foreach($_POST as $key => $value)
{
switch($key)
{
case "name":
$name = $value;
break;
case "last":
$last = $value;
break;
}
}
You can actually use the built-in function called extract
Why not use a foreach?
foreach($_POST as $key=>$val){
${$key} = $val;
}
I just want to mention that you can improve foreach technique because we have in HTML the ability to name one of our form fields using square bracket notation, and if we do that, what HTML will do is it will submit a series of values as an array.
<input name="user[name]">
<input name="user[last]">
<input name="user[age]">
<input name="user[sex]">
Than use just one line of code to assign all values from input fields into local array $args.
$args = $_POST['user'];
So what that means is when we go to process the form, we're looking at an array of values instead of a bunch of single values that we have to go retrieve.
So we can just simply go to the post super global and ask for one item: that is user. And what we get back is an associative array. So instead of having to build up that array by going and retrieving all those values one at a time, we're instantly given an array, just because we named our form fields differently.

convert string into variable name

I am working on a function that takes a string as an argument, which I need to use to get the value of a variable of the same name.
For example
If the string $foo = "$_POST['email']"; is passed I need to retrieve the value of $_POST['email'] and store it as $example, so that $_POST['email'] == $example would return true. There is no feasable way of passing the value directly to function (the variable has to be dynamic to make the function worthwhile).
I did think of using variable variables but they don't work with super globals which will be the primary source of the values I need.
Basically is there a way to get the value of a variable (usually in a superglobal array) with the needed variable as a string?
Let me know if more detail is needed.
Thanks
Variable variables would be the answer, but if you're after fetching values from $_POST array, why not pass just a key to a function?
Note: ths function is provided just for example, my actual recommendation is below.
function fetchFromPost($key) {
if(isset($_POST[$key]) {
return $_POST[$key];
} else {
return null; //or do whatever you want to do in case key is not found
}
}
In fact filter_input(), which allows you to chose an input array, a key and a sanitaion filter to be used, is already there for you
It is possible, although I seriously doubt you should use this. It allows for PHP injection and makes your source code very vulnerable if you don't know where the string came from:
<?
function eval_expression($expression)
{
eval("\$temp = $expression;");
return $temp;
}
// Usage:
echo eval_expression("\$_GET['plop']");

Categories