我请求社区的智慧,因为我想避免糟糕的编码实践和/或错误。我有一个 php 类,它是一个对象管理器。它完成了数据库的所有工作:插入新数据,更新它,获取它并删除它(我读过它被称为CRUD...)。所以它有一个通过id获取元素的函数。
我想写的是一个从表中获取对象列表的函数。然后,我将使用类似
SELECT * FROM mytable WHERE column1='foo'
然后是一些排序和限制/抵消。
但是,在我的应用程序中,在不同的情况下,我需要此表中的不同列表。然后,WHERE 子句将有所不同。
我应该编写不同的函数,每种类型的列表一个吗?或者我应该编写一个通用函数,我将向其发送参数,然后动态创建查询?如果是这样,您对如何正确执行此操作有什么建议吗?
编辑:感谢您的所有回答!我应该告诉我没有使用任何框架(也许不是最好的主意......),所以我不知道查询构建器。我会对此进行调查(要么找到一个独立的 uery 构建器,要么迁移到框架或编写我自己的框架,我还不知道)。每当我需要执行 mysql 查询时,这将很有用:-)
虽然我仍然很困惑:假设我需要多个客户端(对象)列表,例如所有客户端、18 岁以上的客户、当前在线的客户端......检索这些列表的最佳方法是什么?我可以在客户管理器中拥有 3 个功能
allClients() {//execute a specific query and return list of objects}
allClientsOver18() {//execute specific query and return list of objects}
allClientsOnline() {//execute specific query and return list of objects}
或者我可以让一个函数根据参数构建查询
listClients($some, $parameters)
{
//Build the query based on the parameters (definitely need a query builder!)
//Execute the query
//return list of objects
}
哪种方法最好(我想这取决于情况),大多数情况下,为什么?
提前感谢!Rouli<</p>
感谢您提供有关查询构建器的所有信息,我什至不知道它的存在! :-)但是,我仍然感到困惑,我是否应该为每种情况编写一个特定函数(该函数仍然可以使用查询构建器编写其特定查询),或者编写一个基于 f 参数动态构建查询的通用函数。在哪种情况下哪个会更好?我在问题中添加了一个例子,希望它更清楚!
这取决于您使用这些独立查询的频率、条件的复杂程度以及您需要将这些条件与其他查询组合的频率。对于 eaxample,如果每个"在线"和"超过 18 岁"只是简单的条件,那么您可以使用我示例中的正常findBy
逻辑:
$table = new MyTable($db);
$onlineOnly = $table->findBy(array('is_online' => true), null, null);
$over18Only = $table->findBy(array('is_over_18' => true), null, null);
$onlineOver18 = $table->findBy(array('is_over_18' => true, 'is_online' => true), null, null);
如果查询更复杂 - 例如,要获得超过 18 个客户端,您必须执行以下操作:
select client.*, (YEAR(CURDATE()) - YEAR(client.birthdate)) as age
FROM client
WHERE age >= 18
然后,最好将其制作成一个单独的方法或创建方法来直接处理Query
对象以添加复杂的条件 - 特别是如果您在应用程序中的几个不同查询中需要此条件:
$table = new MyTable($db);
// creates a basic query defaulted to SELECT * FROM table_name
$query = $table->createQuery();
// adds the complex condition for over 18 resulting in
// SELECT table_name.*, (YEAR(CURDATE()) - YEAR(table_name.birthdate)) as age WHERE age >= 18
$over18 = $table->applyOver18Query($query)->execute();
通过这种方式,您可以轻松地将超过 18 岁的条件应用于任何查询,而无需手动操作构建器,确保您的超过 18 岁的条件是一致的。但为了简单起见,您还可以使用如下所示的便捷方法:
public function findOver18By(array $criteria, $limit = null, $offest = null) {
$query = $this->findBy($criteria, $limit, $offset);
$this->applyOver18Query($query);
return $query->execute();
}
通常,您会在较低级别使用某种查询构建器,例如:
$query = $db->createQuery()
->select($fields)
->from($tableName)
->where($fieldName, $value);
$results = $query->execute();
然后,您可能有一个使用以下内容的类:
class MyTable
{
protected $tableName = 'my_table';
protected $db;
public function __construct($db) {
$this->db = $db;
}
public function findBy(array $criteria, $limit = null, $offset = null) {
$query = $this->db->createQuery();
$query->select('*')->from($this->tableName);
foreach ($criteria as $col => $value) {
// andWhere would determine internally whether or not
// this is the initial WHERE clause or an AND clause
// something similar would happen with an orWhere method
$query->andWhere($col, $value);
}
if (null !== $limit) {
$query->limit($limit);
}
if (null !== $offset) {
$query->offset($offset);
}
return $query->execute();
}
}
用法如下所示:
$table = new MyTable($db);
$result = $table->findBy(array('column1' => 'foo'), null, null);
这需要您自己实现很多。大多数人使用ORM或DBAL来提供这些功能,这些功能通常包含在框架中,例如Laravel的Eloquent 或Symfony的Doctrine。
一开始你应该需要一些主要数据,比如
$main = [
'from' = '`from_table`',
]
然后你应该添加选择
如果有$selects = ['fields1','field2'];
$where = ['some condition', 'other condition'];
然后你可以
$query = "SELECT ".implode(',', $selects ." FROM ".$main['from']."
WHERE ".implode('AND ', $where .";";
这是简单的单表查询的一些方法。如果您需要连接,那么最好使用别名$selects
,因此如果它们不同,则不会丢失任何字段,例如
select temp.id as temp_id , temp2.id temp2_id from temp
left join temp2 on temp2.temp_id = temp.id
随意问一些问题,也许我还没有告诉,但你也应该用一些函数检查绑定参数以避免sql注入
我建议为您的数据库使用 CLASS,它包含所有数据库访问函数,因为它使您的代码更清晰,从而更容易查看错误或修改。
class Database
{
public function connect() { }
public function disconnect() { }
public function select() { }
public function insert() { }
public function delete() { }
public function update() { }
}
用于连接到所选数据库的示例连接函数。
private db_host = ‘’;
private db_user = ‘’;
private db_pass = ‘’;
private db_name = ‘’;
public function connect()
{
if(!$this->con)
{
$myconn = mysqli_connect($this->db_host,$this->db_user,$this->db_pass);
if($myconn)
{
$seldb = mysqli_select_db($this->db_name,$myconn);
if($seldb)
{
$this->con = true;
return true;
} else
{
return false;
}
} else
{
return false;
}
} else
{
return true;
}
}
使用这种方法将使创建 CRUD 函数变得更加容易。下面是一个示例插入函数。
public function insert($table,$values,$rows = null)
{
if($this->tableExists($table))
{
$insert = 'INSERT INTO '.$table;
if($rows != null)
{
$insert .= ' ('.$rows.')';
}
for($i = 0; $i < count($values); $i++)
{
if(is_string($values[$i]))
$values[$i] = '"'.$values[$i].'"';
}
$values = implode(',',$values);
$insert .= ' VALUES ('.$values.')';
$ins = @mysql_query($insert);
if($ins)
{
return true;
}
else
{
return false;
}
}
}
这是使用它的快速视图。
;<?php;
$db->insert('myDataBase',array(3,"Name 4","this@wasinsert.ed")); //this takes 3 paramteres
$result = $db->getResult(); //Assuming you already have getResult() function.
print_r($result);
?>
编辑
有更纯粹的方法来处理数据库操作。我强烈建议这样做,因为处理信息非常微妙,应该采取许多安全措施,但它需要更深入的 php 知识。尝试 pdo for php 和 matt bango 关于准备语句及其意义的这篇文章。