PHP良好实践-参数太多的方法

时间:2022-11-28 16:36:46

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.

参数用于搜索…$name应该搜索值为$name的人$age应该搜索值为$age的人等等。比如SQL Where子句。

Thanks again.

再次感谢。

6 个解决方案

#1


10  

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.

Darhazer和Zanathel已经给出了很好的答案,我只想向你们展示一件事:界面流畅的定居者。只有当所有参数都是可选的。

$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;

要创建流畅的界面,只需在setter的正文中写上$this;

#2


4  

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().

我喜欢对可能有很多参数的函数使用数组。这种方法允许几乎无限扩展参数,并且比使用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
    }
}

#3


2  

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

您可以将东西打包到一个key=>值的数组中。

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
}

#4


2  

I'd use the closest simile to value objects, where you pass one object that contains all the necessary parameters as properties to the function.

我将使用最接近的比喻来值对象,在其中传递一个包含所有必要参数的对象作为函数的属性。

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

class SomeCollection {
    public function FilterResults(FilterVO $prefs) {
        // got all the goodies in here
    }
}
?>

#5


1  

make it so that it accepts an array as parameter with many name-value pairs. Then you can use extract($paramsArray) to make all names in array as $variables.

使它能接受一个具有许多名称-值对的数组作为参数。然后可以使用extract($paramsArray)将数组中的所有名称作为$变量。

#6


1  

Introduce Parameter Object

引入参数对象

#1


10  

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.

Darhazer和Zanathel已经给出了很好的答案,我只想向你们展示一件事:界面流畅的定居者。只有当所有参数都是可选的。

$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;

要创建流畅的界面,只需在setter的正文中写上$this;

#2


4  

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().

我喜欢对可能有很多参数的函数使用数组。这种方法允许几乎无限扩展参数,并且比使用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
    }
}

#3


2  

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

您可以将东西打包到一个key=>值的数组中。

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
}

#4


2  

I'd use the closest simile to value objects, where you pass one object that contains all the necessary parameters as properties to the function.

我将使用最接近的比喻来值对象,在其中传递一个包含所有必要参数的对象作为函数的属性。

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

class SomeCollection {
    public function FilterResults(FilterVO $prefs) {
        // got all the goodies in here
    }
}
?>

#5


1  

make it so that it accepts an array as parameter with many name-value pairs. Then you can use extract($paramsArray) to make all names in array as $variables.

使它能接受一个具有许多名称-值对的数组作为参数。然后可以使用extract($paramsArray)将数组中的所有名称作为$变量。

#6


1  

Introduce Parameter Object

引入参数对象