Хорошие практики PHP - методы со слишком большим количеством параметров - PullRequest
6 голосов
/ 04 июля 2011

Я создал класс и метод только для поиска вещей на моем сайте. У него слишком много параметров, параметров поиска. Мой контроллер получает данные из форм и затем передает их в модель.

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

Есть ли какие-нибудь советы по поводу этого метода? Возможно, хорошая практика в отношении метода со слишком большим количеством параметров. Спасибо.

EDIT:

параметры для поиска ... $ name должен искать людей со значением $ name $ age должен искать людей со значением $ age и так далее... что-то вроде предложения SQL Where.

Еще раз спасибо.

Ответы [ 6 ]

12 голосов
/ 04 июля 2011

Darhazer и Zanathel уже дали хорошие ответы, и я просто хочу показать вам одну вещь: сеттеры с свободным интерфейсом.Только когда все параметры являются необязательными.

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

или

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

$finder->search($query);

для создания плавного интерфейса , просто напишите в теле установщика return $this;

4 голосов
/ 05 июля 2011

Мне нравится использовать массивы для функций, которые могут иметь много параметров.Такой подход допускает почти бесконечное расширение параметров и является более простым и лучшим, чем использование чего-то вроде 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;
}

... или вы можете использовать объектно-ориентированный подход:

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
    }
}
2 голосов
/ 04 июля 2011

Я бы использовал самое близкое сравнение с объектами значения , где вы передаете один объект, который содержит все необходимые параметры в качестве свойств функции.

<?php
class FilterVO {
    public $id;
    public $name;
    // etc ...
}

class SomeCollection {
    public function FilterResults(FilterVO $prefs) {
        // got all the goodies in here
    }
}
?>
2 голосов
/ 04 июля 2011

Вы можете упаковать вещи в массив => значение на основе

Пример:

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

Это немного утомительно, потому что метод можно очень легко использовать некорректно, поскольку любой массив может быть передан. Для проверки содержимого массивов может потребоваться некоторая проверка при вызове другого метода.

Редактировать: Поскольку в комментариях были споры ... вот еще один способ сделать это

Создайте новый класс! Пользовательский класс, который содержит имя возраста и тому подобное и любые другие демографические данные. В любом случае вы, вероятно, будете использовать их в других местах.

Передать объект или объекты в качестве аргументов

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

public function search(Object $object){
     // Do junk here
}
1 голос
/ 04 июля 2011
0 голосов
/ 04 июля 2011

сделать так, чтобы он принимал массив в качестве параметра со многими парами имя-значение.Затем вы можете использовать extract($paramsArray), чтобы сделать все имена в массиве переменными $.

...