Single function to read one, read all, or set I have the below function, it is designed so I can call:

$object-&gt;temp('one', 1);    //add the key `one` to the temp array with value 1
$object-&gt;temp('two', 2);    //add the key `two` to the temp array with value 2
$object-&gt;temp('three', 3);  //add the key `three` to the temp array with value 3

$object-&gt;temp('three');       //returns 3
$object-&gt;temp('three', null); //removes the `three` key
$object-&gt;temp();              //returns array('one' =&gt; 1, 'two' =&gt; 2)


and it works well, my only gripe is that I don't like using the $value = 'read_temp in the definition, it feels like a hack to me.

So, is there anything wrong with that, and how can this function be optimized?

public function temp($key = null, $value = 'read_temp') {
    if($key === null)
        return $this-&gt;temp;

    if ($value === null){
        unset($this-&gt;temp[$key]);
    }

    elseif ($value == 'read_temp' &amp;&amp; isset($this-&gt;temp[$key])) {
        $value = $this-&gt;temp[$key];
    } else {
        $this-&gt;temp[$key] = $value;
    }

    return $value;
}


I could split this into two setTemp getTemp (or three clearTemp to be pedantic) functions, but I would like to be able to have just one function call to do everything.
Here's one way to do it

public function temp($key = null , $value = null) {
    $args = func_get_args();
    if( count($args) === 2 ) {
        $this-&gt;temp[$key] = $value;
    } elseif( count($args) === 1 ) {
        return @$this-&gt;temp[$key];
    } else {
        return $this-&gt;temp;
    }
}


func_get_args() will return an array of the arguments that were actually passed - i.e. excluding default values. So if no arguments were passed, return the array; if there's 1 argument (the key), return the corresponding value; and if there are 2 arguments, set the key/value pair.

I'm using the warning-suppression @ instead of explicitly checking isset(). Again, the end result is the same; if you check with isset() and don't (explicitly) return anything for missing keys, the function still returns NULL. If you simply return $this-&gt;temp[$key]with no checking, but suppress the "undefined index" warning that might occur, you also get NULL.

I've also skipped the unset() call, since calling $obj-&gt;tmp("key", null) does pretty much the same thing. If you request a value that hasn't been set, you get NULL. If you set that value to NULL, you get NULL. If you were to unset the value, you'd also get NULL.
But if you want to keep the unset, you can just check $value === null in the first branch:

if( count($args) === 2 ) {
    if( $value === null ) {
        unset($this-&gt;temp[$key]);
    } else {
        $this-&gt;temp[$key] = $value;
    }
} // ...


If you skip the unset() part, it'll obviously keep the array keys around, so you won't know for sure if a key whose value is NULL was "deleted", or if it was explicitly set to NULL on purpose.
On the other hand, if you unset() when the passed value is NULL, you won't be able to set a value to NULL on purpose.

The simplest solution is to not use unset in the temp() function, but instead add an extra unset_temp_value($key) function that does the unset. Then you can use that to explicitly remove all traces of a key/value pair, while still being able to store NULLs "on purpose" using temp($key, null).



As mseancole points out below, a switch statement could be used too

public function temp($key = null, $value = null) {
  $args = func_get_args();
  switch( count($args) ) {
    case 2:
      return $this-&gt;temp[$key] = $value;
    case 1:
      return @$this-&gt;temp[$key];
    default:
      return $this-&gt;temp;
  }
}


Only difference is that this returns the value that's set in the first case (just because it's more compact then breaking)

And just for fun, here's the same thing again in Unreadable Mode™

public function temp($key = null, $value = null) {
  $args = count(func_get_args());
  return ($args==2?($this-&gt;temp[$key]=$value):($args==1?@$this-&gt;temp[$key]:$this-&gt;tmp));
}