Extracting array with a suffix - php

Generally, we can extract an array, and also add an prefix to it, like this
extract($array, EXTR_PREFIX_ALL, "myprefix");
// which will give me output like $myprefix_myarrayvar
But, instead, is there a way to set a suffix instead of prefix? Something like,
$myarrayvar_mypostfix;

First of all, you should never use extract because it can make it very hard to tell where some variables are coming from, never mind possible collisions. You don't save much with extract .. it's really just a tool of laziness.
Anyway, since you asked, no there does not seem to be a way to add a suffix with extract natively, so you would have to do it on your own:
foreach ($array as $key => $val) {
${"{$key}_suffix"} = $val;
}

There is no extract option for that. So you need a workaround. You could either write a boring foreach or prepare the keys prior extraction:
extract( array_combine(preg_replace('/$/', "_suffix", array_keys($array)), $array) );

Related

How to use foreach while only defining the key

So I have this slightly annoying issue: say I have a foreach loop like this:
foreach ($arr as $key=>$value) {
do_something($key);
}
In my eclipse environment, I have turned on the feature that displays warnings for unused variables, which is really helpful. However, it complains for all such occurences, where the $value is not used in the loop.
I was wondering if there is some syntax where I don't use this, like is available for list() :
list(,,$my_var) = some_func();
//these returns an array with 3 elements, but I only need the last one
Note: The obvious would be to use array_keys(), but I don't want a function call; I'm merely asking if there's a shorthand I don't know of, or something like it. This is why the question PHP foreach that returns keys only does not cover what I'm asking.
TBH, I couldn't find any resource to back this answer, it works fine as far as my tests went, BUT I CAN'T SAY FOR SURE WHETHER THIS IS OR ISN'T RECOMMENDED TO USE. (Probably not)
Here is what I came up with:
$arr = array('kN1' => '50', 'kN2' => 400);
//$arr = array('50', 400);
foreach ($arr as $var => $var) { // use same variable for both key and value
print_r($var);
echo '<br>';
}
// kN1
// kN2
Run Viper
To get rid of the warning without introducing too much overhead just unset the unused variable once the loop is done.
foreach ($arr as $key => &$val) {
print_r($key);
}
unset($val);
BTW: I believe one should use a reference to the unused variable (&$val instead of $val). Otherwise you might end up producing a full copy of the variable with each iteration and that might be a costly operation.

is there a compelling reason to use php's list() function?

Can anybody provide an example of when php's list() function is actually useful or preferable over some other method? I honestly can't think of a single reason I'd ever actually want/need to use it..
Got a simple sql result row (numeric), containing, say, an ID and a name?
A simple solution to deal with it, can be:
list($id,$name)=$resultRow;
Edit;
or here's another: you want to know the current key/value pair of an array
list($key,$val)=each($arr);
this can even be put into a loop
while (list($key,$val)=each($arr))
altho you could say a foreach is exactly this; but if the
$arr changes in the meantime, well then it's not. It has its uses. :)
It's a handy function when you know the right hand side is returning an indexed array of a certain size.
list($basename, $ext) = explode('.', 'filename.png');
Note that it can be used in PHP 5.5 with foreach:
$data = [
['a1', 'b1'],
['a2', 'b2'],
];
foreach ($data as list($a, $b))
{
echo "$a $b\n";
}
But if you prefer more verbose code, then I doubt you'll think the above is "better" than the alternatives.

How do I clear the values in a PHP array while maintaining its keys?

I would like to take an array and clear all of its values while maintaining its keys. By "clear" I mean replace with an empty type value, such as '' or null. PHP obviously has quite a few array functions, but I didn't find anything there that does exactly this. I am currently doing it this way:
foreach ($array as &$value) $value = ''
My question is, is there some built-in php function I overlooked, or any other way I can accomplish this without iterating over the array at this level?
Without knowing exactly what your memory/performance/object-management needs are, it's hard to say what's best. Here are some "I just want something short" alternatives:
$array = array_fill_keys(array_keys($a),""); // Simple, right?
$array = array_map(function(){return "";},$a); // More flexible but easier to typo
If you have an array that's being passed around by reference and really want to wipe it, direct iteration is probably your best bet.
foreach($a as $k => $v){
$a[$k] = "";
}
Iteration with references:
/* This variation is a little more dangerous, because $v will linger around
* and can cause bizarre bugs if you reuse the same variable name later on,
* so make sure you unset() it when you're done.
*/
foreach($a as $k => &$v){
$v = "";
}
unset($v);
If you have a performance need, I suggest you benchmark these yourself with appropriately-sized arrays and PHP versions.
Easiest way is array_map
$array = array_map(function($x) { return '';}, $array);
You can use array_keys to get the keys. You can then use array_flip if you like, although this will assign the values 0 through length-1 to the keys.
There is no single built-in function for this. You might try:
array_combine(array_keys($array),array_fill(0,count($array)-1,""));
But really the code you have right now does the job just fine.

PHP array in a query

Is there any way, to make something like:
$elements_string = array()
foreach ($something as $element => $value ) {
$elements_string[$element] = $value;
...
}
And save $elements_string into a db row?
Maybe you guys prefer some other way?
I wan't to read it from the database so I can easly parse the string.
Earlier I was using something similar to:
$elements_string = $element . ":" . $value;
And I was trying to use explode on that, but that makes no sense because I need to have $element and $value in one loop for one element.
Normally you would store each element and value in a different row.
If you must store them in one row (and be sure you really have to do that), then use serialize() http://www.php.net/serialize to turn an array into a string you can store.
You can do other things to like: value:element;value:element - then you first split by semicolon, then by colon.
You could use implode(glue,pieces) to turn an array into a string with a given separator, supposing you have a character you never use. (and explode(delimiter,string) to get it back)
Serializing may be a better option in most cases, though. Use serialize(value) to store it and unserialize(value) to get it back.

Using extract

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.

Categories