Related
This is a simplified version of a very large user-defined function I have...
function validate_promotional_code($code, $params = ["reference" => "code", "input-type" => "single", "delimiter" => ","]) {
global $node_connection;
$operator_array = [
"Free With Purchase",
"Buy One Get One Free"
];
return $params;
}
I have used this method of passing an associative array with default values into a user-defined function many times. It lets me set default values for my function without having to worry about which variable is where, etc.
Unfortunately, this function returns nothing, where it should return the $params array containing my default values.
Have I made a syntax error? Why is my function not receiving my default values?
The default $params array will be used by your function – but only if the function call does not contain a $params argument at all.
If there is any value passed for $params, that one will be used instead of your default. PHP does not care that it’s an array and does not merge it. You’ll have to do that on your own:
function validate_promotional_code($code, $params = []) {
$defaults = ["reference" => "code", "input-type" => "single", "delimiter" => ","];
$params = array_merge($defaults, $params);
// ... work with $params ...
}
The array_merge() function will merge the two arrays, while values in the latter one will overwrite values in the first. That’s why we put $defaults as the first argument.
Can pass a value to specific argument in function ?
function fun1($a,$b)
{
echo $b;
}
#fun1(123);
Functions can be defined so that they do not require all parameters. For example:
function foo($a, $b = 2) {
echo $a + $b;
}
foo(1); //gives 3
Read about default function values here
However, you cannot pass in later parameters without specifying earlier ones. Some simple programming-function-parameters-basics... when you do foo($b) the function has no idea that the variable was named b... It just gets the data; usually a primitive type (in this case an int) or a reference.
You haven't specified how you're using these variables, so you may want to give a dummy value like "-1" to $a (and handle it in your function) (foo(-1, 123)), or rewrite your function so that $a is the second parameter with the default value. (function foo($b, $a = NULL))
That's why you must pass the variables in order; the function assumes you're using it right, and it lines up the values passed with the function definition. function foo($a, $b) means "I'm assuming I should associate your first value with a and your second value with b)".
With your original example function foo($a, $b):
No context, so I would just say do this function foo($b, $a = some_default_value). However, I'm assuming you're using $a and $b equally so you could check to see if it was some default-invalid-value and act on it. However, if your function performs different tasks depending on the (number of) parameters passed, you probably want to separate your function.
If you insist on not switching the order, you could call foo(-1, 123) with a dummy value and check it. Again though, same problem as above
Edit: You've given another example foo($a, $b, $c) and you said you want to do foo($b) to update the middle value. See the explanation in the first paragraph about how a function knows what parameter is what.
If you mean you want to pass an arbitrary set of variables to a function and it knows which ones it got? Again I don't think this is the best practice (you'll need to give us more detail about how you're using this) but you could pass an associative array:
function foo($arr) {
if (isset($arr['a'])) {
echo $a;
}
if (isset($arr['b'])) {
echo $b;
}
if (isset($arr['c'])) {
echo $c;
}
}
foo(array('b' => 123));
I feel horrible after writing this function :P
<?php
function FUN1($a, $b)
{
echo "HI";
echo $b;
} //$_a= 123; //error_reporting (E_ALL ^ E_NOTICE ^ E_WARNING); //$b=23; echo #FUN1(123);//it gives HI123
?>
I formatted your function. Firstly, when I tried that call it doesn't give me "HI123". Secondly, # is bad practice and really slows down the code. Thirdly, you don't echo FUN1 since it doesn't return anything; your function prints the stuff itself.
You (your student) are/is going in the wrong direction. As I said in my comment, functions already have a beautiful way of sorting out the parameters. Instead of trying to do something funky and work around that, just change your approach.
The example above has no real use and I'm sure in actual code you should just write different functions when you're setting different variables. like setA($a) setB($b) setC($c) setAll($a, $b, $c) and use them accordingly. Arrays are useful for easy variable length functions, but if you're checking each tag to do something, then something's wrong.
If you only want to pass one argument, you could make a wrapper function like this:
function PassOne($arg)
{
fun1(NULL,$arg);
}
function fun1($a,$b)
{
echo $b;
}
Forgive any inaccuracies. It's been a while since I coded in PHP.
If you want to ensure the order of arguments, you can pass a single array as an argument.
$args = array(
'name' => 'Robert',
'ID' => 12345,
'isAdmin' => true
);
example($args);
function example($args)
{
echo $args['name']; // prints Robert
echo $args['ID']; // prints 12345
echo $args['isAdmin']; // prints true
}
Using this approach, you can also hard-code default values into the function, replacing them only when they're provided in the argument array. Example:
$args = array(
'name' => 'Robert',
'ID' => 12345
// Note that I didn't specify whether Robert was admin or not
);
example($args);
function example($args)
{
$defaultArgs = array(
'name' => '',
'ID' => -1,
'isAdmin' => false // provides a default value to incomplete requests
);
// Create a new, mutable array that's a copy of the default arguments
$mixArgs = $defaultArgs;
// replace the default arguments with what was provided
foreach($args as $k => $v) {
$mixArgs[$k] = $v;
}
/*
Now that we have put all the arguments we received into $mixArgs,
$mixArgs is mix of supplied values and default values. We can use
this fact to our advantage:
*/
echo $mixArgs['name']; // prints Robert
// if ID is still set to the default value, the user never passed an ID
if ($mixArgs['ID'] == -1) {
die('Critical error! No ID supplied!'); // use your imagination
} else {
echo mixArgs['ID']; // prints 12345
}
echo mixArgs['isAdmin']; // prints false
// ... etc. etc.
}
2018's PHP syntax and defaults
function example($args=[], $dftArgs=['name'=>'', 'ID' => -1, 'isAdmin'=>false])
{
if (is_string($args))
$args = json_decode($args,true); // for microservice interoperability
$args = array_merge($dftArgs,$args);
// ... use $args
}
// PS: $dftArgs as argument is not usual, is only a generalization
No.
But by convention you can skip arguments to built in functions by passing NULL in that position:
fun1(NULL, 123);
Obviously this is doesn't make sense for everything - for example this makes no sense:
$result = strpos(NULL, 'a string');
For user defined functions, it's up to you to handle the arguments in whatever way you see fit - but you might find func_get_arg()/func_get_args() useful for functions that use an indeterminate number of arguments.
Also, don't forget you can make arguments optional by defining default values:
function fun ($arg = 1) {
echo $arg;
}
fun(2); // 2
fun(); // 1
Note that default values can only be defined on the right-most arguments. You cannot give an argument a default value if an argument to its right does not have one. So this is illegal:
function fun ($arg1 = 1, $arg2) {
// Do stuff heere
}
When calling a function is there a way to simplify the argument list? Instead of using $blank.
$subscribe=1;
$database->information($blank,$blank,$blank,$blank,$blank,$blank,$subscribe,$blank,$blank,$blank,$blank,$blank);
function information ($search,$id,$blank,$category,$recent,$comment,$subscribe,$pages,$pending,$profile,$deleted,$reported) {
//code
}
You could pass in an array with the specified keys, and merge it with an array of default values
So instead of
function foo($arg1 = 3, $arg2 = 5, $arg3 = 7) { }
You'd have
function foo($args) {
$defaults = array(
'arg1' => '',
'arg2' => null,
'arg3' => 7
);
// merge passed in array with defaults
$args = array_merge($defaults, $args);
// set variables within local scope
foreach($args as $key => $arg) {
// this is to make sure that only intended arguments are passed
if(isset($defaults[$key])) ${$key} = $arg;
}
// rest of your code
}
Then call it as
foo(array('arg3' => 2));
Yes, pass an array instead, or refactor. A long arguments list is usually a bad smell.
function information(array $params) {....
information(array('search'=>'.....
Twelve arguments are generally too many for one function. It's likely that your code could be simplified (including the argument lists getting shorter) by refactoring function information which looks likely to be a monster.
Stopgap measures you can use in the meantime are
adding default argument values
making the function accept all its arguments as an array
Both of the above will require you to visit all call sites for the function for review and modification.
Adding default arguments is IMHO the poor choice here, as by looking at the example call it seems that you would need to make all arguments default, which in turn means that the compiler will never warn you if you call the function wrongly by mistake.
Converting to an array is more work, but it forces you to rewrite the calls in a way that's not as amenable to accidental errors. The function signature would change to
function information(array $params)
or possibly
function information(array $params = array())
if you want all parameters to be optional. You can supply defaults for the parameters with
function information(array $params) {
$defaults = array('foo' => 'bar', /* ... */);
$params += $defaults; // adds missing values that have defaults to $params;
// does not overwrite existing values
To avoid having to rewrite the function body, you can then use export to pull out these values from the array into the local scope:
export($params); // creates local vars
echo $foo; // will print "bar" unless you have given another value
See all of this in action.
You can make it so the function wil automatically fill the variable with a given value like an empty string:
function information ($subscribe, $search="", $id="", $blank="", $category="", $recent="", $comment="", $pages="", $pending="", $profile="", $deleted="", $reported="") {
//code
}
Yes, there are several ways:
Accept an associative array as a single argument, and pass what you need to that. Throw exceptions if a critical argument is missing.
Place critical arguments at the head of the function definition, and optional ones at the end. Give them a default value so that you don't have to declare them.
Recosinder your function. 12 arguments is much too many for one function. Consider using a class/object, or dividing the work between different functions.
Several ways:
function test($input = "some default value") {
return $input; // returns "some default value"
}
function test($input) {
return $input;
}
test(NULL); // returns NULL
function test() {
foreach(func_get_args() as $arg) {
echo $arg;
}
}
test("one", "two", "three"); // echos: onetwothree
I have the following PHP function:
function func_name($name = 'John', $country = 'USA')
{
do something;
}
And now, am trying to pass variable to the function as follows:
func_name($name = 'Jack', $country = 'Brazil');
I know, we can pass it easily as func_name('jack', 'Brazil'); but the above function is just an example. The actual function has around 20 arguments and all have default values, and some are not at all passed to the function
So I would like to know if its proper to pass arguments as func_name($name = 'Jack', $country = 'Brazil');
No, it's not the right way to do it. foo($bar = 'baz') means you're assigning 'baz' to the variable $bar as usual. This assignment operation results in the value that was assigned, so the expression $bar = 'baz' has the value 'baz'. This value 'baz' gets passed into the function. The functions doesn't have any clue that you have assigned to a variable $bar.
In other words, PHP doesn't support named arguments.
If your function accepts many parameters, all or most of which are optional, use arrays:
function foo(array $args = array()) {
// set default values for arguments not supplied
$args += array('name' => 'John', 'country' => 'USA', …);
// use $args['name'] etc.
// you could do extract($args), then use $name directly,
// but take care not to overwrite other variables
}
foo(array('country' => 'Japan'));
Could you pass in an array?
function something($arr) {
$name = $arr['name'];
}
function something(Array("name"=>"jack", "country"=>"UK"));
I've written a PHP function that can accept 10 parameters, but only 2 are required. Sometimes, I want to define the eighth parameter, but I don't want to type in empty strings for each of the parameters until I reach the eighth.
One idea I had was to pass an abstracted function with an array of parameters which passes it along to the real function.
Is there a better way to set up the function so I can pass in only the parameters I want?
What I have done in this case is pass an array, where the key is the parameter name, and the value is the value.
$optional = array(
"param" => $param1,
"param2" => $param2
);
function func($required, $requiredTwo, $optional) {
if(isset($optional["param2"])) {
doWork();
}
}
Make the function take one parameter: an array. Pass in the actual parameters as values in the array.
Edit: the link in Pekka's comment just about sums it up.
To accomplish what you want, use an array Like Rabbot said (though this can become a pain to document/maintain if used excessively). Or just use the traditional optional args.
//My function with tons of optional params
function my_func($req_a, $req_b, $opt_a = NULL, $opt_b = NULL, $opt_c = NULL)
{
//Do stuff
}
my_func('Hi', 'World', null, null, 'Red');
However, I usually find that when I start writing a function/method with that many arguments - more often than not it is a code smell, and can be re-factored/abstracted into something much cleaner.
//Specialization of my_func - assuming my_func itself cannot be refactored
function my_color_func($reg_a, $reg_b, $opt = 'Red')
{
return my_func($reg_a, $reg_b, null, null, $opt);
}
my_color_func('Hi', 'World');
my_color_func('Hello', 'Universe', 'Green');
You can just set the default value to null.
<?php
function functionName($value, $value2 = null) {
// do stuff
}
In PHP 5.6 and later, argument lists may include the ... token to denote that the function accepts a variable number of arguments. The arguments will be passed into the given variable as an array; for example:
Example Using ... to access variable arguments
<?php
function sum(...$numbers) {
$acc = 0;
foreach ($numbers as $n) {
$acc += $n;
}
return $acc;
}
echo sum(1, 2, 3, 4);
?>
The above example will output:
10
Variable-length argument lists PHP Documentation
NOTE: This is an old answer, for PHP 5.5 and below. PHP 5.6+ supports default arguments
In PHP 5.5 and below, you can achieve this by using one of these 2 methods:
using the func_num_args() and func_get_arg() functions;
using NULL arguments;
How to use
function method_1()
{
$arg1 = (func_num_args() >= 1)? func_get_arg(0): "default_value_for_arg1";
$arg2 = (func_num_args() >= 2)? func_get_arg(1): "default_value_for_arg2";
}
function method_2($arg1 = null, $arg2 = null)
{
$arg1 = $arg1? $arg1: "default_value_for_arg1";
$arg2 = $arg2? $arg2: "default_value_for_arg2";
}
I prefer the second method because it's clean and easy to understand, but sometimes you may need the first method.
Starting with PHP 8 you are able to use named arguments:
function namedParameters($paramOne, $paramTwo, $paramThree = 'test', $paramFour = null)
{
dd($paramOne, $paramTwo, $paramThree, $paramFour);
}
We can now call this function with the required params and only the optinal params, that we want to differ from the default value which we specified in the function.
namedParameters('one', 'two', paramFour: 'four');
Result:
// "one", "two", "test", "four"
I think, you can use objects as params-transportes, too.
$myParam = new stdClass();
$myParam->optParam2 = 'something';
$myParam->optParam8 = 3;
theFunction($myParam);
function theFunction($fparam){
return "I got ".$fparam->optParam8." of ".$fparam->optParam2." received!";
}
Of course, you have to set default values for "optParam8" and "optParam2" in this function, in other case you will get "Notice: Undefined property: stdClass::$optParam2"
If using arrays as function parameters, I like this way to set default values:
function theFunction($fparam){
$default = array(
'opt1' => 'nothing',
'opt2' => 1
);
if(is_array($fparam)){
$fparam = array_merge($default, $fparam);
}else{
$fparam = $default;
}
//now, the default values are overwritten by these passed by $fparam
return "I received ".$fparam['opt1']." and ".$fparam['opt2']."!";
}
If only two values are required to create the object with a valid state, you could simply remove all the other optional arguments and provide setters for them (unless you dont want them to changed at runtime). Then just instantiate the object with the two required arguments and set the others as needed through the setter.
Further reading
Martin Fowler on Constructor vs Setter Injection and
Dependency injection through constructors or property setters?
I know this is an old post, but i was having a problem like the OP and this is what i came up with.
Example of array you could pass. You could re order this if a particular order was required, but for this question this will do what is asked.
$argument_set = array (8 => 'lots', 5 => 'of', 1 => 'data', 2 => 'here');
This is manageable, easy to read and the data extraction points can be added and removed at a moments notice anywhere in coding and still avoid a massive rewrite. I used integer keys to tally with the OP original question but string keys could be used just as easily. In fact for readability I would advise it.
Stick this in an external file for ease
function unknown_number_arguments($argument_set) {
foreach ($argument_set as $key => $value) {
# create a switch with all the cases you need. as you loop the array
# keys only your submitted $keys values will be found with the switch.
switch ($key) {
case 1:
# do stuff with $value
break;
case 2:
# do stuff with $value;
break;
case 3:
# key 3 omitted, this wont execute
break;
case 5:
# do stuff with $value;
break;
case 8:
# do stuff with $value;
break;
default:
# no match from the array, do error logging?
break;
}
}
return;
}
put this at the start if the file.
$argument_set = array();
Just use these to assign the next piece of data use numbering/naming according to where the data is coming from.
$argument_set[1][] = $some_variable;
And finally pass the array
unknown_number_arguments($argument_set);
function yourFunction($var1, $var2, $optional = Null){
... code
}
You can make a regular function and then add your optional variables by giving them a default Null value.
A Null is still a value, if you don't call the function with a value for that variable, it won't be empty so no error.
As of PHP 7.1.0, type declarations can be marked nullable by prefixing the type name with a question mark (?). This signifies that the value can be of the specified type or null
<?php
function name(?string $varname){
echo is_null($varname);
}
name();
name('hey');
?>
for more info: Click here
If you are commonly just passing in the 8th value, you can reorder your parameters so it is first. You only need to specify parameters up until the last one you want to set.
If you are using different values, you have 2 options.
One would be to create a set of wrapper functions that take different parameters and set the defaults on the others. This is useful if you only use a few combinations, but can get very messy quickly.
The other option is to pass an array where the keys are the names of the parameters. You can then just check if there is a value in the array with a key, and if not use the default. But again, this can get messy and add a lot of extra code if you have a lot of parameters.
PHP allows default arguments (link). In your case, you could define all the parameters from 3 to 8 as NULL or as an empty string "" depending on your function code. In this way, you can call the function only using the first two parameters.
For example:
<?php
function yourFunction($arg1, $arg2, $arg3=NULL, $arg4=NULL, $arg5=NULL, $arg6=NULL, $arg7=NULL, $arg8=NULL){
echo $arg1;
echo $arg2;
if(isset($arg3)){echo $arg3;}
# other similar statements for $arg4, ...., $arg5
if(isset($arg8)){echo $arg8;}
}
Just set Null to ignore parameters that you don't want to use and then set the parameter needed according to the position.
function myFunc($p1,$p2,$p3=Null,$p4=Null,$p5=Null,$p6=Null,$p7=Null,$p8=Null){
for ($i=1; $i<9; $i++){
$varName = "p$i";
if (isset($$varName)){
echo $varName." = ".$$varName."<br>\n";
}
}
}
myFunc( "1", "2", Null, Null, Null, Null, Null, "eight" );
func( "1", "2", default, default, default, default, default, "eight" );