I want my code to take part in all operations with de database, in order to control all the information flow.
On traditional DAO, with Value Object the class is able to manipulate the relationship User => Code => Database, in other words, with the setters, the information flow that the user sends to the database can be handled in a centralized way before the database insertion.
The problem is: the getters on traditional DAO just return what the user inserted, in a Code <= User relationship, without any relation with the data that are in the database.
Example:
<?php
class UserVO {
private $id, $user, $pwd;
public function setPwd( $pwd )
{
$this->pwd = $pwd; // there is here an interference between what the user sets in $pwd and what is setted in $this->pwd
}
... Other setters ...
public function getPwd( )
{
return $this->pwd; // here we get basically what was setted in $this->pwd, and not what was really inserted in the DB
}
... Other getters ...
}
?>
But then you ask me: Jota, everything I've ever seen with the DAO/VO pattern ended up in ".. query... WHERE pwd = $inst->getPwd()", that returns exactly what was recorded in the database (in $this->pwd), so another layer to deal with these data would be useless, you can just manipulate UserVO::getPwd(), don't need another class for that.
Well, I agree with you! But it just happens while UserVO is instantiated and the pwd setted. If anywhere else I want to get data from the DB to show to the user, I won't have control to handle the relationship Database => User, and now is the time to SDAO: it turns Database => User into Database => CODE => User. This way the coder has total control to manipulate, if he wants, not just the flow of data to set values and record in the database, but also the flow of data while he is getting values from it, in a criterious way or not.
But you, persistent and still not getting it well, ask again: Jay!! Handle data that was gotten from the database can be done in a procedural way!
So I don't even answer you in a proper way... The less procedural you do, the better your code is! Centralize it. If you want to change the criteria in the data getting process, with SDAO you just change a class' getter, and if you were doing it in a procedural way you would have to edit all places where you got data from the DB.
Finally, SDAO is here to give you total control in the flow of data between what's been shown and what is recorded, in a persistent way. Think about a situation that the user setted VAR1 for a field, in the database VAR2 was recorded and it is necessary to change it to VAR1 (or even a generic VAR3) again while it's being gotten from the DB. That's why I created SDAO.
How can I make it?
To fit a class in the SDAO pattern, two thin layers are added to the DAO side of traditional DAO/VO. One to handle with the changes in DB and another one to deal with data getting.
The name pattern is DBG (DataBase Getter) for the data getting layer and DBS (DataBase Setter) for the changes layer. But they're only parts of SDAO, that is in fact a Factory used to join these two classes (DBS and DBG) and select wich one the coder will deal with.
Example:
Let's suppose we want the user to set a password, this password will be encripted by the script, recorded encripted in the Database and, when you get this information back, change this password again to the natural condition to compare with the password inserted by the user on the login.
(P.s.: It's just an example, of course there are other ways to do it, but SDAO is one of the solutions)
First, we create a Value Object class:
<?php
class UserVO { // turns $pwd in $pwd1 (something different from $pwd) in the setters and return, in the getter, $pwd1 (still encripted)
private $id, $user, $pwd;
public function setPwd( $pwd )
{
$this->pwd = encript( $pwd ); //generic function
}
// ... Other setters ...
public function getPwd( )
{
return $this->pwd; // here it return basically what was setted for $this->pwd
}
// ... Other getters ...
}
?>
Now we create the layer that will handle the relationship User => Database, in other words, the insertions/changes/deletions.<?php
class UserDBS { // record $pwd1 defined in the getters of UserVO
// to summarize, we'll put here just the insertion method
private $user, $dealer;
public function __construct( UserVO $user )
{
$this->dealer = new Connection();
$this->user = &$user;
}
public function registry()
{
$sql = "INSERT INTO users(user, pwd) VALUES (:user, :pwd)";
$sth = $this->dealer->prepare( $sql );
$sth->bindParam(":user", $this->user->getUser(), PDO::PARAM_STR);
$sth->bindParam(":pwd", $this->user->getPwd(), PDO::PARAM_STR);
if ( $sth->execute() )
{
return true;
} else
{
throw new Exception('Generic Message');
}
}
}
?>
In this moment, we will create the layer that will manipulate the relationship Database => User, in other words, DBG layer:
<?php
class UserDBG extends UserDBS { // get data from the database / returns $pwd1 as $pwd, through the getters
// extends UserDBS just to be the 'bridge' to make UserSDAO extends UserDBG and UserDBS
// this extension is just necessary to the Factory UserSDAO use the static method UserDBG::list()
private $id, $user, $pwd, $dealer;
function __construct(UserVO $user)
{
$this->dealer = new Connection();
$this->user = $user;
}
public function getUser()
{
$id = (int) $this->user->getId();
$sth = $this->dealer->prepare("SELECT * FROM `users` WHERE id = :id");
$sth->bindParam(":id", $id, PDO::PARAM_INT);
if ( $sth->execute() )
{
$vals = $sth->fetchAll(PDO::FETCH_ASSOC);
$vals = $vals[0];
$this->id = $vals['id'];
$this->user = $vals['user'];
$this->pwd = $vals['pwd'];
return array("id" => $this->getId(), "user" => $this->getUser(), "pwd" => $this->getPwd());
} else
{
throw new Exception("Generic message.");
}
}
public static function list() // static and independent from the instance because it doesn't use anything from UserVO
{
$sql = "SELECT id FROM users";
if ( !isset( self::$dealer ) )
{
$dealer = new Connection();
}
else
{
$dealer = &self::$dealer;
}
$sth = $dealer->prepare( $sql );
if( $sth->execute() )
{
$res = array();
$vals = $sth->fetchAll(PDO::FETCH_ASSOC);
foreach( $vals as $key)
{
$vo = new UserVO();
$vo->setId( $key['id'] );
$a = new UserDBG( $vo );
$res[] = $a->getUser();
}
return $res;
}
else
{
throw new Exception( "Generic message." );
}
}
// ATTENTION!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// These getters are the big difference of SDAO, and are totally different from UserVO getters. Why?
// Because UserVO getters return the variable of the User => Database flow, giving me the freedom to handle this data,
// but UserDBG getters allow me to handle the Database => User flow, modifying, if the coder wants, the value gotten from the value returned
// In the example, I'm not modidying anything, but it's not about that. It's not about what "I WILL" or "I WON'T",
// but about "I CAN DO IF I WANT TO" and the freedom it gives you.
public function getId( )
{
return $this->id;
}
public function getUser( )
{
return $this->user;
}
public function getPwd( )
{
return decript($this->pwd); // returning VAR1 again... remember?
}
}
?>
Here, we create the UserSDAO Factory:
<?php
class UserSDAO extends UserDBG // in order to UserSDAO be allowed to use static methods like UserDBG::list() as if they were his methods
{
public static function setMode( $mode, UserVO $vo )
{
$mode = strtolower( $mode ); // case insensitive
switch ( $mode )
{
case "getter": // if wants to control the data getting flow...
return new UserDBG($vo);
break;
case "setter": // if wants to control the data setting flow...
return new UserDBS($vo);
break;
default:
throw new Exception( "Generic message." );
break;
}
}
}
// Examples of implementation:
///////////////////////////////////////////////////
//Searching an user from his id ///
///////////////////////////////////////////////////
///
$vo = new UserVO(); ///
$vo->setId(7); ///
$a = UserSDAO::setMode('getter', $vo); ///
var_dump($a->getUser()); ///
///
///////////////////////////////////////////////////
////////////////////////////////////////////////////////////
//Listing all users (and justifying the 'extends') ///
////////////////////////////////////////////////////////////
///
var_dump(UserSDAO::list()); ///
///
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Recording users: ///
////////////////////////////////////////////////////////////
$vo = new UserVO(); ///
$vo->setUser("Jota"); ///
$vo->setPwd(123); ///
$a = UserSDAO::setMode('setter', $vo); ///
$a->registry(); ///
////////////////////////////////////////////////////////////
?>
Sorry for any grammar mistakes or anything in the code. I wish people to read and give opinions, please!
And, if you liked it, USE IT!
Sincerely,
Jota Júnior
Edited by dargueta, 30 April 2011 - 06:48 PM.
Changed some spacing for readability


Sign In
Create Account

Back to top









