I am trying to use a list of variables as arguments when DEFINING a function. It seems like it should be straight forward, but no. The callback is easy and I am able to use (...$listOfVariables) to get all needed arguments into callback, but it does not work when defining the function.
I need this because I have 50 different functions that require the use all of the same arguments. When the list of arguments changes (which it does) I need a central location to make sure all of the different functions use the new list of arguments. (Again, I already can do this with the callback, but not when I define the function)
Here is how I would normally do it for a few arguments.
$var1 = 'var1text';
$var2 = 'var2text';
$var3 = 'var3text';
function funcname($var1, $var2, $var3){
echo $var1;
}
That works fine, but my list of variables changes a lot and is used in many other functions. I may be going about it the wrong way and I'm open to whatever suggestions you have. Below is what I need to accomplish.
EDITED
1.variables that are defined outside of the function
$var1 = 'var1text';
$var2 = 'var2text';
$var3 = 'var3text';
2.a variable that contains all of those variables
$listOfVar = $var1, $var2, $var3; //***see note below***.
3.include list of variables that I can use within the function so I don't have to list them one at a time like I did in the first snippet.
function funcname($listOfVar){
echo $var1;
}
the full code I am trying to make work:
$var1 = 'var1text';
$var2 = 'var2text';
$var3 = 'var3text';
$listOfVar = $var1, $var2, $var3;
function funcname($listOfVar){
echo $var1;
}
**I realize the commas in the $listOfVar syntax is not correct for this, but what IS the syntax then? I've tried variable variables ($$) - trying to convert a string to variable name references. I have tried arrays. I have tried literally hundreds of variations of these and I am just out of ideas for this. Please help.
If you do not know in advance how many variables does the end developper will use on your function, you can use func_get_args(). It returns every variables values as an array.
Here is an example of usage:
function foo() {
$arguments = func_get_args();
return $arguments;
}
print_r(foo(1, 2, 3)); // [1, 2, 3]
print_r(foo('a', 'b', 'c')); // ['a', 'b', 'c']
I used this function because you mentioned the fact that you do not know in advance how many parameters the end developper is going to put.
If instead you use an array for the passed data...
function funcname($vars){
echo $vars[0];
}
Although it has advantages not sure if this would be a good idea, but you could also use an associative array...
function funcname($vars){
echo $vars['var1'];
}
Maybe you could modify your function so that it takes an array instead of multiple arguments.
function funcname(array $args){
foreach ($args as $arg_name => $arg) {
// do stuff with $arg_name and $arg
}
// or refer to a specific argument, like where you would have said $var1, instead...
$args['var1'];
// or extract the array within your function to get the keys as variables
extract($args);
echo $var1;
// If you do this, be sure to heed the warnings about extract.
// Particularly the bit about not extracting $_GET, $_POST, etc.
}
Then instead of defining separate variables like
$var1 = 'var1text';
$var2 = 'var2text';
$var3 = 'var3text';
Create an associative array
$text['var1'] = 'var1text';
$text['var2'] = 'var2text';
$text['var3'] = 'var3text';
If you have multiple functions that need to use the same varying list of arguments, I think it makes sense to collect them in a class. Then you can pass the associative array of arguments to the class constructor so all the methods will have access to the same set of variables.
class SomeFunctions
{
private $listOfVar = [];
public function __construct(array $listOfVar) {
$this->listOfVar = $listOfVar;
}
public function funcnameA() {
foreach ($this->listOfVar as $name => $value) // ...
}
public function funcnameB() {
$this->listOfVar['var1'];
}
}
$example = new SomeFunctions(['var1' => 'something', 'var2' => 'something']);
$example->funcnameA();
$example->funcnameB();
If you need to use these functions as callbacks, you can pass them like this as the callback parameter:
functionThatTakesaCallback([$example, 'funcnameB']);
Maybe this could be the central location to change the variable list?
In future, read How to create a Minimal, Complete, and Verifiable example so we can understand your question in order to help you.
Methods have there own scope, meaning unless otherwise declared or passed through, the method will not have access to the variable.
class Retriever {
private static $instance;
protected $listOfVars = array();
public static function getInstance() {
if(self::$instance) return self::$instance;
self::$instance = new self();
return self::$instance;
}
private function __construct() {}
public function addVar($var) { array_push($this->listOfVars, $var); return $this; }
public function getVars() { return $this->listOfVars; }
public function reset() { $this->listOfVars = array(); return $this; }
}
function name($var1, $var2, $var3) {
echo $var1;
}
function anotherName($var1, $var2) {
echo $var2;
}
Retriever::getInstance()->addVar("var1text")->addVar("var2text")->addVar("var3text");
name(...Retriever::getInstance()->getVars()); # Output: var1test
Retriever::getInstance()->reset()->addVar("var1text")->addVar("var2text");
anotherName(...Retriever::getInstance()->getVars()); # Output: var2text
Live demo.
Or you can use the list() method
function name($listOfVars) {
list($var1, $var2) = $listOfVars;
echo $var1;
}
name(array(‘var1text’, ‘var2text’));
Simply put your variables in an array and pass the name of the array to your function.
$vararray[] = 'var1text';
$vararray[] = 'var2text';
$vararray[] = 'var3text';
funcname($vararray);
function funcname($variable_array){
echo $variable_array[1]; // will echo var2text
}
Related
How can i set the function as a variable in php
Similar to list function
example: list($x,$y)=array(1,2); // this is okey ,but...
How do I create such a structure?
You are talking about variable function that if a variable name has parentheses appended to it, PHP will look for a function with the same name as whatever the variable evaluates to, and will attempt to execute it. Among other things, this can be used to implement callbacks, function tables, and so forth.
Here is the little example from PHP manual Variable Functions
function foo() {
echo "In foo()<br />\n";
}
function bar($arg = '')
{
echo "In bar(); argument was '$arg'.<br />\n";
}
// This is a wrapper function around echo
function echoit($string)
{
echo $string;
}
$func = 'foo';
$func(); // This calls foo()
$func = 'bar';
$func('test'); // This calls bar()
$func = 'echoit';
$func('test'); // This calls echoit()
and the other scenario is Anonymous functions, also known as closures, allow the creation of functions which have no specified name. They are most useful as the value of callback parameters, but they have many other uses.
$greet = function($name)
{
printf("Hello %s\r\n", $name);
};
$greet('World');
$greet('PHP');
<?php
$my_array = array("Dog","Cat","Horse");
list($a, $b, $c) = $my_array;
echo "I have several animals, a $a, a $b and a $c.";
?>
The list() function is used to assign values to a list of variables. Like array(), this is not really a function, but a language construct. list() is used to assign a list of variables in one operation.
In the following code; is there a way to use the vars inside the function without having to pass them as params?
$var1 = 'test';
$var2 = 'another';
function testing(){
print $var1;
}
I read up on the php global's but wasn't sure if it was a good idea.
I have an ajax call that gets about 25 vars and replaces the tags in the body of an email where the placeholders are.
The sendEmail piece is in a function and needs access to the outside vars to be able to replace the content.
Without having a function(){} with 25 vars in it, is there another way to acomplish this?
UPDATE
Here is a sample snippet of my code; the reason why I am trying to do this.
http://pastebin.com/8qYsLg5T
You can do as the answer above make vars global.Kinda bad practice and you will end up overwriting them if you re use them and it makes them available for attacks.
What you should be doing(is writing them out) but if that is to much then making the vars an array then passing them as an array. Chances are your getting the data in an array form.
$vars = array(
'varname1' => 'var_value1',
'varname2' => 'var_value2',
'varname3' => 'var_value3',
);
do_stuff_with_vars($vars);
You could quickly create an array as someone else here suggested by using compact.
compact(var,var2,etc);
Your function should look something like
function do_stuff_with_vars($array){
//do stuff with array["varnameX"]
}
You can use compact() to put all of the variables in an array, then pass that to your function.
<?php
$data = compact($var1, $var2, $var3, $var4);
testing($data);
function testing($data) {
print $data['var1'];
print $data['var2'];
// Or, if you don't want to use an array here, use extract() to do the
// opposite of compact():
extract($data);
print $var3;
print $var4;
}
$my_array = array(
'element1' => $var1,
'element2' => $var2
);
function testing($my_array){
print $my_array['element1'];
// or use foreach()
}
The best way is using oop
class A {
public $var = 'test';
public $var2;
public function test(){
print $this->var;
}
}
$a = new A();
$a->test();
$var1 = 'test';
$var2 = 'another';
function testing(){
global $var1;
print $var1;
}
You shouldn't use globals, use OOP. You could create a class as a holder for the 25 parameters and use them from your send function
class MyMail {
public $user;
public $subject;
public $body;
public function send() {
// do the send
mail($this->user, $this->subject, ...);
}
}
$mailSender = new MyMail();
$mailSender->user = 'a#b.com';
$mailSender->subject = 'Hello';
$mailSender->send();
I just created my first PHP class, but I'm very new to this and now I don't know how to call a variable inside a function that I created.
For example:
class Example
{
public function testFunction() {
$var1 = "Test";
$var2 = "Hello";
}
}
And then, for example, echo $var1.
I know that I can call the function through this:
$something = new Example();
$something->testFunction();
But how can I call one of those variables inside the function?
I also know that if the variable was outside the function, it would be:
$something = new Example();
echo $something->var1;
I could use a return, but that way I would end with just one variable, and I have multiple variables inside that function.
I hope that you can help me.
Variables inside functions aren't available outside them. The function needs to return the variable.
i.e.
function getName(){
return "helion3";
}
echo $myClass->getName();
If you need more than one, return an array:
return array("name1","name2");
To access variables from outside class functions like that, you need to set the variables as properties of the class:
class Example {
public $var1 = '';
private $var3 = ''; // private properties etc are not available outside the class
public function testFunction() {
$this->var1 = 'Test';
$var2 = 'Test2';
$this->var3 = 'Test3';
}
}
$something = new Example();
echo $something->var1; // Test
echo $something->var2; // can't do this at all (it's not an object property)
echo $something->var3; // can't do this, it's private!
Of course, you can return whatever you like from the function itself...
public function testFunction() {
$this->var1 = 'Test';
$var2 = 'Test2';
$this->var3 = 'Test3';
return array($this->var1, $var2, $this->var3);
}
You can return private properties and locally scoped variables...
list($var1, $var2, $var3) = $something->testFunction(); // all there!
Variables declared inside your function are only accessible within the function body.
If your function needs to return more than one value, you either a) return a new object, or b) return an array:
return [$var1, $var2];
And in the calling code:
list($a, $b) = $something->testFunction();
I have a code problem which stems from the fact that I am using certain libraries of code I cannot change.
I use the following code to pass execution of any undefined methods to another class, and it works fine but it seems like a waste doubling up.
Any suggestions?
Basically I want to know if it's possible to pass an unknown number of parameters to a method (without using call_user_func_array(), just in case they need to be passed by reference). I am not asking how to use func_get_args(), rather the reverse.
Or should I just allow for a few more arguments in the first logic path (the list() code)?
class Foo {
__construct() {
$this->external = new ClassThatIHaveNoControlOver();
}
function bar($name) {
return 'Hi '.$name;
}
function __call($method, $arguments) {
if (count($arguments) < 3) {
// call_user_func_array won't pass by reference, as required by
// ClassThatIHaveNoControlOver->foobar(), so calling the function
// directly for up to 2 arguments, as I know that foobar() will only
// take 2 arguments
list($first, $second) = $arguments + Array(null, null);
return $this->external->$method($first, $second);
} else {
return call_user_func_array(array($this->external, $method), $arguments);
}
}
}
$foo = new Foo();
$firstName = 'Bob';
$lastName = 'Brown';
echo $foo->bar($firstName); // returns Hi Bob as expected
echo $foo->foobar($firstName, $lastName); // returns whatever
// ClassThatIHaveNoControlOver()->foobar() is meant to return
EDIT
Just to clarify, I know I can use this method to rejig the parameters as references, but that would mean passing everything as a reference, even if the method didn't require it - something I was trying to avoid, but seems unlikely at the moment.
As commented in the thread question post's comments this is an example and not necessarily (likely) best practice.
//Some vars
$foo = "shoe";
$bar = "bucket";
//Array of references
$arr = Array(&$foo, &$bar);
//Show that changing variable value affects array content
$foo = "water";
echo $arr[0];
//Sample function
function fooBar($a)
{
$a[0] = "fire";
}
//Call sample function
call_user_func("fooBar",$arr);
//Show that function changes both array contents and variable value by reference
echo $arr[0];
echo $foo;
Expanding a bit on the discussion, again not the most industry standard approach but it'll do the job.
function pushRefOnArray(&$arr, &$var, $key = false)
{
if(isset($key))
$arr[$key] = &$var;
else
$arr[] = &$var;
}
Essentially you can dynamically build your array and call pushRefToArray() any time you need to pass an item to be passed as reference rather than by value.
You could use something like this:
public function __call($method, $params = array()) {
switch (count($params)) {
case 0:
return $this->external->{$method}();
case 1:
return $this->external->{$method}($params[0]);
case 2:
return $this->external->{$method}($params[0], $params[1]);
case 3:
return $this->external->{$method}($params[0], $params[1], $params[2]);
default:
return call_user_func_array(array(&this->external, $method), $params);
}
}
This is probably not the wisest question, but is it possible to return a variable from a function without redeclaring it?
function test(){
$a = 1;
return $a;
}
Would it somehow be possible to access $a with just calling the function? test();
not $a = test();
Is that the only way? I want to make $a available after calling the function.
You have to put the variable into the global scope:
http://codepad.org/PzKxWGbU
function test()
{
$GLOBALS['a'] = 'Hello World!';
}
test();
echo $a;
But it would be better to use a return value or references:
function test(&$ref)
{
$ref = 'Hello World!';
}
$var = '';
test($var);
I assume you want to change some context when you call the function.
This is possible. For example, all global variables share the same context across your application. If a function set's a global variable, its available in the global scope:
function change_global_variable($name, $value)
{
$GLOBALS[$name] = $value;
}
change_global_variable('a', 1);
echo $a;
However, whenever you do something like this, take care that you're destroying the modularity of your code. For example, if you have 50 functions like this and 80 variables, and then you need to change something, you need to change many, many places. And even harder, you don't remember which places you need to change and how they belong to each other.
It's normally better to make the context an object and pass it to the function that changes it, so it's more clear what the function does:
class Context extends ArrayObject {}
$context = new Context;
function change_context(Context $context, $name, $value)
{
$context[$name] = $value;
}
change_context($context, 'b', 2);
echo $context['b'], "\n";
This example demonstrates something that's called dependency injection. Instead of modifying the only one (global) context that exists in PHP, you are telling the function what it should modify, instead that it modifies hard-encoded global variables
There is a mix form of it, using the global variable scope to contain the context, so you spare to pass it as an additional parameter, however I only show it here for completeness, because it's not helping to retain modularity that well (however it's better than using more than one global variable):
class Context extends ArrayObject {}
$context = new Context;
function change_global_context($name, $value)
{
global $context;
$context[$name] = $value;
}
change_global_context('c', 3);
echo $context['c'], "\n";
Rule of thumb: Avoid global variables. Consider them of being very expensive and you don't want your code to be expensive.
No, it is not due to the scoping.
An option would be to declare $a before and then making it a global. It will then be available inside test:
$a = '';
function test(){
global $a;
$a = 1;
return $a;
}
echo $a; // 1
But may I ask why you want to do this? Are you just playing around or do you have a use case? You're most probably doing it wrong if you need this.
Maybe if you just want to show the variable you can use
function test(){
$a = 1;
echo $a;
return $a;
}
in this way if you want you can save the variable $a in a variable if not you can just show it calling the test function.
Hope it helps.
Nicola.