使用PHP类时的SQL查询效率

时间:2013-10-14 10:50:13

标签: php mysql sql class oop

我已经用PHP编程了很多年,但是最近才开始用类编程。我有以下 - 基本 - 用户类如下:

<?php
/* The class for constructing any user's information
 */

    class User {

        protected $userId, $email, $userGroup;

        protected function getEmail() {
            return $this->email;
        }

        protected function getUserId() {
            return $this->userId;
        }

        protected function getUserGroup() {
            return $this->userId;
        }


        public function __construct($userId='') {
            if($userId) {
                $select = mysql_query("SELECT userId, email, user_group FROM user WHERE userId = '$userId'");
                while($user==mysql_fetch_array($select)) {
                $this->email = $user[email];
                    $this->userId = $userId;
                    $this->userGroup = $user[user_group];
                }
            }
        }

}?>

所以我明白我可以做以下事情

<?php
$user = new User($userId);
echo $user->getEmail();
?>

显示给定userId的用户电子邮件地址。我想知道的是,使用OOP的最佳方式是显示40个用户的电子邮件。显然,创建40个用户对象将是愚蠢的,因为这是40个SQL查询。在给定各种参数的SQL之后,您是否只需创建一个用于返回多个用户数组的“用户”类?

<?php
$getUsers = new Users('Tom');
// create 'Users' object where name is 'Tom'
print_r($users);
// prints the returned array of users?
?>

感谢您的帮助。希望这很清楚。

3 个答案:

答案 0 :(得分:6)

我会这样做(使用另一个类):

class UserRepository {
    public function getByName($name) {
        $result = mysql_query("SELECT userId, email, user_group FROM user WHERE name = '$name'");

        $users = [];

        while ($row = mysql_fetch_assoc($result)) {
            $user = new User;
            $user->email     = $row['email'];
            $user->userId    = $row['userId'];
            $user->userGroup = $row['user_group'];

            $users[] = $user;
        }

        return $users;
    }
}

<强>增加: 以下示例提供了一个很好的想法,了解如何使类更易于测试,并且在将来需要时可以轻松修改:

UserRepositoryInterface

interface UserRepositoryInterface {
    public function getByName($name);
    public function getByUserId($id);
}

MySqliUserRepository

class MySqliUserRepository implements UserRepositoryInterface {
    public function getByName($name) {
        // Get by name using mysqli methods here
    }

    public function getByUserId($id) {
        // Get by user id using mysqli methods here
    }
}

PDOUserRepository

class PDOUserRepository implements UserRepositoryInterface {
    public function getByName($name) {
        // Get by name using PDO methods here
    }

    public function getByUserId($id) {
        // Get by user id using PDO methods here
    }
}

<强>用法

class Foo {

    protected $userRepository;

    public function __construct(UserRepositoryInterface $userRepository) {
        $this->userRepository = $userRepository;
    }

    public function bar() {
        $user = $this->userRepository->getByUserId(10);
    }
}

关于mysql_

的使用

这可能不是你怎么做的,但它会给你一个想法。此外,mysql_已弃用,因此最好使用mysqli_PDO(我个人推荐)。 PDO对OOP更加友好。

PDOhttp://php.net/manual/en/book.pdo.php

mysqli_http://php.net/manual/en/book.mysqli.php

<强>更新

您的个人用户类只包含与用户相关的信息。用户类不应包含任何检索用户的方法,即存储库的工作。因此,如果您想要检索1个用户,而不是像目前那样在User __construct中进行操作,请向UserRepository添加一个类似于此的方法:

public function getByUserId($id) {
    // Select user from db, check only 1 exists, make user object, return.
}

答案 1 :(得分:1)

我尝试将数据对象与数据库内容分开。在你的情况下,我会做出以下安排:

  • User类的实例表示个人用户,无论是否在DB中。构造函数不会从DB中检索任何内容,只会填充类属性。

  • 对于不在DB中的用户(例如,新创建的用户),userId属性为NULL(不是'')。

  • 执行DB填充的方法需要数据库接口(或至少一个对象)作为参数:

    public function save(PDO $pdo){
    }
    
  • 有一些静态方法从DB中获取东西,其中类实例还没有意义;他们返回User个实例或User个集合:

    public static function fetchById(PDO $pdo, $id){
    }
    
    public static function fetchAll(PDO $pdo){
    }
    
  • 如果有意义,我会编写一个私有方法来共享公共代码:

    private static function fetch(PDO $pdo, array $filter=array()){
        $sql = 'SELECT id, email, group
             FROM user' . PHP_EOL;
        $params = array();
    
       if( isset($filter['id']) ){
           $sql .= 'WHERE id=:id';
           $params['id'] = $filter['id'];
       }
    
       //...
    }
    
    public static function fetchById(PDO $pdo, $id){
        $data = self::fetch($pdo, array('id' => $id));
        if( empty($data) ){
            return NULL;
        }else{
            reset($data);
            return curren($data);
        }
    }
    
    public static function fetchAll(PDO $pdo){
        return self::fetch($pdo);
    }
    
  • 我提到过的 User集合可以像User个实例一样简单,也可以像你自己的泛型实现一样精心设计。

这样,典型的脚本如下所示:

// Fetch my details
$me = User::fetchById(1);

// Create a new user
$you = new User(NULL, 'Joe', 'Guests');
$you->save($pdo);
$message = sprintf('User created with ID=%d', $you->userId);

答案 2 :(得分:0)

您可以使用方法来插入/检索用户,而不是使用构造来检索用户。

您可以创建插入新用户,更新特定用户,检索特定用户或检索用户对象数组中所有用户(有条件)等的方法