Ok, thank you Feyd.
Well, infact, I might found a better way to access data from database and returning them as object. I share it here.
In the above code before, I allocate each variables manually, which in fact it was the address class job. So, I fixed my Address class, by moving the logic for allocating data to private vars within the address class in ADDRESS class itself.
Code: Select all
<?php
require_once ('class.AddressFactory.php');
class Address {
private $_addressID;
private $_userID;
private $_streetAddress;
private $_state;
private $_city;
private $_postalCode;
private $_country;
private $_typeID;
private $_defaultAddress = 0; //set to false
private $_addedOn;
private $_lastUpdatedOn;
private $_addressRetrievedFromTheDatabase = array();
private $_dataFromUser = array();
private $_validated = false;
/**
* Constructor of the Address object
* @param int[optional] $addressID
*/
public function __construct ($addressID=null) {
//check the parameter of this object,
//if it's empty then set the private $this->addresssID as null
if ($addressID != null) {
//check if the parameter is a number
$pattern = '/[0-9]/';
$matches = preg_match($pattern, $addressID);
if (!$matches) {
throw new Exception('ERROR: Address ID must be numbers.');
}
$this->_addressID = $addressID;
//store the retrieved data from the database in an array
$this->_addressRetrievedFromTheDatabase = AddressFactory::getSpecificAddressData($addressID);
//allocate stored data in array to private vars
foreach ($this->_addressRetrievedFromTheDatabase as $key => $value) {
switch ($key) {
case "typeID":
$this->_typeID = $value;
break;
case "userID":
$this->_userID = $value;
break;
case "streetAddress":
$this->_streetAddress = $value;
break;
case "state":
$this->_state = $value;
break;
case "city":
$this->_city = $value;
break;
case "postalCode":
$this->_postalCode = $value;
break;
case "country":
$this->_country = $value;
break;
case "defaultAddress":
$this->_defaultAddress = $value;
break;
case "addedOn":
$this->_addedOn = $value;
break;
case "lastUpdatedOn":
$this->_lastUpdatedOn = $value;
break;
}
}
} else {
$this->_addressID = null;
}
}
?>
To retrieve the specific address data based on the addressID, I also created a AddressFactory class, which looks like this:
Code: Select all
<?php
require_once('class.MySQLConnection.php');
/**
* AddressFactory class doesn't need any constructor, because in here, all the methods are declared as static methods, mean that
* you can use it without instantiating the AddressFactory first.
*/
class AddressFactory {
/**
* Method to get specific address data by specifiying its ID
* @name getSpecificAddressData
* @param int $addressID
* @return Array
*/
public static function getSpecificAddressData ($addressID) {
$query = "SELECT * FROM tbladdress WHERE addressID = $addressID";
$result = mysqli_query(MySQLConnection::connectToMySQL(), $query);
if (! ($result && mysqli_num_rows($result))) {
die ("Failed getting the address data for address: $addressID");
}
return mysqli_fetch_assoc($result);
}
}
?>
Now, in UserFactory, we can cut the code down right at the method that retrieves all the addressData for a specific user:
Code: Select all
<?php
require_once ('class.MySQLConnection.php');
class UserFactory {
/**
* Method that retrieve all addresses that a user has
* @name getAddressesForUser
* @param int $userID
* @return Array
*/
public static function getAddressesForUser($userID) {
$query = "SELECT * FROM tbladdress WHERE userID = $userID";
$addresses = array();
$result = mysqli_query(MySQLConnection::connectToMySQL(), $query);
if (!$result) {
die ("Failed getting addresses for user: $userID");
}
if (!mysqli_num_rows($result)) {
die ("You haven't specified any addresses yet.");
}
for ($i = 0; $i < mysqli_num_rows($result); $i++) {
foreach (mysqli_fetch_assoc($result) as $key => $value) {
switch ($key) {
case "addressID":
//after instantiation, all address data will be automatically allocated to their own private vars
//refer to Address class
$objAddress = new Address ($value);
$key = $objAddress->getAddressID();
//pay careful attention here. I added $key here, you'll see where it will be used...
$addresses[$key] = $objAddress;
break;
}
}
}
return $addresses;
mysqli_close(MySQLConnection::connectToMySQL());
}
}
?>
Now, the implementation:
For example you might have a user class:
Code: Select all
<?php
require_once('class.UserFactory.php');
class User {
private $_userID;
private $_addresses;
public function __construct($userID = null) {
if ($userID != null) {
$pattern = '/[0-9]/';
$matches = preg_match($pattern, $userID);
if (!$matches) {
throw new Exception('ERROR: userID must be specified with numbers.');
}
//set the $this->_userID the same as $userID which was specified within the param
$this->_userID = $userID;
//load this user's addresses by calling the private function _loadAddresses()
$this->_loadAddresses();
} else {
/**
* set $this->_userID to null, because this class will be used for data insertion then and new data insertion doesn't require
* any userID. userID will be generated by AUTO_INCREMENT.
*/
$this->_userID = null;
} //end if
}//end __construct()
private function _loadAddresses () {
$this->_addresses = UserFactory::getAddressesForUser($this->_userID);
}
public function addAddress (Address $address, $key) {
if ($this->getNumberOfAddresses() == 5) {
throw new Exception("ERROR: Unable to add address. Maximum addresses per user are limited to 5. You already have $this->getNumberOfAddresses() address(es).");
}
$this->_addresses[$key] = $address;
}
//Still remember the key I mentioned in the UserFactory class ? Here, where it's useful.
public function removeAddress ($key) {
if ($this->getNumberOfAddresses() == 0) {
throw new Exception('ERROR: No address to remove. You have'.$this->getNumberOfAddresses().' addresses');
}
if (isset($this->_addresses[$key])) {
unset ($this->_addresses[$key]);
}
}
public function getNumberOfAddresses() {
return sizeof($this->_addresses);
}
}
?>
Ok, that's it...the class user is ready to use, well not to ready actually...I haven't done the insertion part. Maybe if you want to create for example an Employee class, you can edit the user class to be ABSTRACT, then create:
Using the User class, you can instantiate it:
Implementation of User class. For example you already have a user in the database.
Code: Select all
<?php
require_once('class.User.php');
$member = new User(1);
$memAddress = new Address();
//add address for this member, and give $key in the param for easiness in usage.
$member->addAddress($memAddress, $memAddress->getAddressID());
echo $member->getNumberOfAddresses();
//remove address for this member according the $key, which is the same as the addressID.
$member->removeAddress($memAddress->getAddressID());
echo $member->getNumberOfAddresses();
?>
So, that's it, I hope it would help other members in understanding:
- How OOP works
How objects communicate
This explanations came from what I read from the books, and very helpful and friendly members here in PHPDN. Therefore, I thank them ! (refer to viewtopic.php?t=58324).
See you,
Chris