I have a table called "User" that holds user info. I'll call my user class and create a user object so that I can grab whatever info is needed for that user.
I have been using the below classes and hybrids of them for my sites but have been never really happy with them mainly because I'm unsure how other developers handle this situation and if there is a better solution. Below are a few methods I have been using, I'm curious to see how other developers are doing.
Idea # 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)
}
Idea # 2
class User
{
//user id
public function __construct(user id)
{
开发者_Go百科 //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
}
Idea #1 seems to be the most efficient, or least amount of DB calls but a little more complex and less straightforward than Idea #2.
I like idea #2 better but I'm afraid of it's scalability because each function makes a call to the DB.
Thoughts
I would recommend for you to learn about DataMapper pattern. The basic idea goes like this :
Lets say (for the sake of example ) that you have an MVC structure for application that deals with books.
- It would make sense to have a model
Library
which is responsible with domain logic of managing different books. - The model deals with unknown number of
Book
instances ( many books in a library ).
Each book :- knows everything about itself ( authors , publishing date , language .. etc.)
- has no idea where it is stored or where the data come from
- can be related to a table in Database , but contains information from multiple tables
- And then you have an instance of
BookMapper
class, which :- model receives in the constructor ( implementing predefined interface )
- knows how to ( and where ) store the
Book
objects , and how to read data into them - can be switched to a different object, if storage medium changes
- if it works with DB, then it in constructor has already requested a DB object ( like PDO )
- has methods
store( Book $book )
andretrieve( Book $book )
for saving book's data , or getting new info from storage
This is how i would do it ..
What about something like:
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...
}
This way you can easily use it to get other info as well just be creating a new class with it's functions to retrieve / delete / etc the info.
Firstly the user object is meant to hold user data, so i would suggest method #1, method #2 is more of a amodel object that send's commands to fetch data.
Now, you can automatically map user rows to an object in 1 single query, for example:
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();
so my other answer here : PDO PHP Fetch Class
I think that if you are going to implement your own User class, then it should look something similar to the following:
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 . "'/>";
}
}
What you are trying to archive is the functionally of an ORM (Object-Relational-Mapper). It may be beneficial to use one and not do it yourself.
If you want to do it on your own, I would go for lazy-loading. This is a bit in between your two ideas. In PHP it looks something like this:
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
}
}
The advantage of this design is, that if you construct objects, which ultimately you don't need, nothing has touched the database yet. Also note the commit done during deconstruction.
If you load collections sometimes it may be useful to have a function load a bunch of rows from the DB and pass the rows as argument to a constructor when creating the objects. This would require only one query instead of possibly hundreds if you would have constructed each object by itself.
As a further enhancement you may provide a User::reset()
function, which throws away all the changes made.
I would suggest you to use a PHP-Framework like Yii.
http://www.yiiframework.com/
It has nice Features to interact between Classes and your Database. You can also get some inspiration there if you really want to do this on your own.
精彩评论