Каковы другие конструкции классов PHP для взаимодействия объектов БД? - PullRequest
3 голосов
/ 28 апреля 2011

У меня есть таблица «Пользователь», в которой хранится информация о пользователе.Я позвоню своему классу пользователя и создам объект пользователя, чтобы я мог получить любую информацию, необходимую для этого пользователя.

Я использовал приведенные ниже классы и их гибриды для своих сайтов, но на самом деле никогда не былЯ доволен ими главным образом потому, что я не уверен, как другие разработчики справляются с этой ситуацией и есть ли лучшее решение.Ниже приведены несколько методов, которые я использовал, мне интересно посмотреть, как работают другие разработчики.

Идея № 1

class User
{ 
   //public user

   public function __construct()
   {
          //get user - queries table and returns all fields in array

   }

   //get name function - references user array and returns name
   //set name function - sets new name in array 

   //commit function - commits array to db (saves changes)
}

Идея № 2

class User
    { 
       //user id

       public function __construct(user id)
       {
              //set user id

       }

       //get name function - calls db directly and returns name
       //set name function - calls db directly and sets name

       //commit function - commits array to db saves changes
    }

Идея № 1 представляется наиболее эффективной или наименьшим количеством вызовов БД, но немного большесложный и менее простой, чем идея № 2.

Мне больше нравится идея №2, но я боюсь ее масштабируемости, потому что каждая функция вызывает БД.

Мысли

Ответы [ 6 ]

2 голосов
/ 28 апреля 2011

Я бы порекомендовал вам узнать о шаблоне DataMapper . Основная идея выглядит так:

Скажем (для примера), что у вас есть структура MVC для приложения, которое работает с книгами.

  • Имеет смысл иметь модель Library, которая отвечает за предметную логику управления различными книгами.
  • Модель имеет дело с неизвестным числом Book экземпляров (много книг в библиотеке).
    Каждая книга :
    • знает все о себе (авторы, дата публикации, язык и т. Д.)
    • не имеет никакого представления о том, где оно хранится или откуда поступают данные
    • может относиться к таблице в базе данных, но содержит информацию из нескольких таблиц
  • А потом у вас есть экземпляр класса BookMapper, который :
    • модель получает в конструкторе (реализуя предопределенный интерфейс)
    • знает, как (и где) хранить Book объекты и как считывать в них данные
    • можно переключить на другой объект, если изменяется носитель данных
    • если он работает с БД, то он в конструкторе уже запросил объект БД (например, PDO)
    • имеет методы store( Book $book ) и retrieve( Book $book ) для сохранения данных книги или получения новой информации из хранилища

Вот как бы я это сделал ..

1 голос
/ 28 апреля 2011

Как насчет чего-то вроде:

class Db
{
    function __construct()
    {
        $this->engine = DB_ENGINE;
        $this->dbname = DB_NAME;
        $this->host = DB_HOST;
        $this->username = DB_USERNAME;
        $this->password = DB_PASSWORD;

        $this->connect();
    }

    function connect()
    {
        $this->db = new PDO($this->engine.':host='.$this->host.';dbname='.$this->dbname, $this->username, $this->password);
    }
}

class Table extends Db
{
    protected $from = null;

    function __construct()
    {
        parent::__construct();
    }

    function select($columns, $where, $order, $offset, $limit)
    {
    }

    function update($where, $data)
    {
    }

    function delete($where)
    {
    }

    etc...

}

class User extends Table
{
    function __construct()
    {
        parent::__construct();
        $this->from = 'blog';
    }

    function get_user()
    {
        $this->select(params);
    }

    function get_user_count()
    {
    }

    etc...
}

Таким образом, вы можете легко использовать его для получения другой информации, просто создав новый класс с его функциями для извлечения / удаления / и т.д. информации.

0 голосов
/ 28 апреля 2011

То, что вы пытаетесь заархивировать, это функционально ORM (Object-Relational-Mapper).Может быть полезно использовать один, а не делать это самостоятельно.

Если вы хотите сделать это самостоятельно, я бы пошел на ленивую загрузку.Это немного между твоими двумя идеями.В PHP это выглядит примерно так:

class User
{ 
    private $id; // depends on your application, could also be a string
    private $dirty;
    private $loaded;

    private $properties;

    public function __construct($user_id)
    {
        $this->id = $user_id;
    }

    public function __destruct()
    {
        if ($this->dirty) {
            // commit to DB
        }
    }

    public function __get($name)
    {
        if (!$loaded)
        {
            $this->loadFromDb();
        }
        // error-handling if the key does not exist is missing here!
        return $this->properties[$name];
    }

    public function __set($name, $value)
    {
        // May be required to load the data here...

        // error-handling if the key does not exist is missing here!
        $properties[$name] = $value;
        $this->dirty = true;
    }

    private function loadFromDb()
    {
        // query data from db and store it in properties
    }
}

Преимущество этого дизайна в том, что если вы создаете объекты, которые в конечном итоге вам не нужны, ничто еще не коснулось базы данных.Также обратите внимание на фиксацию, выполненную во время деконструкции.

Если вы загружаете коллекции, иногда бывает полезно, чтобы функция загружала набор строк из БД и передавала строки в качестве аргумента конструктору при создании объектов.Для этого потребуется только один запрос вместо сотен, если бы вы построили каждый объект отдельно.

В качестве дополнительного улучшения вы можете предоставить функцию User::reset(), которая отбрасывает все сделанные изменения.

0 голосов
/ 28 апреля 2011

Я думаю, что если вы собираетесь реализовать свой собственный класс User, то он должен выглядеть примерно так:

class User {
    private $UserID;
    private $Username;
    private $AvatarImg;
    // ... First Name, Last Name, ALL other user information that you store in the DB.

    function __construct( $uid ) {
        // Populate all private members from the DB for the given user id.
    }

    function update( $assocArrayOfValues ) {
        // Commit these values to the Db and Update the private members.
    }

    // All Associated get functions ( getName, getUID, getUsername etc )
    // Any other specialty functions you may want, e.g...
    function getAvatar() {
        return "<img src = '" . $this->AvatarImg . "'/>";
    }

}
0 голосов
/ 28 апреля 2011

Во-первых, пользовательский объект предназначен для хранения пользовательских данных, поэтому я бы предложил метод № 1, метод № 2 - это скорее объект-амодель, который отправляет команды для извлечения данных.

Теперь вы можете автоматически сопоставлятьпользовательские строки для объекта в одном запросе, например:

class User
{
    //Predefine Here
    public $id;
    public $username;
    public $password;
    public $email;
    public $hash;

    public function profileLink()
    {
         return sprintf('<a href="/profile/%s">%s</a>',$this->id,$this->username);
    }
}

//Fetch the results

$result = $sth->fetchAll(PDO::FETCH_CLASS, "User");
$userObjects = array();
foreach($result as $user)
{
    $userObjects[] = $user;
}

//Now you can use like so:

echo $userObjects[2]->profileLink();

, поэтому мой другой ответ здесь: PDO PHP Fetch Class

0 голосов
/ 28 апреля 2011

Я бы предложил вам использовать PHP-Framework, такой как Yii.

http://www.yiiframework.com/

Он имеет приятные возможности для взаимодействия между классами и вашей базой данных. Вы также можете получить вдохновение, если действительно хотите сделать это самостоятельно.

...