Reputation: 13371
I've got a class called Admin
, and it has exactly the same fields as those in my admins
table in the database: id
, email
, pwhash
, pwnonce
, name
, permissions
.
My class looks like this (simplified down):
class Admin {
var $id, $email, $pwhash, $pwnonce, $name, $permissions;
function auth() {
// checks the session and attempts to authenticate the user
}
function login($email,$pw) {
// authenticate the user and start a session for them.
}
}
The problem is, I want to use PDO to fetch an object using the current class, and assign it to the current object.
Before, I was fetching an assoc array and assigning all the variables one-by-one, but now, since I'm changing my system to use PDO, I want to get it to return an instance of the Admin
class, which I assign to the current one.
For example, in the auth()
method, it should be something like this:
function auth() {
if (!isset($_SESSION['id'])) return false;
$id = $_SESSION['id'];
// create PDO connection and assign to $dbh
$sth = $dbh->prepare('SELECT * FROM admins WHERE id = ?');
$sth->execute(array($id));
$sth->setFetchMode(PDO::FETCH_CLASS,get_class($this));
$obj = $sth->fetch();
if (!is_object($obj)) return false;
$this = $obj; // I know this won't work, but anyway...
}
So I tried that, and as I had suspected, it won't let me assign the value of $this
. However, I still want to use the object mapping functionality of PDO, so how can I assign the object returned from PDO to the instance I'm in?
Upvotes: 1
Views: 786
Reputation: 31621
If you want to fetch a new object of a given class, you use PDO::FETCH_CLASS
. If however you want to write property values to an existing object that you already have, you use PDO::FETCH_INTO
, like so:
$sth->setFetchMode(PDO::FETCH_INTO, $this);
$sth->execute();
$sth->fetch();
Note that the properties you want to write to must be publicly-accessible, either directly or through a __set()
magic method.
However, you should carefully consider @Truth's answer. It is not good design to have the same class (much less the same object!) be responsible both for database access and for representing a record. Have one class responsible for managing authorization records, and another one for the records themselves.
Upvotes: 5
Reputation: 174957
Rather then trying to override $this
, return the object in question:
return $obj;
Then use it like so:
$admin = $admin->auth();
Which would override the current admin object.
Though a better approach would be to assign the variables to the current object, or to use an abstraction class, it would make more sense.
Try to say what you're doing out loud. You're telling an Admin
to auth()
, and then replace itself with a new Admin
that's authenticated. Rather, you should have an AdminManager
process the authentication request, and return an Admin
object, or, have the Admin
itself authenticate, and then fill in the details in that same object.
Other than making sense, you're also preventing duplicates and memory leaks in your application.
Upvotes: 1
Reputation: 30414
You could use overloading to redirect every call to your database object.
class Admin {
function auth() {
// [...]
$this->pdo_obj = $obj;
}
function __get($attribute) {
return $this->pdo_obj->$attribute;
}
// Implement __set, __isset, ... here
}
Upvotes: 0
Reputation: 10965
The variable you named $obj is being assigned an associative array, which is what fetch() returns. Each element in that array has a key that is the table's column name and a value that is the value for that row and column. Since you have instance variables in your class that correspond to the same, you can just set them with:
$this->id = $obj['id'];
$this->email = $obj['email'];
...etc for each one.
Upvotes: -4