7

I'm sure there is a better to this. Any help will be greatly appreciated.

I want to pass an array to a php function that contains the argument and all the arguments are optional. I'm using code ignitor and am by no means an expert. Below is what i have been using so far:

function addLinkPost($postDetailArray) {

    if (isset($postDetailArray['title'])) {
        $title = $postDetailArray['title']; }
    else {
        $title = "Error: No Title";
    }

    if (isset($postDetailArray['url'])) {
        $url        = $postDetailArray['url'];
    } else {
        $url        = "no url";
    }
    if (isset($postDetailArray['caption'])) {
        $caption    = $postDetailArray['caption'];
    } else {
        $caption    = "";
    }
    if (isset($postDetailArray['publish'])) {
        $publish    = $postDetailArray['publish'];
    } else {
        $publish    = TRUE;
    }
    if (isset($postDetailArray['postdate'])) {
        $postdate   = $postDetailArray['postdate'];
    } else {
        $postdate   = "NOW()";
    }
    if (isset($postDetailArray['tagString'])) {
        $tagString  = $postDetailArray['tagString'];
    } else {
        $tagString = "";
    }
Ross
  • 14,266
  • 12
  • 60
  • 91

6 Answers6

27

You can use an array of defaults and then merge the argument array with the defaults. The defaults will be overridden if they appear in the argument array. A simple example:

$defaults = array(
    'foo' => 'aaa',
    'bar' => 'bbb',
    'baz' => 'ccc',
);

$options = array(
    'foo' => 'ddd',
);


$merged = array_merge($defaults, $options);

print_r($merged);

/*

Array
(
    [foo] => ddd
    [bar] => bbb
    [baz] => ccc
)

*/

In your case, that would be:

function addLinkPost($postDetailArray) {
    static $defaults = array(
        'title'     => 'Error: No Title',
        'url'       => 'no url',
        'caption'   => '',
        'publish'   => true,
        'postdate'  => 'NOW()',
        'tagString' => '',
    );

    $merged = array_merge($defaults, $postDetailArray);

    $title     = $merged['title'];
    $url       = $merged['url'];
    $caption   = $merged['caption'];
    $publish   = $merged['publish'];
    $postdate  = $merged['postdate'];
    $tagString = $merged['$tagString'];
}
Ionuț G. Stan
  • 176,118
  • 18
  • 189
  • 202
  • This is the way to do it. You get the desired result and you get a very readable summary of what the default values are. It's essentially letting PHP do for you instead of looping, yourself. PHP provides so many wonderful array functions, that I abhor looping over an array -- whenever I see looping through an array, I smell something that can probably be replaced by native array functions. – grantwparks Sep 25 '09 at 20:24
  • Agree - this is by far the most readable way to do this. Less LOC is not always better. – calumbrodie Jan 10 '12 at 15:36
  • Elegant! Note, however, that a use of a separate "merged' array is not strictly necessary. I'm adding the following as a drop-in improvement to my existing code: $argsR = array_merge ($defaultsR, $argsR; ($argsR being the existing function arguments array passed to and processed by the existing function). – Frank van Wensveen Oct 05 '15 at 12:02
10

You could do it like this:

function addLinkPost(array $postDetailArray)
{
    $fields = array(
        'key' => 'default value',
        'title' => 'Error: No Title',
    );

    foreach ($fields as $key => $default) {
        $$key = isset($postDetailArray[$key]) ? $postDetailArray[$key] : $default;
    }
}

Simply edit the $fields array with your key and its default value.

Inspire
  • 2,052
  • 15
  • 14
  • You should be a bit careful doing stuff like this, especially if the data is user-supplied, because it is similar to register_globals. – Tom Haigh Sep 25 '09 at 12:15
  • @Tom Although personally I'd implement it using an array to store the values as opposed to the function local variable scope he used in his question and I used in my response, you could implement a quick check in the foreach loop to ignore any supplied keys that are not in the $fields array – Inspire Sep 25 '09 at 12:24
  • Actually on second thought my example iterates over the $fields array as opposed to $postDetailArray so the key check wouldn't be necessary. – Inspire Sep 25 '09 at 12:28
4

Using the array as an argument is a good idea in this case. However, you could simplify the code in the function a bit by using the ternary operator (http://dk.php.net/ternary):

$title = isset($postDetailArray['title']) ? $postDetailArray['title'] : 'Error: No Title';

You could simplify it even more by doing the following:

function addLinkPost($data) {

$arguments = array('title', 'url', 'caption', 'publish', 'postdate', 'tagString');

foreach ($arguments as $value) {
    $$value = isset($data[$value]) ? $data[$value] : 'Error: No '.$value;
}

}

lukemh
  • 5,043
  • 7
  • 30
  • 38
Jonas
  • 61
  • 1
  • Just noticed that it shouldn't be 'Error: No ...' for all of the options, but still... You get the idea. – Jonas Sep 25 '09 at 12:01
0

How about:

function getdefault($value, $default = null) {
  return isset($value) ? $value : $default;
}

function addLinkPost($postDetailArray) {
  $title = getdefault($postDetailArray['title'], 'Error: No Title');
  $url = getdefault($postDetailArray['url'], 'no url');
  $caption = getdefault($postDetailArray['caption'], '');
  $publish = getdefault($postDetailArray['publish'], TRUE);
  $postdate = getdefault($postDetailArray['postdate'], 'NOW()');
  $tagString = getdefault($postDetailArray['tagString'], '');
}

or alternatively:

$defaults = array(
  'title' => 'Error: No Title',
  'url' => 'no url',
  'caption' => '',
  'publish' => TRUE,
  'postdate' => 'NOW()',
  'tagString' => '',
);

function addLinkPost($postDetailArray) {
  global $defaults;
  foreach ($defaults as $k => $v) {
    $$k = isset($postDetailArray[$k]) ? $postDetailArray[$k] : $v;
  }
}

With the one warning that if you have an array key of 'defaults' in $defaults, it will overwrite the global $defaults.

cletus
  • 616,129
  • 168
  • 910
  • 942
0

Try this:

function addLinkPost($postDetailArray) {

   foreach($array as $key=>$value){
     $$key = (isset($value) && !empty($value)) ? $value : ('no '.$key);
   }
   //all keys are available as variables 
   var_dump($url); var_dump($publish); //etc
}
Andreas
  • 5,305
  • 4
  • 41
  • 60
0

You could make all elements of the array parameters of the function. Check if the first is an array in the function and if so, extract the array.

 function addLinkPost($title = null, $url = null, $caption = null, $publish = null, $postDate = null, $tagString = null)
 {
      if(is_array($title)) {
           extract($title);
      }

      ....
 }

Maybe that makes the code a little more clear.

smack0007
  • 11,016
  • 7
  • 41
  • 48