我是PHP面向对象编程的新手,所以想知道我是否可以对我创建的数据库对象有一些好的建议。
我调用类 db 并将我的类包含到每个页面加载中并启动数据库对象using $db = new db
。然后我根据我想要做的事情,为我可能需要的每个动作调用方法(从数据库构建菜单,获取登录信息等),具有不同的参数。
它的第一个参数作为查询? symbol作为我要绑定的值的替换,第二个参数是在数组中绑定到它的值,然后在prepared_statement方法内循环,第三个参数是类型(FETCH_ARRAY返回SELECT语句行的数组, NUM_ROWS返回受影响的行数,INSERT返回最后插入的ID。)
我将如何调用此函数的示例如下:
$db->prepared_execute( "SELECT * FROM whatever WHERE ? = ? ", array( 'password', 'letmein' ), NUM_ROWS );
如果没有要绑定的参数或者不需要返回,则第二个和第三个参数是可选的。
由于我是OOP的新手,我发现很难确切地知道何时正确使用以及什么是公共,私有,静态函数/变量和设计模式(Singleton等)。
我已经阅读了很多教程,但是我觉得现在我需要把它带到这里以获得有关OOP和我已经建立的这个课程的下一步的进一步答案或建议。
它对我来说是一个很好的起点,除了我将在下一步添加的任何错误处理,但我想确保我没有在这里做任何明显的设计错误。
该课程的代码如下:
class db {
var $pdo;
public function __construct() {
$this->pdo = new PDO('mysql:dbname=' . DB_NAME . ';host=' . DB_HOST . ';charset=utf8', DB_USER, DB_PASS);
$this->pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
public function prepared_execute( $query, $bind_values = null, $type = null ) {
$preparedStatement = $this->pdo->prepare( $query );
if( $bind_values ) {
$i = 1;
foreach( $bind_values as $bind_value ) {
$preparedStatement->bindValue($i, $bind_value);
$i++;
} }
$preparedStatement->execute();
if( $type == FETCH_ARRAY ) { return $preparedStatement->fetchAll(); }
elseif( $type == NUM_ROWS ) { return $preparedStatement->rowCount(); }
elseif( $type == INSERT ) { return $this->pdo->lastInsertId(); }
else{ return true; }
}
答案 0 :(得分:1)
您的代码有点过时了。您应该使用visibility keywords之一而不是var
来声明您的属性。在这种情况下,您可能希望使用protected
,以便它不能从类外部进行修改,但是以后任何子类都可以在内部修改它。您可能还想添加一个getter,以便您需要直接使用PDO(您将 - 在我的类示例下面看到我的最终陈述)。
在类中对您的PDO连接信息进行硬编码很难。您应该将这些参数作为与直接使用PDO时相同的参数传递。我还要添加传递预先配置的PDO实例的功能。
虽然不是必需的,但最好遵守PSR-0 through PSR-2;最后在你的情况下我说的是类和方法命名,它们都应该是camelCase,并且该类的第一个字符应该是大写。与此相关的是你的代码格式也很丑陋,特别是你的块语句...如果那就是复制和粘贴的问题,那么就忽略那个评论。
总的来说,我会重构你的代码看起来像这样:
class Db {
protected $pdo;
public function __construct($dsn, $user, $pass, $options = array()) {
if($dsn instanceof PDO) {
// support passing in a PDO instance directly
$this->pdo = $dsn;
} else {
if(is_array($dsn)) {
// array format
if(!empty($options)) {
$dsn['options'] = $options;
}
$dsn = $this->buildDsn($options);
} else {
// string DSN but we need to append connection string options
if(!empty($options)) {
$dsn = $this->buildDsn(array('dsn' => $dsn, 'options' => $options));
}
}
// otherwise just use the string dsn
// ans create PDO
$this->pdo = new PDO($dsn, $user, $pass);
}
// set PDO attributes
$this->pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
public function getConnection()
{
return $this->pdo;
}
protected function buildDsn($options) {
if($isDbParts = isset($options['dbname'], $options['hostname']) || !($isDsn = isset($option['dsn']))) {
throw new Exception('A dsn OR dbname and hostname are required');
}
if($isDsn === true) {
$dsn = $options['dsn'];
} else if {
$format = '%s:dbname=%s;host=%s';
$driver = isset($options['dbtype']) ? $options['dbtype'] : 'mysql';
$dsn = sprintf($format, $options['dbtype'], $options['dbname'], $options['host']);
}
if(isset($options['options'])) {
$opts = array();
foreach($options['options'] as $name => $value) {
$opts[] = $name . '=' . $value;
}
if(!empty($opts)) {
$dsn .= ';' . implode(';', $opts);
}
}
return $dsn;
}
public function preparedExecute( $query, $bind_values = null, $type = null ) {
$preparedStatement = $this->pdo->prepare( $query );
if( $bind_values ) {
$i = 1;
foreach( $bind_values as $bind_value ) {
$preparedStatement->bindValue($i, $bind_value);
$i++;
}
}
$preparedStatement->execute();
if( $type == FETCH_ARRAY ) {
return $preparedStatement->fetchAll();
}
elseif( $type == NUM_ROWS ) {
return $preparedStatement->rowCount();
}
elseif( $type == INSERT ) {
return $this->pdo->lastInsertId();
}
else {
return true;
}
}
}
最后,除非这只是出于教育目的,否则我不会这样做。有大量不同的查询具有不同的部件组件,这里不考虑这些,因此在某些时候这不会支持您需要它做什么。相反,我会使用Doctrine DBAL,Zend_Db或类似的东西,通过其API支持更高的查询复杂性。简而言之,不要重新发明轮子。
答案 1 :(得分:0)
我已经开发出类似的东西,它可以帮助你。
public function select($sql, $array = array(), $fetchMode = PDO::FETCH_ASSOC){
$stmt = $this->prepare($sql);
foreach ($array as $key => $value){
$stmt->bindValue("$key", $value);
}
$stmt->execute();
return $stmt->fetchAll();
}
public function insert($table, $data){
ksort($data);
$fieldNames = implode('`,`', array_keys($data));
$fieldValues = ':' .implode(', :', array_keys($data));
$sql = "INSERT INTO $table (`$fieldNames`) VALUES ($fieldValues)";
$stmt = $this->prepare($sql);
foreach ($data as $key => $value){
$stmt->bindValue(":$key", $value);
}
$stmt->execute();
}