I am looking to create a class and retrieve the account information in private and then make a public Getters
do you have any advice to improve this code?
private $db;
private $get;
public function __construct($db = null)
{
$this->db = new Database();
}
private function get($information = 0, $userid = null)
{
if ($userid === null)
{
//if ($this->isOnline()) {
$token = $_COOKIE['session'];
$req = $this->db->query('SELECT user_id FROM cms_sessions WHERE token = :token',
array(
"token" => $token
));
$userid = $req[0]['user_id'];
//}
}
$req = $this->db->query('SELECT '. $information .' FROM users INNER JOIN users_info ON users.id = users_info.user_id WHERE users.id = :userid',
array(
"userid" => $userid
));
return (count($req) > 0) ? htmlspecialchars($req[0][$information]) : "Erreur";
}
public function getId()
{
$req = $this->db->query('SELECT user_id FROM cms_sessions WHERE token = :token',
array(
"token" => #$_COOKIE['session']
));
return (count($req) > 0) ? intval($req[0]['user_id']) : "0";
}
public function getIP()
{
return $this->get('last_ip');
}
public function getGender()
{
return $this->get('gender');
}
}
but this gives me '0' once I try to retrieve user information
Thank you for your response! cordially
If you want to follow SOLID design principles to have decoupled code, then here is another way of achieving the required results
Lets define a contract which is responsible for returning a user
interface Extractable
{
public function user($db=null, $userId=null);
}
Lets define a User extractor class to get the user from database or session and will return the user to us
class UserExtractor implements Extractable
{
public function user($db=null, $userId=null)
{
return $this->retrieve($db,$userId);
}
protected function retrieve($db, $userId)
{
$db = $db ?? new Database();
// This logic can further be extracted to its own method to get rid of
// ugly conditional
if($userid ) {
$user = $db->query('SELECT * FROM users INNER JOIN users_info ON users.id = users_info.user_id WHERE users.id = :userid',
array(
"userid" => $userid
));
} else {
// I believe you have this method defined so you can
// bring it in this class
if($this->existValue('session')) {
$user = $this->getValue('session');
}
}
return $user;
}
}
Now we can define the User class which will depend on contract and will give us the required info
class Users extends Session
{
protected $extractable;
// Ok lets work with interface and not the concrete class
public function __construct(Extractable $extractable)
{
$this->extractable = $extractable
}
public function getId()
{
return (int) $this->extractable->user['id'];
}
public function getTokenTimes()
{
return (int) $this->extractable->user['token_times'];
}
}
You can now use them as follow;
$extractedUser = new UserExtractor($db, 5); // whatever the params are
$user = new Users($extractedUser);
$user->getId();
$user->getTokenTimes();
Welcome to stackoverflow!
"Improvement" is a really subjective topic. If I understand your code correctly then I would personally decouple the logic a little bit. In your concrete case I would use a Repository which accesses the database and return a Model and which will have your public getters.
class User
{
private $attributes = [];
public function __construct(array $attributes)
{
$this->attributes = $attributes;
}
public function getId()
{
return $this->attributes['id'];
}
public function getIP()
{
return $this->attributes['last_ip'];
}
public function getGender()
{
return $this->attributes['gender'];
}
}
class UserRepository
{
private $db;
public function __construct(Database $db)
{
$this->db = $db;
}
public function getById($id)
{
$result = $this->db->query('SELECT * FROM ... WHERE userid = :userid', ['userid' => $id]);
return new User($result);
}
public function getByToken($token)
{
$result = $this->db->query('SELECT * FROM ... WHERE token = :token', ['token' => $token]);
return new User($result);
}
}
And finally you could use it like this:
$repository = new UserRepository(new Database());
if (!empty($_COOKIE['session'])) {
$user = $repository->getByToken($_COOKIE['session']);
} else if ($userid > 0) {
$user = $repository->getById($userid);
} else {
// Pseudo exit here. You should handle this accordingly.
exit('User does not exist / not logged in');
}
echo $user->getId();
echo $user->getIP();
echo $user->getGender();
I have this code (which works fine):
Class SsoRequserTable
public function fetchAll()
{
$select = new Select();
$select->from("sso_requser");
$select->join('sso_workunit', 'sso_workunit.sso_workunit_id = sso_requser.sso_workunit_id', array("unitname"), 'left');
echo $select->getSqlString();
$result = $this->tableGateway->selectWith($select);
return $result;
}
class SsoRequser
class SsoRequser{
public $sso_requser_id;
public $firstname;
public $lastname;
public $fullname;
public $sso_workunit_id;
public function exchangeArray($data){
$this->sso_requser_id = (!empty($data['sso_requser_id'])) ? $data['sso_requser_id'] : null;
$this->firstname = (!empty($data['firstname'])) ? $data['firstname'] : null;
$this->lastname = (!empty($data['lastname'])) ? $data['lastname'] : null;
$this->fullname = (!empty($data['fullname'])) ? $data['fullname'] : null;
$this->sso_workunit_id = (!empty($data['sso_workunit_id'])) ? $data['sso_workunit_id'] : null;
}
}
Module.php
public function getServiceConfig() {
return array(
'invokables' => array(
// 'Aclplugin' => 'Auth\Controller\Plugin\Aclplugin',
),
'factories' => array('SSO\Model\SsoRequserTable' => function($sm) {
$tableGateway = $sm->get('SsoRequserTableGateway');
$table = new SsoRequserTable($tableGateway);
return $table;
},
'SsoRequserTableGateway' => function ($sm) {
$dbAdapter = $sm->get('postgresql_adapter');
$resultSetPrototype = new HydratingResultSet();
$resultSetPrototype->setObjectPrototype(new SsoRequser());
return new TableGateway('sso_requser', $dbAdapter, null, $resultSetPrototype);
},
),
);
}
But I can`t get the sso_workunit columns to work. I have read the Zend Documentation and nothing effectively worked for me. I need name to have an alias "unitname".
And i got the message error "Undefined property: SSO\Model\Entity\SsoRequser::$unitname "
Whether I should add unitname in class SsoRequser ?
Anyone can help me ?
I created a standart class Loadercontent(controller) in Codeigniter.
Also in the same file a add abstract Search class and child class SearchDoctor:
When I try to get CI instance &get_instance(); at abstract constructor, I get NULL:
$this->_ci =&get_instance();
var_dump($this->_ci); // NULL
So after I can not use:
$this->_ci->load->view($this->view, $this->item);
because $this->_ci is empty. What is wrong in my code ot abstract class in CI? Also maybe you can ask something about code? Is it wrong?
The full code:
<?php
abstract class Search
{
protected $fields = array('country' => 'country', 'city' => 'city');
protected $table;
protected $limit = 20;
protected $offset = 0;
protected $items;
protected $rand = false;
protected $data;
protected $view;
protected $_ci;
public function __construct($input)
{
$this->_ci =&get_instance();
$this->data = $input;
$this->getPostGet();
}
public function getPostGet(){
if(empty($this->data)){
foreach($this->data as $key => $val){
$this->_check($val, $key);
}
}
}
public function _check($val, $key){
if(in_array($val, $this->fields)){
$this->items[] = $this->getField($val, $key);
}
}
public function getField($value, $key){
return $key. ' = '.$value;
}
public function doQuery(){
if(!empty($this->items)){
$limit = $this->formatLimit();
$this->items = $this->other_model->getItemsTable($this->query, $this->table, $limit);
}
}
public function formatLimit(){
$this->offset = (isset($this->data['limit'])) ? $this->data['limit'] : $this->offset;
$this->limit = (isset($this->data['limit'])) ? $this->offset + $this->limit : $this->limit;
return array('offset' => $this->limit, 'limit' => $this->limit);
}
public function addFields($array){
$this->fields = array_merge($this->fields, $array);
}
public function getView(){
$this->_ci->load->view($this->view, $this->item);
}
public function response(){
echo json_encode($this->view); die();
}
}
class SearchDoctor extends Search
{
protected $fields = array('name' => 'DetailToUsersName');
public function __construct($type)
{
$this->table = 'users';
$this->view = 'users/doctors_list';
$this->limit = 10;
$this->rand = true;
$this->addFields($this->fields);
parent::__construct($type);
}
}
/* Init class */
class Loadercontent {
public function index(){
if(isset($_GET) || isset($_POST)){
$class = 'Search';
if(isset($_POST['type'])){
$type = $_POST['type'];
$input = $_POST;
}
if(isset($_GET['type'])){
$type = $_GET['type'];
$input = $_GET;
}
$class = $class.$type;
if (class_exists($class)) {
$obj = new $class($input);
$obj->getView();
$obj->response();
}
}
}
}
?>
I just can't figure it out.. but i got a feeling the problem is around there when im throwing the exception messages. I got almost the same code in my registration class. There is just give the errors array the messages normaly like $this->errors[] = "some error".
<?php
class class_login
{
private $id;
private $username;
private $password;
private $passmd5;
private $errors;
private $access;
private $login;
private $ltoken;
public function __cunstruct()
{
$this->errors = array();
$this->login = isset($_POST['login'])? 1:0;
$this->access = 0;
$this->ltoken = $_POST['ltoken'];
$this->id = 0;
$this->username = ($this->login)? $this->filter($_POST['lusername']) : $_SESSION['username'];
$this->password = ($this->login)? $this->filter($_POST['lpassword']) : '';
$this->passmd5 = ($this->login)? md5($this->password) : $_SESSION['password'];
}
public function isLoggedIn()
{
($this->login)? $this->verifyPost() : $this->verifySession();
return $this->access;
}
public function filter($var)
{
return preg_replace('/[^a-zA-Z0-9]/','',$var);
}
public function verifyPost()
{
try
{
if(!$this->tokenValid())
throw new Exception('Invalid Form Submission!');
if(!$this->isDataValid())
throw new Exception('Ivalid Form Data!');
if(!$this->verifyDatabase())
throw new Exception('Invalid Username/Password!');
$this->access = 1;
$this->registerSession();
}
catch(Exception $e)
{
$this->errors[] = $e->getMessage();
}
}
public function verifySession()
{
if($this->sessionExist() && $this->verifyDatabase())
$this->access = 1;
}
public function verifyDatabase()
{
include('db_connect.php');
$data = mysql_query("SELECT ID FROM users WHERE username = '($this->username)' AND password = '($this->passmd5)'");
if (mysql_num_rows($data))
{
list($this->id) = #array_values(mysql_fetch_assoc($data));
return true;
}
else
return false;
}
public function isDataValid()
{
return (preg_match('/[^a-zA-Z0-9](5,12)$/', $this->username) && preg_match('/[^a-zA-Z0-9](5,12)$/', $this->password))? 1:0;
}
public function tokenValid()
{
return (!isset($_SESSION['ltoken']) || $this->ltoken != $_SESSION['ltoken'])? 0 : 1;
}
public function registerSession()
{
$_SESSION['ID'] = $this->id;
$_SESSION['username'] = $this->username;
$_SESSION['password'] = $this->passmd5;
}
public function sessionExist()
{
return (isset($_SESSION['username']) && isset($_SESSION['password']))? 1 : 0;
}
public function show_errors()
{
foreach($this->errors as $key=>$value)
echo $value."</br>";
}
}
?>
The constructor is called __construct, not __cunstruct.
I see you are setting $this->errors to an array in your __cunstruct function, but since it is not __construct it may never be set.
You need a associative array for
foreach($this->errors as $key=>$value)
But you have no one. ($this->errors[] = $e->getMessage();)
With out an associative array you must use:
foreach($this->errors as $value)
public function __cunstruct() <------ The error is probably here. It is __construct
{
$this->errors = array();
$this->login = isset($_POST['login'])? 1:0;
$this->access = 0;
$this->ltoken = $_POST['ltoken'];
$this->id = 0;
$this->username = ($this->login)? $this->filter($_POST['lusername']) : $_SESSION['username'];
$this->password = ($this->login)? $this->filter($_POST['lpassword']) : '';
$this->passmd5 = ($this->login)? md5($this->password) : $_SESSION['password'];
}
You have a typo.... _construct and not _construct
I am new to Zend and have been attempting to follow the Zend Quick Start Guide's example of using Data Mappers and extending Zend_Db_Table_Abstract. I think I've grasped the general concepts, but I am now wondering, how I would go about modifying the guide's example code to allow for multiple tables.
Here is the part of the code I am currently interested in modifying:
protected $_dbTable;
public function setDbTable($dbTable)
{
if (is_string($dbTable)) {
$dbTable = new $dbTable();
}
if (!$dbTable instanceof Zend_Db_Table_Abstract) {
throw new Exception('Invalid table data gateway provided');
}
$this->_dbTable = $dbTable;
return $this;
}
public function getDbTable()
{
if (null === $this->_dbTable) {
$this->setDbTable('Application_Model_DbTable_Guestbook');
}
return $this->_dbTable;
}
I have changed it to this:
protected $_dbTables;
public function setDbTable($dbTable, $tableName)
{
if (is_string($dbTable)) {
$dbTable = new $dbTable();
}
if (!$dbTable instanceof Zend_Db_Table_Abstract) {
throw new Exception('Invalid table data gateway provided');
}
$this->_dbTables[$tableName] = $dbTable;
return $this;
}
public function getDbTables()
{
if (null === $this->_dbTables) {
$this->setDbTable('Application_Model_DbTable_Courses', 'courses');
$this->setDbTable('Application_Model_DbTable_CourseTimes', 'course_times');
}
return $this->_dbTables;
}
Is this a correct way to go about implementing multiple tables within the Data Mapper pattern or would you do it differently? Thanks for your help in advance!
Assuming that you want to return data from related tables, you should either add queries with joins to one Zend_Db_Table or use Zend_Db_Table_Relationships to fetch associated data. The benefit of using Joins is that you will only do one query over many when using Relationships. The drawback is that joined tables wont return Zend_Db_Table_Row objects (iirc), but since you are going to map them onto your Domain objects anyway, it's not that much of an issue.
Structurally, you can do like I suggested in How to change Zend_Db_Table name within a Model to insert in multiple tables. Whether you create a Gateway of Gateways or simply aggregate the Table Gateways in the DataMapper directly is really up to you. Just compose them as you see fit.
I'm not sure if it's the best practice, but, this is my abstract mapper:
<?php
abstract class Zf_Model_DbTable_Mapper
{
protected $_db;
protected $_dbTable = null;
protected $_systemLogger = null;
protected $_userLogger = null;
public function __construct()
{
$this->_systemLogger = Zend_Registry::get('systemLogger');
$this->_userLogger = Zend_Registry::get('userLogger');
// Set the adapter
if(null !== $this->_dbTable)
{
$tableName = $this->_dbTable;
$this->_db = $this->$tableName->getAdapter();
}
}
public function __get($value)
{
if(isset($this->$value))
{
return $this->$value;
}
$dbTable = 'Model_DbTable_' . $value;
$mapper = 'Model_' . $value;
if(class_exists($dbTable))
{
return new $dbTable;
}
elseif(class_exists($mapper))
{
return new $mapper;
}
else
{
throw new Exception("The property, DbTable or Mapper \"$value\" doesn't exists");
}
}
public function __set($key,$value)
{
$this->$key = $value;
}
public function getById($id)
{
$resource = $this->getDefaultResource();
$id = (int)$id;
$row = $resource->fetchRow('id =' . $id);
if (!$row) {
throw new Exception("Count not find row $id");
}
return $row;
}
public function getAll()
{
$resource = $this->getDefaultResource();
return $resource->fetchAll()->toArray();
}
public function save(Zf_Model $Model)
{
$dbTable = $this->getDefaultResource();
$data = $Model->toArray();
if(false === $data) return false;
if(false === $Model->isNew())
{
if(1 == $dbTable->update($data, 'id =' . (int)$Model->getId()))
{
return $Model;
}
}
else
{
$id = $dbTable->insert($data);
if($id)
{
$Model->setId($id);
return $Model;
}
}
return false;
}
public function remove($id)
{
return $this->getDefaultResource()->delete('id =' . (int) $id);
}
protected function getDefaultResource()
{
if(empty($this->_dbTable))
{
throw new Exception('The $_dbTable property was not set.');
}
$classname = 'Model_DbTable_' . $this->_dbTable;
if(!class_exists($classname))
{
throw new Exception("The Model_DbTable_\"$classname\" class was not found.");
}
return new $classname;
}
protected function getDefaultModel()
{
return current($this->_models);
}
protected function getResources()
{
return $this->_resources;
}
}
And this is one for my implemented mappers:
<?php
class Model_TwitterPostsMapper extends Zf_Model_DbTable_Mapper
{
/*
* Data Source
* #var string Zend_Db_Table name
*/
protected $_dbTable = 'TwitterPosts';
public function recordExists($Item)
{
$row = $this->TwitterPosts->fetchRow($this->TwitterPosts->select()->where('status_id =?', $Item->getSource()->getStatusId()));
if($row)
{
return $row->id;
}
return false;
}
public function getLastUpdate($options)
{
$select = $this->TwitterPosts->select()
->setIntegrityCheck(false)
->from(array('t' => 'twt_tweets'), 't.created_at')
->join(array('u' => 'twt_users'), 't.user_id = u.id', '')
->order('t.created_at DESC');
if($options['user_id'])
{
$select->where("t.user_id = ?", $options['user_id']);
}
if($options['terms'])
{
if(is_array($options['terms']))
{
$condition = '';
foreach($options['terms'] as $i => $term)
{
$condition .= ($i > 0) ? ' OR ' : '';
$condition .= $this->getAdapter()->quoteInto('content LIKE ?',"%$term%");
}
if($condition)
{
$select->where($condition);
}
}
}
return $this->TwitterPosts->fetchRow($select)->created_at;
}
public function getSinceId($term = null)
{
$select = $this->TwitterPosts->select()->setIntegrityCheck(false)
->from('twt_tweets_content', 'status_id')
->where('MATCH(content) AGAINST(? IN BOOLEAN MODE)', "$term")
->order('status_id ASC')
->limit(1);
//echo $select; exit;
$tweet = $this->TwitterPosts->fetchRow($select);
if(null !== $tweet) return $tweet->status_id;
return 0;
}
public function getAllByStatusId($statuses_id)
{
$select = $this->TwitterPosts->select()
->setIntegrityCheck(false)
->from(array('t' => 'twt_tweets'), array('t.id', 't.user_id', 't.status_id','t.user_id'))
->join(array('u' => 'twt_users'), 't.user_id = u.id', array('u.screen_name', 'u.profile_image'))
->where('status_id IN(?)', $statuses_id);
$rows = $this->TwitterPosts->fetchAll($select);
$Posts = array();
foreach($rows as $row)
{
// Here we populate the models only with the specific method return data
$data = $row->toArray();
$Post = new Model_TwitterPost($data['id']);
$Post->populate($data);
$User = new Model_TwitterUser($data['user_id']);
$User->populate($data);
$Post->setUser($User);
$Posts[] = $Post;
}
return $Posts;
}
public function getAllSince($since_id)
{
$select = $this->TwitterPosts->select()
->setIntegrityCheck(false)
->from(array('t' => 'twt_tweets'), array('t.status_id','t.user_id'))
->join(array('u' => 'twt_users'), 't.user_id = u.id', array('u.screen_name', 'u.profile_image'))
->where('status_id > ?', $since_id)
->order('t.datetime DESC');
$rows = $this->TwitterPosts->fetchAll($select);
$Posts = array();
foreach($rows as $row)
{
// Here we populate the models only with the specific method return data
// TODO: This is not a truly lazy instatiation, since there's no way to get the not setted properties
$data = $row->toArray();
$Post = new Model_TwitterPost($data);
$User = new Model_TwitterUser($data);
$Post->setUser($User);
$Posts[] = $Post;
}
return $Posts;
}
public function getTotalRatedItems($options)
{
$options = $this->prepareOptions($options);
$select = $this->TwitterPosts->select()
->setIntegrityCheck(false)
->from(array('t' => 'twt_tweets'), array('COUNT(DISTINCT t.id) AS total','r.rate'))
->join(array('u' => 'twt_users'), 't.user_id = u.id', '')
->join(array('r' => 'twt_tweets_rate'), 't.id = r.tweet_id', array('r.rate'))
->group('r.rate')
->order('t.datetime DESC');
$select = $this->prepareSelect($select, $options);
$rates = $this->TwitterPosts->fetchAll($select)->toArray();
$itemsRated = array('Green' => 0, 'Yellow' => 0, 'Orange' => 0, 'Red' => 0, 'Gray' => 0);
foreach ($rates as $rate)
{
$itemsRated[$rate['rate']] = $rate['total'];
}
return $itemsRated;
}
public function getUsersActivity($options)
{
$options = $this->prepareOptions($options);
$select = $this->TwitterPosts->select()
->setIntegrityCheck(false)
->from(array('t' => 'twt_tweets'), array('COUNT(DISTINCT t.id) AS total','DATE(t.datetime) AS datetime'))
->join(array('u' => 'twt_users'), 't.user_id = u.id', '')
->joinLeft(array('r' => 'twt_tweets_rate'), 't.id = r.tweet_id', '')
->group('t.user_id')
->order('t.datetime DESC');
$select = $this->prepareSelect($select, $options);
$activity = $this->TwitterPosts->fetchAll($select)->toArray();
return $activity;
}
public static function prepareOptions($options)
{
if(!is_array($options))
{
$options = array();
}
date_default_timezone_set('America/Sao_Paulo');
if(Zend_Date::isDate($options['start_date']))
{
$date = new Zend_Date($options['start_date']);
$date->setTime('00:00:00');
$date->setTimezone('UTC');
$options['start_date'] = $date->toString('yyyy-MM-dd HH:mm:ss');
}
if(Zend_Date::isDate($options['end_date']))
{
$date = new Zend_Date($options['end_date']);
$date->setTime('23:59:59');
$date->setTimezone('UTC');
$options['end_date'] = $date->toString('yyyy-MM-dd HH:mm:ss');
}
date_default_timezone_set('UTC');
$options['mainTerms'] = array();
if(!empty($options['terms']) && !is_array($options['terms']))
{
$options['mainTerms'] = explode(' ', $options['terms']);
}
if(!is_array($options['terms']))
{
$options['terms'] = array();
}
if($options['group_id'] || $options['client_id'])
{
$TwitterSearches = new Model_DbTable_TwitterSearches();
$options['terms'] = array_merge($TwitterSearches->getList($options),$options['terms']);
if(empty($options['terms']))
{
$options['terms'] = array();
}
}
return $options;
}
public static function prepareSelect($select, $options)
{
if($options['start_date'])
{
$select->where('t.datetime >= ?', $options['start_date']);
}
if($options['end_date'])
{
$select->where('t.datetime <= ?', $options['end_date']);
}
foreach($options['mainTerms'] as $mainTerm)
{
$select->where('t.content LIKE ?', "%$mainTerm%");
}
if($options['user_id'])
{
$select->where("t.user_id = ?", $options['user_id']);
}
if($options['terms'])
{
$select->where('MATCH (t.content) AGASINT(?)', $options['terms']);
}
if($options['rate'])
{
if($options['rate'] == 'NotRated')
{
$select->where('r.rate IS NULL');
}
else
{
$select->where('r.rate = ?', $options['rate']);
}
}
if($options['last_update'])
{
$select->where('t.created_at > ?', $options['last_update']);
}
if($options['max_datetime'])
{
$select->where('t.created_at < ?', $options['max_datetime']);
}
return $select;
}
}
The Model:
<?php
class Model_TwitterPost extends Zf_Model
{
private $_name = 'twitter';
protected $_properties = array(
'id',
'status_id',
'user_id',
'content'
);
protected $_User = null;
public function setUser(Zf_Model $User)
{
$this->_User = $User;
}
public function getUser()
{
return $this->_User;
}
public function getPermalink()
{
return 'http://twitter.com/' . $this->screen_name . '/' . $this->status_id;
}
public function hasTerm($term)
{
if(preg_match("/\b$term\b/i", $this->getContent()))
{
return true;
}
return false;
}
public function getEntityName()
{
return $this->_name;
}
public function getUserProfileLink()
{
return $this->getUser()->getProfileLink() . '/status/' . $this->getStatusId();
}
}
Abstract model (Generic Object):
<?php
abstract class Zf_Model
{
protected $_properties = array();
protected $_modified = array();
protected $_data = array();
protected $_new = true;
protected $_loaded = false;
public function __construct($id=false)
{
$id = (int)$id;
if(!empty($id))
{
$this->_data['id'] = (int)$id;
$this->setNew(false);
}
}
public function populate($data)
{
if(is_array($data) && count($data))
{
foreach($data as $k => $v)
{
if(in_array($k,$this->_properties))
{
$this->_data[$k] = $v;
}
}
}
$this->setLoaded(true);
}
public function setNew($new=true)
{
$this->_new = (bool)$new;
}
public function isNew()
{
return $this->_new;
}
public function setLoaded($loaded = true)
{
$this->_loaded = (bool)$loaded;
}
public function isLoaded()
{
return $this->_loaded;
}
public function __call($methodName, $args) {
if(method_exists($this, $methodName))
{
return $this->$methodName($args);
}
$property = $methodName;
if (preg_match('~^(set|get)(.*)$~', $methodName, $matches))
{
$filter = new Zend_Filter_Word_CamelCaseToUnderscore();
$property = strtolower($filter->filter($matches[2]));
if(in_array($property, $this->_properties))
{
if('set' == $matches[1])
{
$this->_data[$property] = $args[0];
if(true === $this->isLoaded())
{
$this->_modified[$property] = true;
}
return $this;
}
elseif('get' == $matches[1])
{
if(array_key_exists($property, $this->_data))
{
return $this->_data[$property];
}
throw new Exception("The property $property or $methodName() method was not setted for " . get_class($this));
}
}
}
throw new Exception("The property '$property' doesn't exists.");
}
public function __get($key)
{
if(isset($this->_data[$key]))
{
return $this->_data[$key];
}
return $this->$key;
}
public function __set($key,$value)
{
if(array_key_exists($key,$this->_properties))
{
$this->_data[$key] = $value;
return;
}
$this->$key = $value;
}
public function getId()
{
return (!$this->_data['id']) ? null : $this->_data['id'];
}
public function toArray()
{
// If it's a new object
if(true === $this->isNew())
{
return $this->_data;
}
// Else, if it's existing object
$data = array();
foreach($this->_modified as $k=>$v)
{
if($v)
{
$data[$k] = $this->_data[$k];
}
}
if(count($data))
{
return $data;
}
return false;
}
public function reload()
{
$this->_modified = array();
}
}