23

A function (actually the constructor of another class) needs an object of class temp as argument. So I define interface itemp and include itemp $obj as the function argument. This is fine, and I must pass class temp objects to my function. But now I want to set default value to this itemp $obj argument. How can I accomplish this?

Or is it not possible?

The test code to clarify:

interface itemp { public function get(); }

class temp implements itemp
{
    private $_var;
    public function __construct($var = NULL) { $this->_var = $var; }
    public function get() { return $this->_var ; }
}
$defaultTempObj = new temp('Default');

function func1(itemp $obj)
{
    print "Got: " . $obj->get() . " as argument.\n";
}

function func2(itemp $obj = $defaultTempObj) //error : unexpected T_VARIABLE
{
    print "Got: " . $obj->get() . " as argument.\n";
}

$tempObj = new temp('foo');

func1($defaultTempObj); // Got: Default as argument.
func1($tempObj); // Got : foo as argument.
func1(); // "error : argument 1 must implement interface itemp (should print Default)"
//func2(); // Could not test as I can't define it
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
wadkar
  • 960
  • 2
  • 15
  • 29

5 Answers5

32

You can't. But you can easily do that:

function func2(itemp $obj = null)
    if ($obj === null) {
        $obj = new temp('Default');
    }
    // ....
}
Arnaud Le Blanc
  • 98,321
  • 23
  • 206
  • 194
  • thanks [found this](http://stackoverflow.com/questions/2224014/php-default-function-argument-as-a-t-variable/2224044#2224044) after searching for php method defaults, didn't think that I can compare object with nulls. – wadkar Aug 15 '11 at 12:44
4

A possible problem with Arnaud Le Blanc's answer is that in some cases you might wish to allow NULL as a specified parameter, e.g. you might wish for the following to be handled differently:

func2();
func2(NULL);

If so, a better solution would be:

function func2(itemp $obj = NULL)
{

  if (0 === func_num_args())
  {
    $obj = new temp('Default');
  }

  // ...

}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Michael
  • 11,912
  • 6
  • 49
  • 64
  • 1
    Does this make sense? The only valid parameter values are `null` and implementations of `itemp`. There is (or atleast should be from an API perspective) no behavorial difference in passing a marker for an absent value (`null`) and no value at all. I agree, if the parameter would not be typehinted, this is actually usefull in some cases. – Rangad Dec 04 '14 at 12:44
  • 1
    If you're not passing a parameter then you're doing so intentionally, and so you might want it to perform some default behaviour. If you're passing a `NULL` parameter then it's likely expecting an `itemp` implementation and so you might want it to log an error and/or throw an exception. – Michael Dec 04 '14 at 14:38
  • sneaky, that way you're introducing a bit of overloading to php. I like it. Not sure if I'd endorse it, but who cares... :) – VolkerK Feb 28 '15 at 11:02
3

PHP 8.1 and later

Since PHP 8.1 you will be able to define a new instance of an object as a default value of the function argument without error, however with some limitations.

function someFunction(Item $obj = new Item('Default'))
{
    ...
}

Documentation: PHP RFC: New in initializers

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Jsowa
  • 9,104
  • 5
  • 56
  • 60
2

Since PHP 5.5 you can simply use the ::class to pass a class as a parameter as follow:

function func2($class = SomeObject::class) {
    $object = new $class;
}

func2(); // Will create an instantiation of SomeObject class
func2(AnotherObject::class); // Will create an instantiation of the passed class
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
hassan
  • 7,812
  • 2
  • 25
  • 36
  • Thanks! Sadly it doesn't work together with a type hint: function func2(SomeInterface $class = SomeObject::class) yields a Fatal: "Default value for parameters with a class type can only be NULL" (Tested with PHP 7.2) – Den Jan 26 '20 at 09:44
0

You could use my tiny library ValueResolver in this case, for example:

function func2(itemp $obj = null)
    $obj = ValueResolver::resolve($obj, new temp('Default'));
    // ....
}

and don't forget to use namespace use LapaLabs\ValueResolver\Resolver\ValueResolver;

There are also ability to typecasting, for example if your variable's value should be integer, so use this:

$id = ValueResolver::toInteger('6 apples', 1); // returns 6
$id = ValueResolver::toInteger('There are no apples', 1); // returns 1 (used default value)

Check the docs for more examples

Victor Bocharsky
  • 11,930
  • 13
  • 58
  • 91