PHP store function in array - php

i want to store function in array
send the array to another page
then execute it
i already read Can you store a function in a PHP array but still don't know what to do
here's what i try
control.php (it start here)
<?php
function getFirstFunction(){ echo "first function executed"; }
$data = array();
$data[0] = getFirstFunction();
$data[1] = function(){ echo "second function executed"; };
$data[2] = function(){ require_once "additional.php"; };
$data[3] = "my string";
header('Location: view.php?data='.$data);
?>
additional.php
<?php echo "additional included" ?>
view.php
<?php
if( isset($_GET['data']) ){
foreach( $_GET['data'] as $temp ){
if( is_callable($temp) ){
$temp;
}else{
"its not a function";
}
}
}
?>
my error =
Warning: Invalid argument supplied for foreach() in D:\Workspace\Web\latihanns\php\get\view.php on line 4
EDIT
thanks for notify that this code its dangerous.i'm not use this code in real live. i just try to learn store function in array then call it. then i just curious how if i call it on another page. i just simply curious... i make my code look clear and simple here because i afraid if i wrote complicated code, no one will be here or my post will closed as too localized...

If you want to pass anything than string into URL, only option is convert it to string form which is reversible to original types. PHP offers function called serialize() which converts anything to string. After that, you can call unserialize() to convert string back to original data. So you have to change one line in control.php to this:
header('Location: view.php?data='.serialize($data));
In file view.php you have to change one line to this:
foreach( unserialize($_GET['data']) as $temp ){
But you have to fix more things than this. If you have callable variable, you can't invoke function with $variable, but with $variable(). It is good to mention, that in PHP does not matter if you have real function (anonymous function, Closure etc.) in variable, or if variable is simple string with name of exists function.
However you have even another bug in control.php. Code $data[0] = getFirstFunction(); will not pass function getFirstFunction an make it callable, it just calls the function and put its return value to variable. You can define getFirstFunction as anonymouse function like function in $data[1] or just pass it as string like $data[0] = 'getFirstFunction' which will work.
At the end - as anyone mentioned here - IT IS VERY DANGEROUS ans you shouldn't use this on public server.

Related

PHP scope issue within while loop

Trying to teach myself php and I am struggling with what I think is a scoping issue?
I have a query, while loop, if/else and a function.
I would like to echo the results of the function get_patronapi_data($id) within my while loop.
My code so far is as follows (stripped for legibility);
$stmt = $conn->prepare("SELECT... ..."); //QUERY here ...
if( $stmt->num_rows > 0 )
{
while ($stmt->fetch()) {
if (SomethingIsTrue){
echo get_patronapi_data($id);
}
else {
echo $somethingElse;
}
}//end while
}//end if
define("APISERVER", "http://mydomain:4500");
function get_patronapi_data($id) {
$apiurl = "APISERVER" . "/PATRONAPI/$id/dump";//line 135
$api_contents = get_api_contents($apiurl);
$api_array_lines = explode("\n", $api_contents);
foreach($api_array_lines as $line){
if(strpos($line, "EXP DATE") !== false){
$data = explode("=", $line);
return $data[1];
}//end if
}//end foreach
}//end function
function get_api_contents($apiurl) {
$api_contents = file_get_contents($apiurl);//line 154
$api_contents = trim(strip_tags($api_contents));
return $api_contents;
}//end function
echo get_patronapi_data($id); // this works and echoes $data on screen
Whenever I echo get_patronapi_data($id); outside of the functions I successfully see the data on screen. However when I echo get_patronapi_data($id); within the loop I receive the following errors;
Notice: Use of undefined constant APISERVER - assumed 'APISERVER' in
C:\xampp...search_1.php on line 135
Warning: file_get_contents(APISERVER/PATRONAPI/3047468/dump): failed
to open stream: No such file or directory in C:\xampp...search_1.php
on line 154
I'm sure I am doing something very silly however any help is appreciated.
Putting some of my comments to an answer.
You need to remove the quotes from:
$apiurl = "APISERVER" . "/PATRONAPI/$id/dump";
^ ^ <<< remove those
since that's treated as a string literal, rather than a constant.
It is declared in:
define("APISERVER", "http://mydomain:4500");
Reference:
http://php.net/manual/en/function.constant.php
Then your connection is out of scope and should be used inside your function(s).
I.e.:
function get_patronapi_data($conn, $id)
and do that for all your functions requiring a connection for them.
You will need to make sure that all folders/files have proper permissions to be written to.
The missing link is the statement:
$data = get_patronapi_data($id);
you should put before echo $data;.
It calls the function get_patronapi_data() passing the value of variable $id as argument and stores the values the function returns in the variable $data.
The variable $data you echo() is not the same as the one used by the function. They use the same name but they are different (I hope you don't use the keyword global in the function).
Read more about functions in the PHP documentation.
The updated (fragment of) code looks like:
if (SomethingIsTrue) {
$data = get_patronapi_data($id);
echo $data;
} else {
echo $somethingElse;
}
If you don't do further processing on the value returned by the function, you can, as well, remove the temporary variable $data from the code fragment above and just use:
if (SomethingIsTrue) {
echo get_patronapi_data($id);
} else {
echo $somethingElse;
}
Assuming you want to print the data from the get_patronapi_data() every iteration in the while loop, you need to actually call the method instead of using $data. Right now you're trying to print something called $data, though you never set a value to it. The $data you return in the function cannot be used outside of that function, so it does not exist in the while loop.
What you could do in your while loop is $data = get_patronapi_data();, and then echo $data. However, you can just echo get_patronapi_data(); first.
If you only want to call your function once, you need to set a variable before you start your while loop (i.e. $variable = get_patronapi_data()), and then use that variable in your while loop (i.e. echo $variable);
I'm not sure I fully understand your question. What happens if you just put
echo get_patronapi_data($id);
in the loop instead of
echo $data;
? As written, you're not calling the function in the loop.

PHP - Pass arguments into function as array without having to define as parameters

Is there away to pass a variable (with array data) into a function without having to use as a parameter each time I want to use the function?
My situation is that I have producing UI elements for a form. Right now if I define the input's name I get the field which works as designed, but I also have to pass two variables every time.
Function Defined:
function getDecision($name,$game,$answer) {
// lots of code not very relevant
}
Ideally I want to pass the $game and $answer variables inside the function for what is dependent on them. I am using code igniter and the $game variable is passed to the view on load of the page. The $answer variable can be defined within function only if the $game has been passed or define.
Current use of the function:
getDecision('company_name', $game, $answer);
Ideal use of function (simpler use):
getDecision('company_name');
Let me know if there is anything else I need to define, I don't want to show all of the code because there is nearly 100 lines of code.
You could use global variables to do so. For example:
<?php
$array = array();
function test() {
global $array;
print_r($array);
}
function main() {
test();
}
main();
?>
http://php.net/manual/en/language.variables.scope.php
Although, it should be avoided.
Using closures for this would be a good option - http://php.net/manual/en/functions.anonymous.php, specifically the 'use' construct
#!/usr/bin/env php
<?php
function getDecision($name, $game, $answer) {
echo "$name : $game : $answer \n";
}
function main() {
$my_game = "my game";
$my_answer = "my answer";
$getDecisionCaller = function($name) use ($my_game, $my_answer) {
getDecision($name, $my_game, $my_answer);
};
// Don't really need the line below, can simply use: $getDecisionCaller('company 0');
getDecision('company 0', $my_game, $my_answer);
$getDecisionCaller('company 1');
$getDecisionCaller('company 2');
}
main();
?>
Will give the output
company 0 : my game : my answer
company 1 : my game : my answer
company 2 : my game : my answer
In the code above i define getDecision($name, $game, $answer) that simply prints out the values sent.
Then, i define getDecisionCaller that accepts only $name an an argument but uses the values of $my_game, $my_answer already defined.
Note - The 'use' construct needs variables to bind to, and you cannot set the values via a string. It will give the error - 'Parse error: parse error, expecting '&'' or"variable (T_VARIABLE)"''
eg. You cannot do the below
$getDecisionCaller = function($name) use ('a game', 'an answer') {
getDecision($name, $my_game, $my_answer);
};
Hopefully, that helped :)

PHP. Pass variable by reference vs string. How to works with these two different arguments?

I'm writing my own debug functions and I need some help to fix the code below.
I'm trying to print a variable and its name, the file where the variable and the function was declared and the line of the function call. The first part I did, the variable, the variable name, the file and the line is printed correctly.
At the code, a($variable) works good.
The problem is I'd like this function accepts a string too, out of a variable. But PHP returns with a fatal error (PHP Fatal error: Only variables can be passed by reference in ...). At the code, a('text out').
So, how can I fix this code to accept a variable or a string correctly?
code (edited):
function a(&$var){
$backtrace = debug_backtrace();
$call = array_shift($backtrace);
$line = $call['line'];
$file = $call['file'];
echo name($var)."<br>".$var."<br>".$line."<br>".$file;
}
$variable='text in';
a($variable);
a('text out');
I need pass the variable by reference to use this function below (the function get the variable name correctly, works with arrays too):
function name(&$var, $scope=false, $prefix='unique', $suffix='value'){
if($scope) $vals = $scope;
else $vals = $GLOBALS;
$old = $var;
$var = $new = $prefix.rand().$suffix;
$vname = FALSE;
foreach($vals as $key => $val) {
if($val === $new) $vname = $key;
}
$var = $old;
return $vname;
}
The way your code is currently implementing pass by reference is perfect by design, but also by design cannot be changed to have two a() methods - one accepting a variable by reference and the other as a string-literal.
If the desire to pass a string literal instead of assigning it to a variable first is really needed, I would suggest creating a second convenience method named a_str() that actually accepts a string-literal instead of a variable by reference. This method's sole-purpose would be to relay the variable(s) to the original a() method - thereby declaring a variable to pass by reference.
function a_str($var) {
a($var);
}
The only thing to remember is, use a($variable); when passing by reference and a_str('some text'); when not.
Here is the same convenience-method for your name() function:
function name_str($var, $scope=false, $prefix='unique', $suffix='value'){
return name($var, $scope, $prefix, $suffix);
}
The only way to do what you are asking without writing an additional function like #newfurniturey suggests is plain and simply opening and parsing the file where your function was called as text (e.g. with fopen), using the data from debug_backtrace. This will be expensive in terms of performance, but it might be ok if used only for debugging purposes; and using this method you will no longer need a reference in your function, which means you can freely accept a literal as the parameter.

create_function with default parameter values?

Ok, I'm looking into using create_function for what I need to do, and I don't see a way to define default parameter values with it. Is this possible? If so, what would be the best approach for inputting the params into the create_function function in php? Perhaps using addslashes?
Well, for example, I have a function like so:
function testing($param1 = 'blah', $param2 = array())
{
if($param1 == 'blah')
return $param1;
else
{
$notblah = '';
if (count($param2) >= 1)
{
foreach($param2 as $param)
$notblah .= $param;
return $notblah;
}
else
return 'empty';
}
}
Ok, so how would I use create_function to do the same thing, adding the parameters and their default values?
The thing is, the parameters are coming from a TEXT file, as well as the function itself.
So, wondering on the best approach for this using create_function and how exactly the string should be parsed.
Thanks :)
Considering a function created with create_function this way :
$func = create_function('$who', 'echo "Hello, $who!";');
You can call it like this :
$func('World');
And you'll get :
Hello, World!
Now, having a default value for a parameter, the code could look like this :
$func = create_function('$who="World"', 'echo "Hello, $who!";');
Note : I only added the default value for the parameter, in the first argument passed to create_function.
And, then, calling the new function :
$func();
I still get :
Hello, World!
i.e. the default value for the parameter has been used.
So, default values for parameters work with create_function just like they do for other functions : you just have to put the default value in the list of parameters.
After that, on how to create the string containing the parameters and their values... A couple of string concatenations, I suppose, without forgetting to escape what should be escaped.
Do you want to create an anonymous function? The create_function is used to create the anonymous functions. Otherwise you need to create function normally like:
function name($parms)
{
// your code here
}
If you want to use the create_function, here is the prototype:
$newfunc = create_function('$a,$b', 'return "ln($a) + ln($b) = " . log($a * $b);');
echo "New anonymous function: $newfunc\n";
echo $newfunc(2, M_E) . "\n";
// outputs
// New anonymous function: lambda_1
// ln(2) + ln(2.718281828459) = 1.6931471805599
I'm having the same problem, trying to pass an array to a created callback function... I think I'll create a temporary variable... It's ugly but I have better to do then torture myself with slashes, my code is already cryptic enough the way it is now.
So, to illustrate:
global $tmp_someArray;
$tmp_someArray = $someArray;
$myCallback = create_function(
'$arg1',
'
global $tmp_someArray;
// do stuff with $tmp_someArray and $arg1....
return($something);
'
);

Is there a way to get the name of a variable? PHP - Reflection

I know this is not exactly reflection, but kind of.
I want to make a debug function that gets a variable and prints a var_dump and the variable name.
Of course, when the programmer writes a call to the function, they already know the variable's name, so they could write something like:
debug( $myvar, 'myvar' );
But I want it to be quick and easy to write, just the function name, the variable, and voilĂ  !
debug( $myvar ); // quicker and easier :)
You can do it by converting the variable to a key/value set before passing it to the function.
function varName($theVar) {
$variableName = key($theVar);
$variableValue = $theVar[$variableName];
echo ('The name of the variable used in the function call was '.$variableName.'<br />');
echo ('The value of the variable used in the function call was '.$variableValue.'<br />');
}
$myVar = 'abc';
varName(compact('myVar'));
Though I don't recommend creating a reference to a nameless variable, function varName(&$theVar) works too.
Since compact() takes the variable name as a string rather than the actual variable, iterating over a list of variable names should be easy.
As to why you would want to do this -- don't ask me but it seems like a lot of people ask the question so here's my solution.
I know I'm answering a 4 year old question but what the hell...
compact() might help you is your friend here!
I made a similar function to quickly dump out info on a few chosen variables into a log for debugging errors and it goes something like this:
function vlog() {
$args = func_get_args();
foreach ($args as $arg) {
global ${$arg};
}
return json_encode(compact($args));
}
I found JSON to be the cleanest and most readable form for these dumps for my logs but you could also use something like print_r() or var_export().
This is how I use it:
$foo = 'Elvis';
$bar = 42;
$obj = new SomeFancyObject();
log('Something went wrong! vars='.vlog('foo', 'bar', 'obj'));
And this would print out like this to the logs:
Something went wrong! vars={"foo":"Elvis","bar":42,"obj":{"nestedProperty1":1, "nestedProperty2":"etc."}}
Word of warning though: This will only work for variables declared in the global scope (so not inside functions or classes. In there you need to evoke compact() directly so it has access to that scope, but that's not really that big of a deal since this vlog() is basically just a shortcut for json_encode(compact('foo', 'bar', 'obj')), saving me 16 keystrokes each time I need it.
Nope, not possible. Sorry.
Not elegantly... BUT YOU COULD FAKE IT!
1) Drink enough to convince yourself this is a good idea (it'll take a lot)
2) Replace all your variables with variable variables:
$a = 10
//becomes
$a = '0a';
$$a = 10;
3) Reference $$a in all your code.
4) When you need to print the variable, print $a and strip out the leading 0.
Addendum: Only do this if you are
Never showing this code to anyone
Never need to change or maintain this code
Are crazy
Not doing this for a job
Look, just never do this, it is a joke
I know this is very very late, but i did it in a different way.
It might honestly be a bit bad for performance, but since it's for debugging it shouldn't be a problem.
I read the file where the function is called, on the line it was called and I cut out the variable name.
function dump($str){
// Get the caller with debug backtrace
$bt = debug_backtrace();
$caller = array_shift($bt);
// Put the file where the function was called in an array, split by lines
$readFileStr = file($caller['file']);
// Read the specific line where the function was called
$lineStr = $readFileStr[$caller['line'] -1];
// Get the variable name (including $) by taking the string between '(' and ')'
$regularOutput = preg_match('/\((.*?)\)/', $lineStr, $output);
$variableName = $output[1];
// echo the var name and in which file and line it was called
echo "var: " . $variableName . " dumped in file: " . $caller['file'] . ' on line: ' . $caller['line'] . '<br>';
// dump the given variable
echo '<pre>' . var_export($str, true) . '</pre>';
}
i've had the same thought before, but if you really think about it, you'll see why this is impossible... presumably your debug function will defined like this: function debug($someVar) { } and there's no way for it to know the original variable was called $myvar.
The absolute best you could do would be to look at something like get_defined_vars() or $_GLOBALS (if it were a global for some reason) and loop through that to find something which matches the value of your variable. This is a very hacky and not very reliable method though. Your original method is the most efficient way.
No, the closer you will get is with get_defined_vars().
EDIT: I was wrong, after reading the user comments on get_defined_vars() it's possible with a little hack:
function ev($variable){
foreach($GLOBALS as $key => $value){
if($variable===$value){
echo '<p>$'.$key.' - '.$value.'</p>';
}
}
}
$lol = 123;
ev($lol); // $lol - 123
Only works for unique variable contents though.
Bit late to the game here, but Mach 13 has an interesting solution: How to get a variable name as a string in PHP
You could use eval:
function debug($variablename)
{
echo ($variablename . ":<br/>");
eval("global $". $variablename . ";");
eval("var_dump($" . $variablename . ");");
}
Usage: debug("myvar") not debug($myvar)
This is late post but I think it is possible now using compact method
so the code would be
$a=1;
$b=2;
$c=3
var_dump(compact('a','b','c'));
the output would be
array (size=3)
'a' => int 1
'b' => int 2
'c' => int 3
where variable name a, b and c are the key
Hope this helps
I believe Alix and nickf are suggesting this:
function debug($variablename)
{
echo ($variablename . ":<br/>");
global $$variablename; // enable scope
var_dump($$variablename);
}
I have tested it and it seems to work just as well as Wagger's code (Thanks Wagger: I have tried so many times to write this and the global variable declaration was my stumbling block)

Categories