views:

316

answers:

6

I program in PHP mostrly and Ruby sometimes I happen to be in need of a way to implements those "hash arguments" into my PHP funcions (Like, say, an HTML select helper)

draw_select :name => :id, :onclick => 'alert(this.value)'

The problem in PHP is that I would have to define an argument order to implement many possible attributes.

I have been thinking of just define 1 string argument and use json_decode() so i can pass arguments like this:

draw_select("'name': 'id', 'onclick': 'alert(this.value)' ")

the definition would be as follows:

function draw_select($string) {
// use json_decode here and pass them as variables
}

Do you know a smarter way to do this.. or you think that triying to to this in PHP does actually makes any sense at all?

Edited to add: I'm looking for a 'alternative' alternative to just pass a signle array as an argument like function(array(...))

+3  A: 

PHP definitely is lacking some sugar in this aspect. I do a lot of Python also and I dearly miss named arguments when using PHP. With PHP, however, whenever I have a function that will need to accept a multitude of options I simply accept one or two required/important arguments, and an array for the rest:

function draw_select($name, $options = array(), $html_options = array()) {

}

This is the way libraries like CodeIgniter and CakePHP handle the same <select> scenario.

Personally, using JSON in this situation brings no real benefit when PHP's associative arrays are so powerful. Just stick to what the language gives you, and this is the way to do it with PHP.

Paolo Bergantino
+5  A: 

Why not pass an array instead?

draw_select(array(
  'name'=> 'id', 
  'onclick'=> 'alert(this.value)'
));
Frank Farmer
i thougt about this but is not as elegant as in Ruby,
Guillermo
It's more elegant than passing a string in and JSON decoding it :)
Frank Farmer
This approach of passing an array is exactly what your desired Ruby method is doing, if you look at the implementation of draw_select it probably is something like : "def draw_select(opts = {})", so it just takes a hash. The PHP equivalent of passing an array is just that! - its the equivalent! I dont see how you can get any more equivalent than that.
Cody Caughlan
As a followup, because Ruby allows you to skip syntax characters like the opening parenthesis and curly brace, it almost appears as if the arguments are positional, but they're really not. Its all just a Hash
Cody Caughlan
A: 

Since all the options here involve calling array, and it seems to be the "PHPish" way of doing things, I'll throw in that if you're doing this all the time that maybe it makes sense to have a function z() (I'm just thinking along the lines of $() in jQuery) that aliases to array(). Besides the length of the name array, I don't see how the Ruby version is any more elegant. There are less characters, but I somewhat dislike that you can't immediately tell the difference between a function parameter and a key/value pair in that example code.

Oliver N.
A: 

A solution is to use variable arguments.

I sometimes use this with languages that don't support associative arrays natively.

function AssociativeArrayFromFlatArray($args)
{
    $nbArgs = count($args);
    if( $nbArgs % 2 != 0 )
    {
     die('This function must have an even number of arguments');
    }

    $ret = array();
    for( $i = 0; $i < $nbArgs; $i += 2 )
    {
     $key = $args[$i];
     $value = $args[$i + 1];
     $ret[$key] = $value;
    }
    return $ret;
}

function DoSomething(/*...*/)
{
    $args = AssociativeArrayFromFlatArray(func_get_args());

    if( $args['action'] == 'greet' )
    {
     $count = $args['count'] or 1;
     for( $i = 0; $i < $count; $i += 1 )
     {
      echo $args['text'];
     }
    }
}

DoSomething('action', 'greet', 'count', 10, 'text', 'Hello World! ');

Though this is a shame to use this for PHP since it natively supports associative arrays...

Vincent Robert
+1  A: 

There's no1 way to do this in any version of PHP up to and including PHP 5.3.

PHP doesn't have support for named parameters and/or smalltalk/objective-c/ruby style selectors. PHP doesn't offer a way to redefine this part of the language either. If you want this in PHP you're out of luck. PHP has never been the best language choice for so-called "meta-programming".

As others have mentioned, your best bet with PHP is to use an array with key/value pairs in combination with extract.

myFunction(array(
    'theThing'=>0,
    'param2'=>'another value',
));

function myFunction($params){
    extract($params);
    echo $param2;
}
  1. You could probably write an extension on C/C++ to extend PHP with this ability, but you'd be a masochist. :)
Alan Storm
+1 for mentioning extract() ... which tends to get overlooked
dreftymac
A: 

You could use the 'func_get_args()' function and just use every first parameter as a var name and every second as the value. It's probably as close as your going to get to the ruby way (I've been looking for ages on a way to do it, I understand exactly what you mean about ruby's elegant solution to arrays). Hopefully in the future PHP opens it's self up to be reprogrammed on execution like ruby can be(don't know what that's actually called, but it is what makes ruby and ruby on rails so brilliant).