PHP Variable Variables within setter function - php

I am trying to achieve a way to define an indefinite, but not infinite number of variables, to be used to create objects. I have tried a couple of ways to try this but i cant seem to wrap my head around this.
Here is what i came up with:
$aCount= 0;
$Foo = "Bar".$aCount;
$$Foo = array("Data1"=>NULL, "Data2"=>NULL);
function getBarData1() {
return ${$Foo}['Data1'];
}
function getBarData2() {
return ${$Foo}['Data2'];
}
function setBarData($newBarData1, $newBarData2) {
${$Foo}['Data1'] = $newBarData1;
${$Foo}['CONTENT'] = $newBarData2;
$aCount++;
}
setBarData('First', 'Line');
setBarData('Second', 'Dot');
setBarData('Third', 'Dash');
for($aCount == $aCount; $aCount > -1; $aCount--) {
echo getBarData1() ."\n";
echo getBarData2() ."\n";
}
Any help would be greatly appreciated.

You are heading two problems:
variable scope
value of variable $Foo is static and never change - value is always: Bar0 even when you change $aCount because the value is just a string
working example:
<?php
$aCount= 0;
$Foo = function(){ global $aCount; return "Bar".$aCount; };
${$Foo()} = array("Data1"=>NULL, "Data2"=>NULL);
function getBarData1() {
global $Foo, ${$Foo()};
return ${$Foo()}['Data1'];
}
function getBarData2() {
global $Foo, ${$Foo()};
return ${$Foo()}['Data2'];
}
function setBarData($newBarData1, $newBarData2) {
global $aCount, $Foo, ${$Foo()};
${$Foo()}['Data1'] = $newBarData1;
${$Foo()}['Data2'] = $newBarData2;
$aCount++;
}
setBarData('First', 'Line');
setBarData('Second', 'Dot');
setBarData('Third', 'Dash');
$aCountTotal = $aCount;
for($i = 0; $i < $aCountTotal; $i++) {
$aCount = $i;
echo getBarData1() ."\n";
echo getBarData2() ."\n";
}
in this case you should use array instead, variable-variable is really usefull in rare cases
array example:
<?php
$arr = array();
function getBarData1($index) {
global $arr;
return $arr[$index]['Data1'];
}
function getBarData2($index) {
global $arr;
return $arr[$index]['Data2'];
}
function setBarData($newBarData1, $newBarData2) {
global $arr;
$arr[] = ['Data1' => $newBarData1, 'Data2' => $newBarData2];
}
setBarData('First', 'Line');
setBarData('Second', 'Dot');
setBarData('Third', 'Dash');
for($i = 0; $i < count($arr); $i++) {
echo getBarData1($i) ."\n";
echo getBarData2($i) ."\n";
}
better than using global variable in functions is passing data through parameters like:
<?php
$arr = array();
function getData1($array, $index) {
return $array[$index]['Data1'];
}
function getData2($array, $index) {
return $array[$index]['Data2'];
}
// reference to $array because we want to change the value
function setData(&$array, $newBarData1, $newBarData2) {
$array[] = ['Data1' => $newBarData1, 'Data2' => $newBarData2];
}
setData($arr, 'First', 'Line');
setData($arr, 'Second', 'Dot');
setData($arr, 'Third', 'Dash');
for($i = 0; $i < count($arr); $i++) {
echo getData1($arr, $i) ."\n";
echo getData2($arr, $i) ."\n";
}

Related

changing variable value outside a function inside a class

how can i make it change the count value. the RollingCurlX thing is a multithreading class for php which only let you process response through a function and i dont know how you should handle it. please help me
class MyClass extends RollingCurlX {
public function someFunc() {
$url = 'https://example.com/';
$count = 0;
function callback_functn($response, $url, $request_info, $user_data, $time) {
if ($response['c'] == 'd') {
$count++;
}
}
$RCX = new RollingCurlX(10);
for ($i=0; $i < 100; $i++) {
$post_data = ['a' => 'b'];
$RCX->addRequest($url, $post_data, 'callback_functn');
}
$RCX->execute();
echo $count;
}
}
$c = new MyClass();
$c->someFunc();
Use the use() declaration to give the function access to an external variable. Make it a reference with & so assignments to the variable inside the function will affect the outer variable.
function callback_functn($response, $url, $request_info, $user_data, $time) use (&$count) {
if ($response['c'] == 'd') {
$count++;
}
}
Try it
public function someFunc() {
$url = 'https://example.com/';
$count = 0;
$callbackFunction = static function ($response, $url, $request_info, $user_data, $time) use (&$count) {
if ($response['c'] == 'd') {
$count++;
}
};
$RCX = new RollingCurlX(10);
for ($i = 0; $i < 100; $i++) {
$post_data = ['a' => 'b'];
$RCX->addRequest($url, $post_data, $callbackFunction);
}
$RCX->execute();
echo $count;
}

PHP - Modify array value by reference inside object

How can I pass a value of an array by reference to modify its value inside an object? I've tried it with the & operator at public function f(&$z) {.
<?php
class C {
private $a;
public function f($z) {
foreach ($z as $i => $v) {
$v = 8888;
}
}
}
$p = 4;
$obj = new C();
$obj->f(array('key'=>$p));
echo $p;
?>
I would like to set the 8888 value to the $p variable.
The fiddle: http://codepad.org/RvKU4hY1
You have to use references when you 1) create the array, 2) iterate over it:
<?php
class C {
private $a;
public function f($z) {
foreach ($z as $i => &$v) {
$v = 8888;
}
}
}
$p = 4;
$obj = new C();
$obj->f(array('key'=>&$p));
echo $p;
?>
Only slightly different to georg, you can do it this way;
<?php
class C {
private $a;
public function f($z) {
foreach ($z as $i => $v) {
$z[$i] = 8888;
}
}
}
$p = 4;
$obj = new C();
$result = array('key'=> &$p);
$obj->f($result);
echo $p;
?>
Here the code with explanation:
<?php
class C {
private $a;
public function f(&$z) { // we receive a pointer
foreach ($z as $i => $v) {
// here you overwrite $v, even if it a pointer in foreach
// It has mean when you want to do unset($v); here
// $v = 8888;
$z[$i] = 8888;
}
}
}
$p = 4;
$obj = new C();
$param = array('key'=>$p);
$obj->f($param);
echo $p;

array_push inside function produces error "expects parameter 1 to be array, null given.."

Why am I getting this error message "Warning: array_push() expects parameter 1 to be array, null given ..." When I removed the function and just run the for loop, it works, but not inside function. why?
<?php
$arr = array();
function callme() {
for ($x = 1; $x <= 10; $x++) {
array_push($arr, $x);
}
return $arr;
}
callme();
print_r($arr);
?>
Declare array $arr as global
$arr = array();
function callme() {
global $arr;
for ($x = 1; $x <= 10; $x++) {
array_push($arr, $x);
}
return $arr;
}
Or pass $arr as a parameter.
You need to do either of two things:
Add $array as function parameter and return that.
<?php
$arr = array();
function callme($array) {
for ($x = 1; $x <= 10; $x++) {
array_push($array, $x);
}
return $array;
}
$arr = callme($arr);
print_r($arr);
?>
If you don't like returns you can have the array as reference...
<?php
$arr = array();
function callme(&$array) {
for ($x = 1; $x <= 10; $x++) {
array_push($array, $x);
};
}
callme($arr);
print_r($arr);
?>
or define $arr als global in the function(least desired, you're stuck with only one array)
<?php
$arr = array();
function callme() {
global $arr;
for ($x = 1; $x <= 10; $x++) {
array_push($arr, $x);
}
return $arr;
}
callme();
print_r($arr);
?>
Someone needs to learn some basics about variable scopes.
http://php.net/manual/language.variables.scope.php

Checking a for progression in a list of variables

Let's say I want to check for simple mathematical progression. I understand I can do it like this:
if ($a<$b and $b<$c and $c<$d and $d<$e and $e<$f) { echo OK; }
Is there a way to do it in a more convenient way? Like so
if ($a..$f isprog(<)) { echo OK; }
I don 't know if I get your problem right. But propably the solution for your progression could be the SplHeap object of the SPL delivered with php.
$stack = new SplMaxHeap();
$stack->insert(1);
$stack->insert(3);
$stack->insert(2);
$stack->insert(4);
$stack->insert(5);
foreach ($stack as $value) {
echo $value . "\n";
}
// output will be: 5, 4, 3, 2, 1
I havent heard of something like this, but how about using simple function:
function checkProgress($vars){ //to make it easie i assume that vars can be given in an array
$result = true;
for ($i=0; $i<= count($vars); $i++){
if ($i>0 && $vars[$i] > $vars[$i-1]) continue;
$result = false;
}
return $result;
}
Solved it quick and dirty:
function ispositiveprogression($vars) {
$num=count($vars)-1;
while ($num) {
$result = true;
if ($vars[$num] > $vars[$num-1]) {
$num--;
}
else { $result = false; break; }
}
return $result;
}
Create an array of values, iterate over them and maintaining a flag that checks if the current element value is greater than / less than that of the next value. Unlike some of the solutions in this thread, this doesn't loop through the whole array. It stops looping when it discovers the first value that's not a progression. This will be a lot more faster if the operation involves a lot of numbers.
function checkIfProg($arr, $compare) {
$flag = true;
for ($i = 0, $c = count($arr); $i < $c; $i++) {
if ($compare == '<') {
if (isset($arr[$i + 1]) && $arr[$i] > $arr[$i + 1]) {
$flag = false;
break;
}
} elseif ($compare == '>') {
if (isset($arr[$i + 1]) && $arr[$i] < $arr[$i + 1]) {
$flag = false;
break;
}
}
}
return $flag;
}
Usage:
$a = 2;
$b = 3;
$c = 4;
$d = 5;
$e = 9;
$f = 22;
$arr = array($a, $b, $c, $d, $e, $f);
var_dump(checkIfProg($arr, '<')); // => bool(true)
If you want the array to be created dynamically, you could use some variable variable magic to achieve this:
$arr = array();
foreach (range('a','f') as $v) {
$arr[] = $$v;
}
This will create an array containing all the values of variables from $a ... $f.

Combining of array items

I have a problem with an advanced loop, this are my arrays
$array1 = array(1,2,3);
$array2 = array(4,5);
$array3 = array(6,7,8,9);
$array4 = array(10,11);
I want to loop with the following result:
1,4,6,10
1,4,6,11
1,4,7,10
1,5,7,11
With the last: 3,5,8,11
How can I do that?
Solution for a variable number of arrays. Can probably be written a bit shorter, but I leave that to you. ;)
<?php
$array1 = array(1,2,3);
$array2 = array(4,5);
$array3 = array(6,7,8,9);
$array4 = array(10,11);
function turboArray()
{
$arrays = func_get_args();
$indexes = array_fill(0, count($arrays), 0);
function turboSubArray(&$arrays, &$indexes, $l){
for ($a = 0; $a < count($arrays[$l]); $a++){
$indexes[$l] = $a;
if ($l == count($arrays) - 1) {
for ($i = 0; $i < count($indexes); $i++)
{
echo $arrays[$i][$indexes[$i]];
if ($i == count($indexes) - 1){
echo "\n<br/>";
$indexes[$i] = 0;
if ($i == 0) return;
}
else {
echo ', ';
}
}
} else if ($l < count($indexes)) {
turboSubArray($arrays, $indexes, $l + 1);
}
}
}
$l = 0;
turboSubArray($arrays, $indexes, $l);
}
turboArray($array1, $array2, $array3, $array4);
This should do it... ?
foreach ($array1 as $first) {
foreach ($array2 as $second) {
foreach ($array3 as $third) {
foreach ($array4 as $fourth) {
echo "$first $second $third $fourth";
}
}
}
}
I got bored and decided to overengineer a bit. Enjoy.
class CrossJoin implements Iterator {
private $arrays = array();
private $index = 0;
public function __construct(/* $array1, ... */) {
foreach (func_get_args() as $arr) {
// ArrayIterator's iteration stuff is cleaner than arrays',
// and less prone to breakage when objects are passed around
if (count($arr)) $this->arrays[] = new ArrayIterator($arr);
}
// if any of the arrays were empty, a cross join should fail.
// fudge a single empty array to prevent special-casing later
if (count($this->arrays) !== func_num_args()) {
$this->arrays = array(new ArrayIterator(array()));
}
}
public function next() {
for ($i = count($this->arrays) - 1; $i >= 0; --$i) {
// carry til we don't have to anymore
$place = $this->arrays[$i];
$place->next();
if ($place->valid()) break;
}
// if $i<0, then we carried right off the edge of the list.
// don't let $arrays[0] be reset, cause that's our indicator
// that we're done.
if ($i<0) return;
++$this->index;
for (++$i; $i < count($this->arrays); ++$i) {
$this->arrays[$i]->rewind();
}
}
public function current() {
$result = array();
foreach ($this->arrays as $arr) { $result[] = $arr->current(); }
return $result;
}
public function key() { return $this->index; }
public function valid() {
return !empty($this->arrays) && $this->arrays[0]->valid();
}
public function rewind() {
foreach ($this->arrays as $arr) $arr->rewind();
$this->index = 0;
}
}
$combos = new CrossJoin(
array(1, 2, 3),
array(4, 5),
array(6, 7, 8, 9),
array(10, 11)
);
foreach ($combos as $combo) {
echo implode(', ', $combo), "\n";
}
Hope that helps:
for ($i = 0; $i < count($a1); ++i) {
for ($j = 0; $j < count($a2); ++j) {
for ($k = 0; $k < count($a3); ++k) {
for ($l = 0; $l < count($a4); ++l) {
echo $a1[$i] . ' ' . $a2[$j] . ' ' . $a3[$k] . ' ' . $a4[$l] . '\n';
}
}
}
}
Cheers!
You are looking for the PHP array_merge function.

Categories