Home > Backend Development > PHP Tutorial > 设计模式 - php中如何解决函数参数列表过长问题

设计模式 - php中如何解决函数参数列表过长问题

WBOY
Release: 2016-06-06 20:51:20
Original
1445 people have browsed it

想写个灵活拼接sql语句的函数,把select,from,where,group by,order by,limit这些都作为参数传递。但是如果每一个都作为独立的参数传递,调用函数的时候,就会受到参数顺序的限制,简单的sql也可能写好几个无用空参数。如果要是通过构造一个对象来传递所有参数,参数列表短了,也不受顺序限制了,但是每次调用函数前又都要构造对象,也挺麻烦,感觉用起来不自然。有什么好的方法解决吗?

回复内容:

想写个灵活拼接sql语句的函数,把select,from,where,group by,order by,limit这些都作为参数传递。但是如果每一个都作为独立的参数传递,调用函数的时候,就会受到参数顺序的限制,简单的sql也可能写好几个无用空参数。如果要是通过构造一个对象来传递所有参数,参数列表短了,也不受顺序限制了,但是每次调用函数前又都要构造对象,也挺麻烦,感觉用起来不自然。有什么好的方法解决吗?

过长的函数拼接可读性差,也就是说,代码没有表达性

给楼主一个DSL的传送门,很可以没有对应中文版 http://en.wikipedia.org/wiki/Domain-s...

如果你不喜欢面对对象的语法:

query().from("user")
    .where(
      (user.firstName.like("Bob")).or(user.firstName.like("Ann")))
    .orderBy(user.firstName.asc())
    .list(user);
Copy after login

面向对象语法:

InsertSQL sql = new InsertSQL();
sql.insertInto("students")
   .value("id", new Integer(id))
   .value("name", name)
   .value("gender", gender);
Copy after login

-----------------------------------
最后赠送你一个我以前用过的DSL

/**
 * 配置路由规则
 */
RouteBuilder builder = new RouteBuilder() {
    public void configure() {
        from("/user").filter(header("language").isEqualTo("zh")).to("/zh/user");
        from("/user/edit/3").choice()
            .when(header("foo").isEqualTo("bar")).to("queue:d")
            .when(header("foo").isEqualTo("cheese")).to("queue:e")
            .otherwise().to("queue:f");
    }
};
Copy after login

具有表达性的代码是:做什么,而不是怎么做

有时候,我会做一个类似这样的封装,提供给楼主参考……

//伪代码
class Sql {
  protected $fields, $table, $where;
  function __construct($table) {
    $this->table = $table; 
  }
  function select($fields){
    $this->fields = $fields;
    return $this;
  }
  function where($where) {
    $this->where = $where;
    return $this;
  }
  function __toString(){
    return "select {$this->fields} from {$this->table} where {$this->where}";
  }
  static function from($table) {
    return new self($table);
  }
}

//用法
echo Sql::from('table')->select('*')->where('1=1');
//输出: select * from table where 1=1;
Copy after login

当然,实际用到的封装会比这个复杂一些……

不知道有多少人做过这种"灵活"拼SQL的东西,我想他们最后都会发现,SQL太灵活,语言太死板,拼来拼去也不会让人满意。

一个可行的实践是将SQL语句集中起来。实际上每次去找数据库的SQL语句中变量并不多,完全可以事先写好SQL语句,分配个id,简单包装一下,在调用的时候给出参数。

这样做的好处至少有这两个:
1. 可以保证sql语句经过测试,用上了该用的索引
2. 参数化查询可以避免SQL注入攻击

我个人比较喜欢把这些可变的参数用一个数组($options)传入...然后在函数内部判断传入了这个参数没...不知道我是不是答非所问...

  1. 针对SQL而言,建议直接拼SQL或找个框架吧,比如Yii框架的就支持下面这样的写法:(是不是简单多了呢?)
<code>$rows = (new \yii\db\Query())
    ->select(['id', 'email'])
    ->from('user')
    ->where(['last_name' => 'Smith'])
    ->limit(10)
    ->all();
</code>
Copy after login
  1. 针对问题标题本身——“php中如何解决函数参数列表过长问题”——PHP有个很强大的array,可以用它来传参数呀(变相的命名参数):
<code>function foo($params){
    $params = array_merge(array(
            'select' => 'default selector',
            'where' => 'default where',
            // ...
       ), $params);

    // do something with $params...

}
</code>
Copy after login
Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template