The goal is to get some precise values of $_GET in a property of a class while:
removing any key not desired
defaulting values when keys are not defined
With this code in a file /request.php:
$req = new request();
var_dump($req);
class request {
private $Get;
function __construct() {
$this->Get = filter_input_array(INPUT_GET,array (
'menu'=>array (
'filter'=>FILTER_VALIDATE_INT,
'options'=>array (
'default'=>30,
),
),
));
}
}
from php's man page for filter_input_array() about the third parameter (true by default):
Add missing keys as NULL to the return value.
I would expect that calling domain.com/request.php would yield a defaulted [sic] array with the integer 30 as menu's value. however when no $_GET are defined (that is, when there's no character after a question mark in the url) filter_input_array returns null therefore the var_dump is this:
object(request)#1 (1) { ["Get":"request":private]=> NULL }
however when $_GET is defined (that is, having at least one character after the question mark in the url) such as calling domain.com/request.php?a will yield:
object(request)#1 (1) { ["Get":"request":private]=> array(1) { ["menu"]=> NULL } }
How can I force filter_input_array() to return an array so that default values will be built even if I call an url with no $_GET value defined like index.php?
It seems possible to rewrite a request from .htaccess so that I could mimic a $_GET value being defined if there are not, but it feels weird.
Why not to use another simple way?
var_dump(filter_var_array($_GET, array(
'key' => FILTER_DEFAULT,
), true));
In Python it is possible to have a function with several variables all having a default value. And then just passing the value of one of the values. So if I have
function foo(a=10,b=50, c=70)
pass
pass
return
Then I can call
foo(b=29)
and it would call
foo(10,29,70)
(using the default for all the values, and the exact value for that one variable).
Is something similar possible in PHP?
No there is no equivalent to that in PHP. You can have default values for function arguments, but they are evaluated from left to right and are not named:
function test($var1 = 'default1', $var2 = 'default2')
{
}
In that example the two variables are optional, but you must specify the first argument if you want to specify the second.
test(); // works
test('arg1'); // works
test('arg1', 'arg2'); // works
test('arg2'); // this will set the first argument, not the second.
A common workaround if you need flexibility on your optional arguments is to pass an array as the argument:
function test($options)
{
}
This can have a variable number of arguments in the form of a single associative array:
$options = array('var1' => 'arg1', 'var2' => 'arg2');
test($options);
Use array as an argument. For example:
function a(array $params) {
$defaults = array(
'a' => 10,
'b' => 50,
'c' => 70,
);
$params += $defaults;
// use $params
}
a(array('b' => 29));
PHP has some great functions (like array_walk) that allow you to process each element in an array. They're generally set up so you specify the array you want processed as the first parameter and a callback function to apply to each element as the second. These functions return booleans indicating success, not a copy of the modified array as you might expect. If you want the array to be modified, you have to pass the array in by reference like array_walk(&$my_array, 'my_callback');
However, in PHP 5.3 and above, if you pass by reference to function call you get a E_DEPRECATED error.
Does anyone know (if there exists) a correct way to use these functions to modify arrays without triggering the errors and without explicitly suppressing them? Are there newer alternatives to these old array processing functions.
Values are passed by reference implicitly in PHP >= 5.3 as determined by the function definition.
Function definition for array_walk():
bool array_walk ( array &$array , callable $funcname [, mixed $userdata = NULL ] )
Note &$array. As such, you do not need to explicitly pass the array by reference in the function call in PHP >= 5.3.
array_walk($my_array, 'my_callback');
However, you will need to ensure that the callback accepts it's value by reference accordingly (as demonstrated by nickb).
Also take a look at PHP 5.4 Call-time pass-by-reference - Easy fix available?
Because you should be defining the callback to accept its parameter by reference to modify the array.
array_walk( $my_array, function( &$el, $key) { $el = $el / 2; });
So a quick example like this:
$my_array = range( 2, 10, 2);
array_walk( $my_array, function( &$el, $key) { $el = $el / 2; });
var_dump( $my_array);
Will output:
array(5) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
int(3)
[3]=>
int(4)
[4]=>
int(5)
}
You can also pass an argument for the callback as the third parameter of array_walk. The problem is how to pass a reference as the callback argument. This used to be possible using the & prefix when calling array_walk. This is deprecated and subsequently made illegal. Defining the callback with a reference-type third parameter doesn't help here.
A workaround could be to pass a reference inside an array (&$var is allowed as argument of 'array'!) as the third argument and dereference the array in the callback to obtain the reference again, like so:
function cb(&$v, $k, $ar) {
$v='bla'.$k;
$ar[0]++;
}
$count=0;
$arr = array('sint'=>'er','kla'=>'aas','en'=>'zwartepiet');
array_walk($arr,'cb',array(&$count));
var_dump($arr,$count);
Which prints:
array(3) {
["sint"]=>
string(7) "blasint"
["kla"]=>
string(6) "blakla"
["en"]=>
string(5) "blaen"
}
int(3)
When call-time references were still allowed, it used to be possible like so:
function cb(&$v, $k, $ref) {
$v='bla'.$k;
$ref++;
}
$count=0;
$arr = array('sint'=>'er','kla'=>'aas','en'=>'zwartepiet');
array_walk($arr,'cb',&$count);
var_dump($arr,$count);
In Python and others, there's special syntax for variable length argument lists:
def do_something(*args):
# do something
do_something(1, 2, 3, 4, 5, ...) # arbitrarily long list
I was reading the PHP manual, and it said this:
PHP 4 and above has support for
variable-length argument lists in
user-defined functions. This is really
quite easy, using the func_num_args(),
func_get_arg(), and func_get_args()
functions.
No special syntax is required, and
argument lists may still be explicitly
provided with function definitions and
will behave as normal.
I get the first part. You can pass as many arguments as you'd like to a function that takes no arguments, then get them as an array using func_get_args(), etc. I don't really get what the second part is saying, though.
So, my question is, is there some special syntax for variable length arguments, or some best practice that I don't know about? The approach that the manual suggests seems kludgey at best and makes your function seem like it's taking no arguments (unless I'm doing it wrong). Should I not be trying to use this language feature at all?
Here is a more realistic example:
function Average()
{
$result = 0;
$arguments = func_get_args();
foreach ($arguments as $argument)
{
$result += $argument;
}
return ($result / max(1, func_num_args()));
}
Average(1, 2, 3, 4, 5); // 3
This is called a variadic function.
Unlike Python's * operator or C#'s params keyword, in PHP you don't even have to specify the variable length arguments. As the second part starts off, "No special syntax is required."
As to the rest of the second paragraph: if you want to specify any required or unrelated arguments that come before the variable-length arguments, specify them in your function signature so your function can handle those. Then to get the variable-length arguments, remove the required variables from func_get_args(), like so:
function func($required) {
// Contains all arguments that come after $required
// as they were present at call time
$args = array_slice(func_get_args(), 1);
}
You don't have to do this (you can still slice from func_get_args() and use its different elements accordingly), but it does make your code more self-documenting.
Since PHP 5.6, a variable argument list can be specified with the ... operator.
function do_something($first, ...$all_the_others)
{
var_dump($first);
var_dump($all_the_others);
}
do_something('this goes in first', 2, 3, 4, 5);
#> string(18) "this goes in first"
#>
#> array(4) {
#> [0]=>
#> int(2)
#> [1]=>
#> int(3)
#> [2]=>
#> int(4)
#> [3]=>
#> int(5)
#> }
As you can see, the ... operator collects the variable list of arguments in an array.
If you need to pass the variable arguments to another function, the ... can still help you.
function do_something($first, ...$all_the_others)
{
do_something_else($first, ...$all_the_others);
// Which is translated to:
// do_something_else('this goes in first', 2, 3, 4, 5);
}
Since PHP 7, the variable list of arguments can be forced to be all of the same type too.
function do_something($first, int ...$all_the_others) { /**/ }
There's no special syntax for variable length argument functions.
Simply use the func_num_args() and func_get_args() functions to get the arguments.
Example:
function callMe(){
if(func_num_args() == 0){
echo 'No arguments =)';
}else{
var_dump(func_get_args());
}
}
The second portion is basically saying that once you start using the variable argument functions, then
function average() { ... }
function average(arg1, arg2, arg3) { ... }
work identically, just that the second version has 3 arguments explicity listed. That's all, don't try to read more into a man page than there is.
I usually do this to avoid kept changing function, and avoid error on argument order
function any_function($ops=array())
{
}
$ops = array('name'=>1, 'type'=>'simplexml', 'callback'=>...);
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" );