0

Lets assume I have the following function:

<?php
    function MyFunction($color="green", $type="wood", $shape="circle")
    {
        echo "Its a ", $color , " " , $shape, ", made of " , $type , ".";
    }

    MyFunction();    // prints Its a green circle, made of wood.
?>

All three parameters in the function are optional parameters.

I know I can skip a parameter by typing null in its parameter slot. For example, to change wood to plastic, I would have to type in:

MyFunction(null,"plastic");

How can I call the same function and parse to the function which variable I want to change without using something fancy like an array?

For example, if we take Powershell, the code would be like this:

function MyFunction()
{
    [CmdletBinding()]
    param (
        [Parameter(Mandatory=$False)][string]color=green,
        [Parameter(Mandatory=$False)][string]type=wood,
        [Parameter(Mandatory=$False)][string]circle=circle
    )

    write-host "Its a" $color $shape", made out of" $type"."
}

In Powershell, I can call the function in two ways.

MyFunction "red", "plastic", "square"

or

MyFunction -type "plastic"

How can I achieve the second way in php? For example, lets assume the following code is valid:

MyFunction ($type="plastic");
0

4 Answers 4

1

If you really do not want to use an array, I would suggest you to use setting a param to null for using a default value. But it is set in the function's body.

function MyFunction($color=null, $type=null, $shape=null)
{
    echo "Its a ", $color ?? 'green' , " " , $shape ?? 'circle', ", made of " , $type?? 'wood' , ".";
}

I am using the null coalescing operator here. Follow the link for more information.

Sign up to request clarification or add additional context in comments.

7 Comments

Sorry to say this, but if you pass null to a function that has an optional parameter, it will understand that you want the optional parameter. Try it out and be amazed.
But the whole point is that I want to ommit having to put null values in their place, because I plan on making it possible to have the function have more parameters in the future without having to look up what all the params and their positions are every time I want to use them. So I really am looking for a way to name the variables I parse, which so far, seems to be only possible with arrays.
For me it looks like arrays or objects are the best way to go
Hmm, this used to be possible. I have to do some more research it seems. (the ability to ommit an optional parameter. I thought it was doing func(param,,param) but that didn't work, so I used null and that seemed to work, but indeed seems to parse null to it now. Dunno why it works in the example in my code, but in my test doesn;t. maybe null cannot be the first param in a function
apparnetly using null skips the param and uses the next one. I think this is actually a bug in php.
|
1

I 'd suggenst working with value objects because you can 't get a single function work like you described in PHP. A possible solution could look like the following example. (Type safety included)

class Thing
{
    protected string $color = 'green';
    protected string $type = 'wood';
    protected string $shape = 'circle';

    public function getColor(): string
    {
        return $this->color;
    }

    public function setColor(string $color): self
    {
        $this->color = $color;
        return $this;
    }

    public function getType(): string
    {
        return $this->type;
    }

    public function setType(string $type): self
    {
        $this->type = $type;
        return $this;
    }

    public function getShape(): string
    {
        return $this->shape;
    }

    public function setShape(string $shape): self
    {
        $this->shape = $shape;
        return $this;
    }

    public function __toString(): string
    {
        return "Its a " . $this->color . " " . $this->shape . " made of " . $this->type . ".";
    }
}

function yourFunction(Thing $thing): void
{
    echo $thing;
}

$thing = (new Thing())
    ->setColor('red')
    ->setShape('rectangle');

yourFunction($thing); // Its a red rectangle made of wood.

Since we work with an value object you don not have to deal with function parameters anymore. The object has all the properties you need. Through the getter and setter functions you are able to get all the values you need. If a value is not set, the default value will work instead. Your function does only take the object as parameter.

5 Comments

This is a very elaborate construction when using an array is a simpler approach then. Thanks for the suggestion though...
It all depends on how complex the project will be. PHP arrays are very imprecise. If in doubt, you do not know the contents of an array and you always have to check whether the elements that you expect are actually included. You don't have this problem with a value object. In addition, the problem with the function parameters is completely eliminated, since you only pass the value object, which already contains all expected values. Only when you initialize the value object do you enter the values that actually differ from the standard values.
Yes, I know. I work with classes a lot. This is going to be for a function inside a class, and making a new object specifically for this function is going to make my project too complex to allow others to work on it too. I want to contain as much inside the function without it being too complex. Arrays seem to become the only option here, and even that turns quite complex due to not being able to predefine the array values before it becomes a parameter
I understand you and the situation you are in now, all too well. From experience I can say that the Value Object, although it means more effort at the moment, ultimately makes more sense and results in clean code that benefits everyone. It 's up to you. ;)
I am constructing something that uses an array, which seems to do what I want. I'll post it as an answer even though I will not mark it solved just so others see what I'm after and might give me an answer I actually like in the future.
0

PHP is a bit tricky language in this problem because function arguments is passed by order. You can pass null values or leave last argument non provided by calling function (which have default value)

But from 5.6.x versions you can use argument unpacking in functions. PHP

Example:

function add($a, $b, $c) {
    return $a + $b + $c;
}

$operators = [2, 3];
echo add(1, ...$operators);

Output: 10

Also you can use older approach func_get_args() Example:

function foo(){

    $numargs = func_num_args();
    echo "Number of arguments: $numargs \n";

    if ($numargs >= 2) {
        echo "Second argument is: " . func_get_arg(1) . "\n";
    }

    $arg_list = func_get_args();

    for ($i = 0; $i < $numargs; $i++) {
        echo "Argument $i is: " . $arg_list[$i] . "\n";
    }

}

foo(1, 2, 3);

3 Comments

It seems variadic functions is going to come the closest to what I'm looking for, grouping all optional functions into an array.
Yup since there is no better alternative right now. I also use spread array operator in arguments, but I prefer to use required first arguments, and last one leave array of arguments
I still can't define its defaults though, without going through hoops and hoops...
0

For now, it seems it is not possible to do. I wanted to avoid arrays because I could not figure out how to set defaults, but I have managed to figure that part out. I still would like a better solution, but for now, this comes closest to what I want. I'll leave the question open for when PHP actually starts to support it and someone posts the correct answer.

The code I am using right now is as follows:

<?php
    function MyFunction($params=null)
    {   // define defaults
        $arg['color'] = 'green';
        $arg['shape'] = 'circle';
        $arg['type'] = 'wood';

        if( isset($params) )
        {
            $arg = array_merge($arg,$params);
        }

        echo "Its a ", $arg['color'] , " " , $arg['shape'], ", made of " , $arg['type'] , ".";
    }
    MyFunction(); 
    // prints Its a green circle, made of wood.

    MyFunction(array('type'=>'plastic', 'shape'=>'square'));
    // prints Its a green square, made of plastic.

?>

EDIT: Refining that idea to what I really want makes the code more ugly in the function itself, but makes calling the function a lot pretier.

<?php
    function MyFunction(...$params)
    {   // define defaults
        $arg['color'] = 'green';
        $arg['shape'] = 'circle';
        $arg['type'] = 'wood';

        if( count($params)>0 )
        {   // We have more than 0 params

            foreach($params as $id=>$param)
            {
                if( strpos($param,"=") )
                {   // if we have a param assigner.
                    $array = explode('=', $param);              
                    $array2[$array[0]]=$array[1];
                    $arg = array_merge($arg,$array2);
                }
                else
                {   // assume the params are in correct order.
                    $arraykeys = array_keys($arg);
                    $arg[ $arraykeys[$id] ] = $param;
                }
            }

        }


        echo "Its a ", $arg['color'] , " " , $arg['shape'], ", made of " , $arg['type'] , ".<br/>";
    }

    MyFunction();    // prints Its a green circle, made of wood.
    MyFunction('red', 'square');    // prints Its a red square, made of wood.
    MyFunction('color=pink', 'type=plastic');    // prints Its a pink circle, made of plastic.
?>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.