Quentin Zervaas, author of Web 2.0 development practices, is a simple PHP Data Access Object.
- /**
- * DatabaseObject
- *
- * Abstract class used to easily manipulate data in a database table
- * Via simple load/save/delete methods
- */
- Abstract class DatabaseObject
- {
- Const TYPE_TIMESTAMP = 1;
- Const TYPE_BOOLEAN = 2;
- Protected static $ types = array (self: TYPE_TIMESTAMP, self: TYPE_BOOLEAN );
- Private $ _ id = null;
- Private $ _ properties = array ();
- Protected $ _ db = null;
- Protected $ _ table = '';
- Protected $ _ idField = '';
- Public function _ construct (Zend_Db_Adapter_Abstract $ db, $ table, $ idField)
- {
- $ This-> _ db = $ db;
- $ This-> _ table = $ table;
- $ This-> _ idField = $ idField;
- }
- Public function load ($ id, $ field = null)
- {
- If (strlen ($ field) = 0)
- $ Field = $ this-> _ idField;
- If ($ field ==$ this-> _ idField ){
- $ Id = (int) $ id;
- If ($ id <= 0)
- Return false;
- }
- $ Query = sprintf ('select % s from % s where % s =? ',
- Join (',', $ this-> getSelectFields ()),
- $ This-> _ table,
- $ Field );
- $ Query = $ this-> _ db-> quoteInto ($ query, $ id );
- Return $ this-> _ load ($ query );
- }
- Protected function getSelectFields ($ prefix = '')
- {
- $ Fields = array ($ prefix. $ this-> _ idField );
- Foreach ($ this-> _ properties as $ k => $ v)
- $ Fields [] = $ prefix. $ k;
- Return $ fields;
- }
- Protected function _ load ($ query)
- {
- $ Result = $ this-> _ db-> query ($ query );
- $ Row = $ result-> fetch ();
- If (! $ Row)
- Return false;
- $ This-> _ init ($ row );
- $ This-> postLoad ();
- Return true;
- }
- Public function _ init ($ row)
- {
- Foreach ($ this-> _ properties as $ k => $ v ){
- $ Val = $ row [$ k];
- Switch ($ v ['type']) {
- Case self: TYPE_TIMESTAMP:
- If (! Is_null ($ val ))
- $ Val = strtotime ($ val );
- Break;
- Case self: TYPE_BOOLEAN:
- $ Val = (bool) $ val;
- Break;
- }
- $ This-> _ properties [$ k] ['value'] = $ val;
- }
- $ This-> _ id = (int) $ row [$ this-> _ idField];
- }
- Public function save ($ useTransactions = true)
- {
- $ Update = $ this-> isSaved ();
- If ($ useTransactions)
- $ This-> _ db-> beginTransaction ();
- If ($ update)
- $ Commit = $ this-> preUpdate ();
- Else
- $ Commit = $ this-> preInsert ();
- If (! $ Commit ){
- If ($ useTransactions)
- $ This-> _ db-> rollback ();
- Return false;
- }
- $ Row = array ();
- Foreach ($ this-> _ properties as $ k => $ v ){
- If ($ update &&! $ V ['updated'])
- Continue;
- Switch ($ v ['type']) {
- Case self: TYPE_TIMESTAMP:
- If (! Is_null ($ v ['value']) {
- If ($ this-> _ db instanceof Zend_Db_Adapter_Pdo_Pgsql)
- $ V ['value'] = date ('Y-m-d H: I: so', $ v ['value']);
- Else
- $ V ['value'] = date ('Y-m-d H: I: S', $ v ['value']);
- }
- Break;
- Case self: TYPE_BOOLEAN:
- $ V ['value'] = (int) (bool) $ v ['value']);
- Break;
- }
- $ Row [$ k] = $ v ['value'];
- }
- If (count ($ row)> 0 ){
- // Perform insert/update
- If ($ update ){
- $ This-> _ db-> update ($ this-> _ table, $ row, sprintf ('% s = % d', $ this-> _ idField, $ this-> getId ()));
- }
- Else {
- $ This-> _ db-> insert ($ this-> _ table, $ row );
- $ This-> _ id = $ this-> _ db-> lastInsertId ($ this-> _ table, $ this-> _ idField );
- }
- }
- // Update internal id
- If ($ commit ){
- If ($ update)
- $ Commit = $ this-> postUpdate ();
- Else
- $ Commit = $ this-> postInsert ();
- }
- If ($ useTransactions ){
- If ($ commit)
- $ This-> _ db-> commit ();
- Else
- $ This-> _ db-> rollback ();
- }
- Return $ commit;
- }
- Public function delete ($ useTransactions = true)
- {
- If (! $ This-> isSaved ())
- Return false;
- If ($ useTransactions)
- $ This-> _ db-> beginTransaction ();
- $ Commit = $ this-> preDelete ();
- If ($ commit ){
- $ This-> _ db-> delete ($ this-> _ table, sprintf ('% s = % d', $ this-> _ idField, $ this-> getId ()));
- }
- Else {
- If ($ useTransactions)
- $ This-> _ db-> rollback ();
- Return false;
- }
- $ Commit = $ this-> postDelete ();
- $ This-> _ id = null;
- If ($ useTransactions ){
- If ($ commit)
- $ This-> _ db-> commit ();
- Else
- $ This-> _ db-> rollback ();
- }
- Return $ commit;
- }
- Public function isSaved ()
- {
- Return $ this-> getId ()> 0;
- }
- Public function getId ()
- {
- Return (int) $ this-> _ id;
- }
- Public function getDb ()
- {
- Return $ this-> _ db;
- }
- Public function _ set ($ name, $ value)
- {
- If (array_key_exists ($ name, $ this-> _ properties )){
- $ This-> _ properties [$ name] ['value'] = $ value;
- $ This-> _ properties [$ name] ['updated'] = true;
- Return true;
- }
- Return false;
- }
- Public function _ get ($ name)
- {
- Return array_key_exists ($ name, $ this-> _ properties )? $ This-> _ properties [$ name] ['value']: null;
- }
- Protected function add ($ field, $ default = null, $ type = null)
- {
- $ This-> _ properties [$ field] = array ('value' => $ default,
- 'Type' => in_array ($ type, self: $ types )? $ Type: null,
- 'Updated' => false );
- }
- Protected function preInsert ()
- {
- Return true;
- }
- Protected function postInsert ()
- {
- Return true;
- }
- Protected function preUpdate ()
- {
- Return true;
- }
- Protected function postUpdate ()
- {
- Return true;
- }
- Protected function preDelete ()
- {
- Return true;
- }
- Protected function postDelete ()
- {
- Return true;
- }
- Protected function postLoad ()
- {
- Return true;
- }
- Public static function BuildMultiple ($ db, $ class, $ data)
- {
- $ Ret = array ();
- If (! Class_exists ($ class ))
- Throw new Exception ('undefined class specified: '. $ class );
- $ TestObj = new $ class ($ db );
- If (! $ TestObj instanceof DatabaseObject)
- Throw new Exception ('class does not extend from databaseobject ');
- Foreach ($ data as $ row ){
- $ Obj = new $ class ($ db );
- $ Obj-> _ init ($ row );
- $ Ret [$ obj-> getId ()] = $ obj;
- }
- Return $ ret;
- }
- }
- Class DatabaseObject_User extends DatabaseObject
- {
- Static $ userTypes = array ('member' => 'member ',
- 'Admin' => 'admin ');
- Public $ profile = null;
- Public $ _ newPassword = null;
- Public function _ construct ($ db)
- {
- Parent: :__ construct ($ db, 'users', 'User _ id ');
- $ This-> add ('Username ');
- $ This-> add ('password ');
- $ This-> add ('User _ type', 'Member ');
- $ This-> add ('ts _ created ', time (), self: TYPE_TIMESTAMP );
- $ This-> add ('ts _ last_login ', null, self: TYPE_TIMESTAMP );
- $ This-> profile = new Profile_User ($ db );
- }
- Protected function preInsert ()
- {
- $ This-> _ newPassword = Text_Password: create (8 );
- $ This-> password = $ this-> _ newPassword;
- Return true;
- }
- Protected function postLoad ()
- {
- $ This-> profile-> setUserId ($ this-> getId ());
- $ This-> profile-> load ();
- }
- Protected function postInsert ()
- {
- $ This-> profile-> setUserId ($ this-> getId ());
- $ This-> profile-> save (false );
- $ This-> sendEmail ('User-register. tpl ');
- Return true;
- }
- Protected function postUpdate ()
- {
- $ This-> profile-> save (false );
- Return true;
- }
- Protected function preDelete ()
- {
- $ This-> profile-> delete ();
- Return true;
- }
- Public function sendEmail ($ tpl)
- {
- $ Templater = new Templater ();
- $ Templater-> user = $ this;
- // Fetch the e-mail body
- $ Body = $ templater-> render ('email/'. $ tpl );
- // Extract the subject from the first line
- List ($ subject, $ body) = preg_split ('/\ r | \ n/', $ body, 2 );
- // Now set up and send the e-mail
- $ Mail = new Zend_Mail ();
- // Set the to address and the user's full name in the 'to 'line
- $ Mail-> addTo ($ this-> profile-> email,
- Trim ($ this-> profile-> first_name .''.
- $ This-> profile-> last_name ));
- // Get the admin 'from 'Details from the config
- $ Mail-> setFrom (Zend_Registry: get ('config')-> email-> from-> email,
- Zend_Registry: get ('config')-> email-> from-> name );
- // Set the subject and body and send the mail
- $ Mail-> setSubject (trim ($ subject ));
- $ Mail-> setBodyText (trim ($ body ));
- $ Mail-> send ();
- }
- Public function createAuthIdentity ()
- {
- $ Identity = new stdClass;
- $ Identity-> user_id = $ this-> getId ();
- $ Identity-> username = $ this-> username;
- $ Identity-> user_type = $ this-> user_type;
- $ Identity-> first_name = $ this-> profile-> first_name;
- $ Identity-> last_name = $ this-> profile-> last_name;
- $ Identity-> email = $ this-> profile-> email;
- Return $ identity;
- }
- Public function loginSuccess ()
- {
- $ This-> ts_last_login = time ();
- Unset ($ this-> profile-> new_password );
- Unset ($ this-> profile-> new_password_ts );
- Unset ($ this-> profile-> new_password_key );
- $ This-> save ();
- $ Message = sprintf ('successful login attempt from % s user % s ',
- $ _ SERVER ['remote _ ADDR '],
- $ This-> username );
- $ Logger = Zend_Registry: get ('logger ');
- $ Logger-> notice ($ message );
- }
- Static public function LoginFailure ($ username, $ code = '')
- {
- Switch ($ code ){
- Case Zend_Auth_Result: FAILURE_IDENTITY_NOT_FOUND:
- $ Reason = 'unknown username ';
- Break;
- Case Zend_Auth_Result: FAILURE_IDENTITY_AMBIGUOUS:
- $ Reason = 'multiple users found with this username ';
- Break;
- Case Zend_Auth_Result: FAILURE_CREDENTIAL_INVALID:
- $ Reason = 'invalid password ';
- Break;
- Default:
- $ Reason = '';
- }
- $ Message = sprintf ('failed login attempt from % s user % s ',
- $ _ SERVER ['remote _ ADDR '],
- $ Username );
- If (strlen ($ reason)> 0)
- $ Message. = sprintf ('(% s)', $ reason );
- $ Logger = Zend_Registry: get ('logger ');
- $ Logger-> warn ($ message );
- }
- Public function fetchPassword ()
- {
- If (! $ This-> isSaved ())
- Return false;
- // Generate new password properties
- $ This-> _ newPassword = Text_Password: create (8 );
- $ This-> profile-> new_password = md5 ($ this-> _ newPassword );
- $ This-> profile-> new_password_ts = time ();
- $ This-> profile-> new_password_key = md5 (uniqid ().
- $ This-> getId ().
- $ This-> _ newPassword );
- // Save new password to profile and send e-mail
- $ This-> profile-> save ();
- $ This-> sendEmail ('User-fetch-password.tpl ');
- Return true;
- }
- Public function confirmNewPassword ($ key)
- {
- // Check that valid password reset data is set
- If (! Isset ($ this-> profile-> new_password)
- |! Isset ($ this-> profile-> new_password_ts)
- |! Isset ($ this-> profile-> new_password_key )){
- Return false;
- }
- // Check if the password is being confirm within a day
- If (time ()-$ this-> profile-> new_password_ts> 86400)
- Return false;
- // Check that the key is correct
- If ($ this-> profile-> new_password_key! = $ Key)
- Return false;
- // Everything is valid, now update the account to use the new password
- // Bypass the local setter as new_password is already an md5
- Parent: :__ set ('password', $ this-> profile-> new_password );
- Unset ($ this-> profile-> new_password );
- Unset ($ this-> profile-> new_password_ts );
- Unset ($ this-> profile-> new_password_key );
- // Finally, save the updated user record and the updated profile
- Return $ this-> save ();
- }
- Public function usernameExists ($ username)
- {
- $ Query = sprintf ('SELECT count (*) as num from % s where username =? ',
- $ This-> _ table );
- $ Result = $ this-> _ db-> fetchOne ($ query, $ username );
- Return $ result> 0;
- }
- Static public function IsValidUsername ($ username)
- {
- $ Validator = new Zend_Validate_Alnum ();
- Return $ validator-> isValid ($ username );
- }
- Public function _ set ($ name, $ value)
- {
- Switch ($ name ){
- Case 'password ':
- $ Value = md5 ($ value );
- Break;
- Case 'user _ type ':
- If (! Array_key_exists ($ value, self: $ userTypes ))
- $ Value = 'member ';
- Break;
- }
- Return parent ::__ set ($ name, $ value );
- }
- }
- ?>
|