我正在使用members.php
中的以下代码获取要在页面上显示的用户列表:
$users = $user->getUsers($_GET['skill'], $_GET['hometowm'], $_GET['county']);
members.php
显示所有成员members.php?skill=Foo
显示具有该技能的用户members.php?hometown=Foo
显示家乡“Foo”members.php?county=Foo
显示县(美国的AKA州)members.php?skill=Foo&hometown=Foo
显示技能和家乡用户members.php?skill=Foo&county=Foo
显示技能和县的用户以下是我想知道的:有没有办法可以缩短if
语句的数量或提高效率?我做得对吗?因为我不喜欢我有这么多参数的事实,特别是当我想要扩展时。
**User.class.php**
public function getUsers($skill = null, $hometown = null, $county = null) {
$user_table = $this->cfg['users_table']['table'];
# Search Skill
if ($skill != null && $hometown == null && $county == null) {
$sql = 'SELECT skills.Title, users_skills.SkillId, users.*
FROM users INNER JOIN (skills INNER JOIN users_skills ON skills.SkillId = users_skills.SkillId) ON users.UserId = users_skills.UserId
WHERE (((skills.Title)="' . $skill . '"))';
# Search Hometown
} else if ($hometown != null && $skill == null && $county == null) {
$sql = 'SELECT * FROM users WHERE HomeTown = "' . $hometown . '"';
# Search County
} else if ($county != null && $skill == null && $hometown == null) {
$sql = 'SELECT * FROM users WHERE county = "' . $county . '"';
# Search Skill and Hometown
} else if ($skill != null && $hometown != null && $county == null) {
//sql
# Search Skill and County
} else if($skill != null && $county != null && $hometown == null){
} else {
$sql = "SELECT * FROM " . $user_table;
}
$stmt = $this->db->prepare($sql);
$stmt->execute();
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
感谢。
答案 0 :(得分:2)
这里实际上有两个问题。首先,您的界面设计太具体了。另一个是你将数据模型与数据库访问层混合在一起,这使你的代码变得更加复杂。
为简洁起见,我在示例中略过了一些细节(代码未经测试),但我认为你可以填补空白。
第一项业务是使您的界面更加通用。不是使用一种方法来完成所有事情,而是将county
,skill
等分成不同的方法:
class userFilter
{
protected $db;
protected $params;
protected function __construct()
{
$this->db = new database_connection();
}
public static function create()
{
return new userFilter();
}
public function addCounty($county)
{
// For simplicity, 'county' is the column name
$this->params['county'][] = $county;
// Return $this to enable method chaining, used below
return $this;
}
public function addSkill($skill)
{
$this->params['skill'][] = $skill;
return $this;
}
public function addHometown($hometown)
{
return $this;
}
public function fetchUsers()
{
return '$data';
}
}
使用上面的接口,您可以选择添加任意数量的参数,每个参数(可能)都有自己的逻辑与验证输入,编写SQL条件等相关联。
此解决方案的难点在于编写实际的SQL。为此,您需要了解一些事项:
SELECT
子句)?WHERE
子句)?解决此问题的简单方法是使用数组,因为您可以轻松地foreach
包含数组,并且可以使用其key =>值配对来维护关联您的数据库架构。
现在,当您开始编写fetchUsers()
的查询时,您可以使用array_keys($this->params)
作为列名称并使用$this->params
作为数据来迭代$this->params
。这可能看起来像这样:
// Select all columns present in $this->params
$sql = 'SELECT id, '.implode(', ', array_keys($this->params));
$sql .= 'FROM table_name WHERE ';
$where = array()
foreach($this->params as $column => $ids){
$where[] = $column . ' IN ('.implode(', ', $ids).')';
}
$sql .= implode(' AND ', $where);
对于需要连接的更复杂的架构,您可能需要一个开关来处理每个连接和连接条件,或者您可能会找到一种方法将其塞入阵列。你还需要额外的逻辑来确保你不添加一个空的WHERE
条款或其他愚蠢的东西,但它的内容就在那里。
当上述代码在类中自包含时,获取数据非常简单。
$results = userFilter::create()
->addCounty($county)
->addHometown($hometown)
->addSkill($skill)
->addSkill($skill)
->addSkill($skill)
->fetchUsers();
如果您想有条件地使用某些方法:
$userFilter = userFilter::create();
if(isset($_GET['hometown'])){
$userFilter->addHometown($_GET['hometown']);
}
if(isset($_GET['skill'])){
$userFilter->addSkill($_GET['skill']);
}
$userFilter->fetchUsers();
答案 1 :(得分:1)
我经常最终得到一个像这样(大约)的结构:
$select = array("users.*"); // columns
$where = array("1=1"); // WHERE clauses
$values = array(); // values to bind
$join = array(); // additional joins
if ($skill) {
$join[] = " JOIN users_skills USING (userid) JOIN skills USING (skillid)";
$where[] = "skills.title = ?";
$values[] = $skill;
}
if ($hometown) {
$where[] = "hometown = ?";
$values[] = $hometown;
}
if ($county) {
$where[] = "county = ?";
$values[] = $county;
}
$parenthesise = function($value) { return "($value)"; };
$sql = "SELECT ".implode(",", $select)
." FROM users ".implode("", $join)
." WHERE ".implode(" AND ", array_map($parenthesise, $where));
// now prepare $sql and execute with $values
答案 2 :(得分:0)
在实际查询或存储过程中执行逻辑将为您提供RDBMS提供的优化,并且将返回更少的记录,消耗更少的资源并使您减少工作量。