Perform operations after extract() - php

I have been looking for an answer, but maybe because I am searching the wrong terms or concepts - I did not yet find any lead on how to perform operations on extracted arguments .
I have an array, which is dynamic ( I can not predict how many $vars or of what name or type )
global $o99_option;
extract( $o99_option );
so now, theoretically, I can have any number of $vars with any possible name..
example :
$first_var = 'first-var';
$my_second_var = 'another';
$enigma = NULL;
$answer = '42';
my question is - how can I perform operations on the result of extract ( after extraction ) in a manner that will effect all the created $vars ?
for example, let´s say I want to trim all of those variables - How do I achieve that ?
( that , In my twisted mind, should have the same effect as
foreach (extract( $o99_option ) as $single_var ){
do_something($single_var);
}
)
Edit I : So, is there a way to perform operations on all extracted elements ? ( assuming I DO need to extract them ..) Or should I always do that BEFORE the extraction ( for example with the help of array_map() ) - or, should I , like people here suggested just forget that extract ever existed never ever use it..
Edit II :
Sure, like many here said , I can also do
$first_var = $o99_option['first-var'];
$my_second_var = $o99_option['my_second_var'];
$enigma = $o99_option[enigma];
$answer = $o99_option['answer'];
but
1) it seems a little absurd doing that for 100+ variables, and
2 ) what to do with the ones that I need to use their value as name ?
right now, for example, I use
${$title_field} = $formdata[$post_title_field];
where I know that $title_field exists as $o99_option['title_field'], and therefore exists as a variable after extract ..
Again, I might be approaching that all wrong, but up until now the script works great , and actually , the first comment by #Mark Baker ( using array_map() ) might be the best option when doing so BEFORE the extract ...

You must not extract the variables, you need to keep them in the $o99_option array otherwise it's impossible to determine the number of elements.
foreach ($o99_option as $variable) {
// Do something with the variable
}

Imagine you're sitting in one of those kids ball pits. This is your variable scope. You have all sorts of variables floating around in this scope. Now you get handed a box full of even more colourful balls. Those balls are important balls, they're more interesting to you than all the other balls around you.
What you're doing with extract is you're turning the box upside down and empty all those balls into the ball pit and mix them with all the other balls. And you didn't even really know what balls were in that box exactly, but you emptied the box anyway. Well, good luck finding those balls again now and doing anything with them.
Keep the balls in the box! While they're in the box, you can inspect them one by one. You can look at each one in turn and do something with it. You can carry them all around inside that box together. Don't extract!
If you know what you're looking for in that box:
echo $o99_option['first-var'];
Simple. Just take that ball directly and do whatever you want with it.
If you want to check whether a specific ball is in the box:
if (isset($o99_option['first-var']))
If you want to look through all balls and do something with each of them:
foreach ($o99_option as $name => $ball) {
echo "$name: $ball";
}

If you want to do something to all the variables:
foreach ($o99_option as &$variable) {
$variable = strtoupper($variable); //for example
}
Then you should work with each element individually. Don't extract.

Related

php get array elememnt using $$

i know this
$var1 = "10";
$var2 = "var1";
then
echo $$var2 gives us 10
i want to this with array
i have array
$intake_arr = array(5=>10,7=>20,8=>30,9=>40,10=>50,11=>60,12=>70);
i have some logic that will pick one array from set of array , all array will look like $intake_arr
if i do this $target_arr = "intake_arr";
then can $$target_arr[5] will yield 10? i tried but i didnt that 10 value, how can i achieve this with array
Your statement ($$target_arr[5]) is ambiguous. PHP doesn't know what you actually want to say: Do you mean: use $target_arr[5]'s value and prepend the $, to use that as a variable, or do you want to use the value of $target_arr, and get the fifth element of that array?
Obviously it's the latter, but PHP doesn't know that. In order to disambiguate your statement, you have to use curly braces:
${$target_arr}[5];
That'll yield 10. See the manual on variable variables for details
Note:
As people said in comments, and deleted answers: variable variables, like the one you're using is risky business. 9/10 it can, and indeed should be avoided. It makes your code harder to read, more error prone and, in combination with the those two major disadvantages, this is the killer: it makes your code incredibly hard to debug.
If this is just a technical exercise, consider this note a piece of friendly advice. If you've gotten this from some sort of tutorial/blog or other type of online resource: never visit that site again.
If you're actually working on a piece of code, and you've decided to tackle a specific problem using variable vars, then perhaps post your code on code-review, and let me know, I'll have a look and try to offer some constructive criticism to help you on your way, towards a better solution.
Since what you're actually trying to do is copying an array into another variable, then that's quite easy. PHP offers a variety of ways to do that:
Copy by assignment:
PHP copies arrays on assignment, by default, so that means that:
$someArray = range(1,10);//[1,2,3,4,5,6,7,8,9,10]
$foo = $someArray;
Assigns a copy of $someArray to the variable $foo:
echo $foo[0], ' === ', $someArray[0];//echoes 1 === 1
$foo[0] += 123;
echo $foo[0], ' != ', $someArray[0];//echoes 123 != 1
I can change the value of one of the array's elements without that affecting the original array, because it was copied.
There is a risk to this, as you start working with JSON encoded data, chances are that you'll end up with something like:
$obj = json_decode($string);
echo get_class($obj));//echoes stdClass, you have an object
Objects are, by default, passed and assigned by reference, which means that:
$obj = new stdClass;
$obj->some_property = 'foobar';
$foo = $obj;
$foo->some_property .= '2';
echo $obj->some_property;//echoes foobar2!
Change a property through $foo, and the $obj object will change, too. Simply because they both reference exactly the same object.
Slice the array:
A more common way for front-end developers (mainly, I think, stemming from a JS habbit) is to use array_slice, which guarantees to return a copy of the array. with the added perk that you can specify how many of the elements you'll be needing in your copy:
$someArray = range(1,100);//"large" array
$foo = array_slice($someArray, 0);//copy from index 0 to the end
$bar = array_slice($someArray, -10);//copy last 10 elements
$chunk = array_slice($someArray, 20, 4);//start at index 20, copy 4 elements
If you don't want to copy the array, but rather extract a section out of the original you can splice the array (as in split + slice):
$extract = array_splice($someArray, 0, 10);
echo count($someArray);//echoes 90
This removes the first 10 elements from the original array, and assigns them to $extract
Spend some time browsing the countless (well, about a hundred) array functions PHP offers.
${$target_arr}[5]
PHP: Variable variables
Try this one:
$intake_arr = array(5=>10,7=>20,8=>30,9=>40,10=>50,11=>60,12=>70);
$target_arr = 'intake_arr';
print ${$target_arr}[5]; //it gives 10
For a simple variable, braces are optional.But when you will use a array element, you must use braces; e.g.: ${$target_arr}[5];.As a standard, braces are used if variable interpolation is used, instead of concatenation.Generally variable interpolation is slow, but concatenation may also be slower if you have too many variables to concatenate.Take a look here for php variable variables http://php.net/manual/en/language.variables.variable.php

Php regexp get the strings from array print_r like string

Im trying to list out here how to match strings that looks like array printr.
variable_data[0][var_name]
I would like to get from above example 3 strings, variable_data, 0 and var_name.
That above example is saved in DB so i same structure of array could be recreated but im stuck. Also a if case should look up IF the string (as above) is in that structure, otherwise no preg_match is needed.
Note: i dont want to serialize that array since the array 'may' contain some characters that might break it when unserializing and i also need that value in the array to be fully visible.
Any one with regexp skills who might know the approach ?
Solution:
(\b([\w]*[\w]).\b([\w]*[\w]).+(\b[\w]*[\w]))
Thos 2 first indexes should be skipped... but i still get what i want :)
Not for nothing but couldn't you just do..
$result = explode('[', someString);
foreach ($result as $i => $v) {
$temp = str_replace(']'. ''. $result[$i]);
//Do something with temp
}
Obviously you need to edit the above a little bit depending on what you are doing but it is very simple and even gives you the same flexibility and you don't need to invoke the matching engine...
I don't think we build regex's here for people... instead please see http://regexpal.com/ for a Regex tester / builder with visual aid.
Furthermore people usually don't know how to use them properly which is then fostered by others creating the expressions for them.
Please remember complex expressions can have terrible performance overheads although there is nothing seemingly complex about your request...
Then after it is compelte post your completed RegEx and answer your own question for maximum 1337ne$$ :)
But since I am nice here is your reward:
\[.+\]\[\d+\]
or
[a-z]+_[a-z]+\[.+\]\[\d+\]
Depending on what you want to match out of the string (which you didn't specify) so I assumed all
Both perform as follows:
arr_var[name][0]; //Matched
arr_var[name]; //Not matched
arr_var[name][0][1];//Matched
arr_var[name][2220][11];//Matched
Again, test them and understand with visual aid at the above link.
Solution:
(\b([\w]*[\w]).\b([\w]*[\w]).+(\b[\w]*[\w]))
Those 2 first indexes should be skipped... but i still get what i want :)
Edit
Here is improved one:
$str = "variable[group1][parent][child][grandchild]";
preg_match_all('/(\b([\w]*[\w]))/', $str,$matches);
echo '<pre>';
print_r($matches);
echo '</pre>';
// Output
Array
(
[0] => variable
[1] => group1
[2] => parent
[3] => child
[4] => grandchild
)

PHP Change Array Over and Over

I have any array
$num_list = array(42=>'0',44=>'0',46=>'0',48=>'0',50=>'0',52=>'0',54=>'0',56=>'0',58=>'0',60=>'0');
and I want to change specific values as I go through a loop
while(list($pq, $oin) = mysql_fetch_row($result2)) {
$num_list[$oin] = $pq;
}
So I want to change like 58 to 403 rather then 0.
However I always end up getting just the last change and non of the earlier ones. So it always ends up being something like
0,0,0,0,0,0,0,0,0,403
rather then
14,19,0,24,603,249,0,0,0,403
How can I do this so it doesn't overwrite it?
Thanks
Well, you explicititly coded that each entry should be replaced with the values from the database (even with "0").
You could replace the values on non-zero-values only:
while(list($pq, $oin) = mysql_fetch_row($result2)) {
if ($pq !== "0") $num_list[$oin] = $pq;
}
I don't get you more clear, i thought your asking this only. Check this
while(list($pq, $oin) = mysql_fetch_row($result2)) {
if($oin==58) {
$num_list[$oin] = $pq;
}
}
In my simulated tests (although You are very scarce with information), Your code works well and produces the result that You want. Check the second query parameter, that You put into array - namely $pg, thats what You should get there 0,0,0,0,0...403 OR Other thing might be that Your $oin numbers are not present in $num_list keys.
I tested Your code with mysqli driver though, but resource extraction fetch_row is the same.
Bear in mind one more thing - if Your query record number is bigger than $numlist array, and $oin numbers are not unique, Your $numlist may be easily overwritten by the folowing data, also $numlist may get a lot more additional unwanted elements.
Always try to provide the wider context of Your problem, there could be many ways to solve that and help would arrive sooner.

PHP Compare Two Arrays?

I'm trying to compare two entries in a database, so when a user makes a change, I can fetch both database entries and compare them to see what the user changed, so I would have an output similar to:
User changed $fieldName from $originalValue to $newValue
I've looked into this and came across array_diff but it doesn't give me the output format I need.
Before I go ahead and write a function that does this, and returns it as a nice $mtextFormatDifferenceString, can anyone point me in the direction of a solution that already does this?
I don't want to re-invent the wheel..
Since you require "from $originalValue to $newValue", I would go ahead and select the two rows, put them in assoc arrays, then foreach through the keys, saving the ones that aren't equal. Kind of like:
$fields = array_keys($row1);
$changedFields = array();
foreach ($fields as $field) {
if ($row1[$field] != $row2[$field]) {
$changedFields[] = $field;
}
}
I realize you were asking about the existence of pre-built wheels but I felt the solution was pretty simple.
?>
Although you didn't define what format you needed, but well-known diff algorithm is probably for you. Google for PHP diff algorithm and you'll find some suggestions I am sure.
You could get the changed values ($newValue) with array_diff_assoc and then just use the keys ($fieldName) to find the original value $originalValue and output it in anyformat you want

Populating a PHP array: check for index first?

If I'm deep in a nest of loops I'm wondering which of these is more efficient:
if (!isset($array[$key])) $array[$key] = $val;
or
$array[$key] = $val;
The second form is much more desirable as far as readable code goes. In reality the names are longer and the array is multidimensional. So the first form ends up looking pretty gnarly in my program.
But I'm wondering if the second form might be slower. Since the code is in one of the most frequently-executed functions in the program, I'd like to use the faster form.
Generally speaking this code will execute many times with the same value of "$key". So in most cases $array[$key] will already be set, and the isset() will return FALSE.
To clarify for those who fear that I'm treating non-identical code as if it were identical: as far as this part of the program is concerned, $val is a constant. It isn't known until run-time, but it's set earlier in the program and doesn't change here. So both forms produce the same result. And this is the most convenient place to get at $val.
For an array you actually want: array_key_exists($key, $array) instead of isset($array[$key]).
isset() is very fast with ordinary variables, but you have an array here. The hash-map algorithm for arrays is quick, but it's still takes more time than doing nothing.
Now, first form can be faster if you have more values that are set, than those that are not, simply because it just looks up for hash without fetching or setting the value. So, that could be a point of difference: pick the first form if you have more 'hits' at keys that are set, and pick the second one if you have more 'misses'.
Please note that those two pieces of code are not identical. The first form will not set the value for some key when it's already set - it prevents 'overwriting'.
Have you measured how often you run into the situation that $array[$key] is set before you try to set it? I think one cannot give a general advice on this, because if there are actually a lot of those cases, the isset check could possibly save some time by avoiding unnessecary sets on the array. However, if this is just rarely the case, the overhead could slow you down …. The best thing would be to do a benchmark on your actual code.
However, be aware that both codes can lead to different results! If $val is not always the same for a $array[$key] combination, the former code would always set the value to the first $val for that $array[$key] where the latter code would always set it to the last value of that combination.
(I guess you are aware of that and $val is always the same for $array[$key], but some reader stopping by might not.)
The overhead of a comparison which may or may not be true seems like it should take longer.
What does running the script in both configurations show for performance time?
You should check the array upto but not including the level you are going to set.
If you're going to set
$anArray[ 'level1' ][ 'level2' ][ 'level3' ] = ...
You should make sure that the path upto level2 actually exists prior to setting level3.
$anArray[ 'level1' ][ 'level2' ]
No puppies will actually be killed if you don't, but they might be annoyed depending on your particular environment.
You don't have to check the index you are actually setting, because setting it automatically means it is declared, but in the interest of good practice you should make sure nothing is magically created.
There is an easy way to do this:
<?php
function create_array_path( $path, & $inArray )
{
if ( ! is_array( $inArray ) )
{
throw new Exception( 'The second argument is not an array!' );
}
$traversed = array();
$current = &$inArray;
foreach( $path as $subpath )
{
$traversed[] = $subpath;
if ( ! is_array( $current ) )
{
$current = array();
}
if ( ! array_key_exists( $subpath, $current ) )
{
$current[ $subpath ] = '';
}
$current = &$current[ $subpath ];
}
}
$myArray = array();
create_array_path( array( 'level1', 'level2', 'level3' ), $myArray );
print_r( $myArray );
?>
This will output:
Array
(
[level1] => Array
(
[level2] => Array
(
[level3] =>
)
)
)
The extra function call to isset() is almost guaranteed to have more overhead than any assignment. I would be extremely surprised if the second form is not faster.
Do you need an actual check to see if the key is there? With an assignment to a blank array the isset() will just slow the loop down. And unless you do a second pass with data manipulation I strongly advise against the isset check. This is population, not manipulation.
You can take a look at the PHP source code to see the difference. Didn't check whether this would be different in later versions of PHP, but it would seem in PHP3 the associative array functionality is in php3/php3_hash.c.
In the function _php3_hash_exists, the following things are done:
key is hashed
correct bucket found
bucket walked, until correct item found or not
Function _php3_hash_add_or_update:
hashed
bucket found
walked, existing overridden if existed
if didn't exist, new one added
Therefore it would seem just setting it is faster, because there is just one function call and this hashing and bucket finding business will only get done once.
i am a newbie to PHP but a combination of both could be with the ternary operator
$array[$key] = !isset($array[$key]) ? $val : $array[$key];
that's one way to go with it.

Categories