Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP Good practices - Methods with too many parameters

I've made a class and method just for search things on my website. It has too many parameters, the search parameters. My controller grabs data from forms and then pass to the model.

public function search($name, $age, $foo, ... $bar, $lorem) {

Are there any tips of this kind of method? Maybe a good practice about method with too much parameters. Thanks.

EDIT:

parameters are for the search... $name should search people with value of $name $age should search people with value of $age and so on... something like the SQL Where clause.

Thanks again.

like image 343
thom Avatar asked Jul 04 '11 19:07

thom


4 Answers

Darhazer and Zanathel already gave good answers, and I just want to show you one thing: setters with fluent interface. Only when all parameters are optional.

$finder->
 setName($name)->
 setAge($age)->
 setFoo($foo)->
 setBar($bar)->
 setLorem($lorem)->
 search();

or

$query = new SearchQuery($required_argument);
$query->setAge($optional)->setLorem($optional);

$finder->search($query);

to create fluent interface, just write in setter's body return $this;

like image 85
OZ_ Avatar answered Nov 02 '22 14:11

OZ_


I like using arrays for functions that might/have many parameters. This sort of approach allows for near infinite expansion of parameters, and is more straightforward and better than using something like func_get_args().

public function search(array $options = array())
{
    $defaults = array(
        'name'   => null,
        'age'    => null,
        'order'  => null,
        'limit'  => null,
        'offset' => null,
    );
    $options = array_merge($defaults, $options);

    extract($options);

    $select = $this->select();

    if (!is_null($name)) {
        $select->where('name = ?', $name);
    }
    if (!is_null($age)) {
        $select->where('age = ?', $age, Zend_Db::INT_TYPE);
    }
    if (!is_null($order)) {
        $select->order($order);
    }
    if (!is_null($limit) || !is_null($offset)) {
        $select->limit($limit, $offset);
    }

    $results = $this->fetchAll($select);

    return $results;
}

...or you can use an object oriented approach:

class SearchQuery
{
    public function __construct(array $options = null)
    {
        if (!is_array($options)) {
            return;
        }

        if (array_key_exists('name', $options)) {
            $this->setName($options['name']);
        }
        if (array_key_exists('age', $options)) {
            $this->setAge($options['age']);
        }
    }

    public function setName($name)
    {
        if (!is_string($name)) {
            throw InvalidArgumentException('$name must be a string');
        }

        $this->_name = $name;

        return $this;
    }

    public function setAge($age)
    {
        if (!is_numeric($age) || $age <= 0) {
            throw new InvalidArgumentException('$age must be a positive integer');
        }

        $this->_age = $age;

        return $this;
    }
}

// then you can use dependency injection in your main search class

class SearchService
{
    public function search(SearchQuery $query)
    {
        // search
    }
}
like image 35
webjawns.com Avatar answered Nov 02 '22 14:11

webjawns.com


You could pack things into a key=>value based array

Example:

$params = array("Name"=>"Bob", "Age"=32.....);
Class->search($params);
public function search($params) {
    // access keys
}

This is a little bit weary because the method could be used incorrectly very easily since any array could be passed in. Some validation may be required in some other method call to verify the arrays contents.

Edit: Since there has been some debate in the comments.... here is another way to do this

Create a new class! A user class that contains name age and such and whatever other demographics. You'll probably use those in other places anyway.

Pass the object or objects in as arguments

$object = new Object();
SearchClass->search($object)

public function search(Object $object){
     // Do junk here
}
like image 34
Trevor Avatar answered Nov 02 '22 13:11

Trevor


Introduce Parameter Object

like image 21
Maxim Krizhanovsky Avatar answered Nov 02 '22 14:11

Maxim Krizhanovsky