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

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

WBOY
Freigeben: 2016-06-06 20:51:20
Original
1443 Leute haben es durchsucht

想写个灵活拼接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);
Nach dem Login kopieren

面向对象语法:

InsertSQL sql = new InsertSQL();
sql.insertInto("students")
   .value("id", new Integer(id))
   .value("name", name)
   .value("gender", gender);
Nach dem Login kopieren

-----------------------------------
最后赠送你一个我以前用过的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");
    }
};
Nach dem Login kopieren

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

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

//伪代码
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;
Nach dem Login kopieren

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

不知道有多少人做过这种"灵活"拼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>
Nach dem Login kopieren
  1. 针对问题标题本身——“php中如何解决函数参数列表过长问题”——PHP有个很强大的array,可以用它来传参数呀(变相的命名参数):
<code>function foo($params){
    $params = array_merge(array(
            'select' => 'default selector',
            'where' => 'default where',
            // ...
       ), $params);

    // do something with $params...

}
</code>
Nach dem Login kopieren
Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage