applying a string of commands to properties of an object in php - php

I've got a Accounts class which looks like this:
class Account {
public $accID;
public $balance;
public function __construct($accNum, $startBalance){
$this->accID = $accNum;
$this->balance = $startBalance;
}
public function deposit($amount){
$this->balance = $balance + $amount;
}
public function withdraw($amount){
if($amount > $this->balance)
die("There is not enough money in this account to withdraw");
$this->balance = $balance + $amount;
}
public function getbalance() {
return $this->balance;
}
public function getaccID() {
return $this->accID;
}
public function setaccID($accID){
$this->accID = $accID;
}
}
This is fine, however I am inputting from a text file which deals with transactions. Example: "105 D 200" which means go to account 105 and Deposit 200.
I have been able to create multiple Accounts and split the transaction file into their different parts.
foreach($getFile as $v) {
list($c, $d, $e) = explode(" ", $v);
$acc[] = $c;
$type[] = $d;
$amount[] = $e;
}
I just cannot figure out how to use these sub strings in order work with my functions in the accounts class.
Any help would be appreciated, thanks you!

First of all , there is a logic error in your withdraw method, you are adding an amount and not subtracting it from the balance,
You can create some kind of Account Manager , which will store all accounts and you can get the account from it,delete,get all accounts ... etc
Then you can read file and process it.
Overall code would be something like this.
foreach($getFile as $v) {
list($c, $d, $e) = explode(' ', $v);
$account = AccountManager::manager()->getAccountWithId($c);
if($d == 'D') {
$account->deposit($e);
}
// add more cases when to withdraw ... etc
}
print_r(AccountManager::manager()->getAccounts());
// This will be a Singleton
class AccountManager {
private static $instance;
private $accounts;
protected function __construct() {
$this->accounts = Array();
}
// To create a single instance
public static function manager() {
if(AccountManager::$manager === null) {
AccountManager::$manager = new AccountManager();
}
return AccountManager::$manager;
}
public getAccountWithId($accountId,$autoCreate = true) {
if(array_key_exists($accountId,$this->accounts)) {
return $this->accounts[$accountId];
} else if($autoCreate) {
// Create a new account with zero balance
$account = new Account($accountId,0);
$this->accounts[$accountId] = $account;
return $account;
}
return null;
}
public deleteAccountWithId($accountId) {
if(array_key_exists($accountId,$this->accounts)) {
unset($this->accounts[$accountId]);
}
}
public getAccounts() {
return array_values($this->accounts);
}
}
class Account {
public $accID;
public $balance;
public function __construct($accNum, $startBalance){
$this->accID = $accNum;
$this->balance = $startBalance;
}
public function deposit($amount){
$this->balance += $amount;
}
public function withdraw($amount){
if($amount > $this->balance) {
die("There is not enough money in this account to withdraw");
}
// Make sure you are substracting the amount and not adding it.
$this->balance -= $amount;
}
public function getbalance() {
return $this->balance;
}
public function getaccID() {
return $this->accID;
}
public function setaccID($accID){
$this->accID = $accID;
}
}

Related

How to update value in a class objecct in php

I have one file user.php with constructor for the client:
class Client{
public $name;
public $pin;
public $balance;
function __construct($name, $pin, $balance){
$this->name = $name;
$this->pin = $pin;
$this->balance = $balance;
}
}
$client1 = new Client("Alan", "0201", 2000);
?>
Also I have a file where i do some math to the client object:
$balance = $client1->balance;
function withdrow($amount, $balance){
$currentBalance = $balance - $amount;
if($balance < $amount){
echo "You are low on balance";
}
else{
$client1->balance = $currentBalance;
return $currentBalance;
}
}
And 3rd html file where I include First file with the client and I want to echo the updated value of balance on the screen.But its print the value set in client.How to update the balance.
My code look like this right now but setter not change the value balance:
class Client{
public $name;
private $pin;
private $balance;
function __construct($name, $pin, $balance){
$this->name = $name;
$this->pin = $pin;
$this->balance = $balance;
}
private function setPin($pin){
$this->pin = $pin;
}
public function getPin(){
return $this->pin;
}
public function setBalance($balance){
$this->balance = $balance;
}
public function getBalance(){
return $this->balance;
}
}
$client1 = new Client("Alan", "0201", 2000);
you must call function with call by reference
function withdrow($amount, &$balance){ /** call by reference */
$currentBalance = $balance - $amount;
if($balance < $amount){
echo "You are low on balance";
}
else{
$client1->balance = $currentBalance;
return $currentBalance;
}
}

php5 OOP - object type restriction doesn't work

I'm learning OOP, and got a little problem here with not understanding the code.
Here it is.
class ShopProduct {
private $title;
private $producerMainName;
private $producerFirstName;
protected $price;
private $discount = 0;
function __construct( $name, $firstName, $mainName, $price) {
$this->title = $name;
$this->producerFirstName = $firstName;
$this->producerMainName = $mainName;
$this->price = $price;
}
public function getProducer() {
return "{$this->producerMainName} "."{$this->producerFirstName} \n ";
}
public function setDiscount($num){
$this->discount = $num;
}
public function getDiscount() {
return $this->discount;
}
public function getTitle() {
return $this->title;
}
public function getPrice() {
return ($this->price - $this->discount);
}
public function getSummaryLine() {
$base = "{$this->title} ( {$this->producerMainName}, ";
$base .= "{$this->producerFirstName} )";
return $base;
}
}
class CDProduct extends ShopProduct {
private $playLength = 0;
public function __construct($title, $firstName, $mainName, $price, $playLength) {
parent::__construct($title, $firstName, $mainName, $price);
$this->playLength = $playLength;
}
public function getPlayLength() {
return $this->playLength;
}
public function getSummaryLine() {
$base = parent::getSummaryLine();
$base .= ": {$this->playLength()} minutes";
return $base;
}
}
class BookProduct extends ShopProduct {
private $numPages = 0;
public function __construct($title, $firstName, $mainName, $price, $numPages) {
parent::__construct($title, $firstName, $mainName, $price);
$this->numPages = $numPages;
}
public function getNumberOfPages() {
return $this->numPages;
}
public function getSummaryLine() {
$base = parent::getSummaryLine();
$base .= ": {$this->numPages()} pages";
return $base;
}
}
class ShopProductWriter {
private $products = array();
public function addProduct($shopProduct){
if(! ($shopProduct instanceof ShopProduct) ){
die('object error');
}
$this->products[] = $shopProduct;
}
public function write($shopProduct) {
foreach($this->products as $shopProducts){
$str = "{$shopProduct->getTitle()}: "."{$shopProduct->getProducer()}"." {$shopProduct->getPrice()}$ \n";
}
print $str;
}
}
$product = new CDProduct('Song is the rythm','Zyxel','Beatz',50, 60.33);
$write = new ShopProductWriter();
$write->addProduct($product);
$write->write($product);
The problem is here
class ShopProductWriter {
private $products = array();
public function addProduct($shopProduct){
if(! ($shopProduct instanceof ShopProduct) ){
die('object error');
}
$this->products[] = $shopProduct;
}
public function write($shopProduct) {
foreach($this->products as $shopProducts){
$str = "{$shopProduct->getTitle()}: "."{$shopProduct->getProducer()}"." {$shopProduct->getPrice()}$ \n";
}
print $str;
}
}
As you see there is condition - if the object is not ShopProduct type - goes error.
But as you see i'm creating CDProduct object.
$product = new CDProduct('Song is the rythm','Zyxel','Beatz',50, 60.33);
$write = new ShopProductWriter();
$write->addProduct($product);
$write->write($product);
It should show error. Anybody can say me what i'm doing wrong?
Objects of CDProduct are also of type ShopProduct. In the class definition:
class CDProduct extends ShopProduct {
So it is an object of both types.
http://php.net/manual/en/language.oop5.inheritance.php
If an object extends a parent or implements an interface, it can be considered of that type also.
http://php.net/manual/en/language.operators.type.php
You got already feedback about why a CDProduct is a ShopProduct, so I just add another hint on some code you've written where PHP has already support for:
public function addProduct($shopProduct){
if(! ($shopProduct instanceof ShopProduct) ){
die('object error');
}
$this->products[] = $shopProduct;
}
Instead of doing the check on your own, you can just make use of Type Hinting to reduce your code and make it more expressive:
public function addProduct(ShopProduct $shopProduct) {
$this->products[] = $shopProduct;
}
I hope this helps as you wrote you're currently learning about OOP.

PHP aggregation of a property, of all objects in a class

apologies in advance for being a OO noob...
I am trying to write a method to aggregate a property of all objects that exist for a given class. The code below describes what I want to do.
Class TeamMember(){
function SetScore($value) {
$this->score = $value;
}
function GetTotalScoreForTeam() {
//best way to iterate over all the objects to get a sum??????
return totalScore;
}
}
$john = new TeamMember();
$john->SetScore('182');
$paul = new TeamMember();
$paul->SetScore('212');
$totalScore = TeamMember->GetTotalScoreForTeam;
Thanks!
Even if this is not the best way to approach this problem, I think it is the most explaining your problem with your pre-written code:
class TeamMember { // a class is not a function/method; removed the ()
public static $members = array(); // holds the instances
public $score; // It is simply good practice to declare your fields (it is not necessary)
function __construct () {
self::$members[] = $this; // save the instances accessible for your score-calcuating method
}
function setScore ($value) {
$this->score = $value;
}
static function getTotalScoreForTeam () { // a static method is best here
$totalScore = 0;
foreach (self::$members as $member) // foreach over the instances holding list
$totalScore += $member->score;
return $totalScore;
}
}
$john = new TeamMember();
$john->setScore('182');
$paul = new TeamMember();
$paul->setScore('212');
$totalScore = TeamMember::getTotalScoreForTeam(); // for static access, use a :: instead of ->
As Mike B said in the comment you should first group your TeamMember instances in an instance of a Team class and then run some aggregate function to calculate the total score of that particular team, e.g.
<?php
$team1 = Team::create('Team 1')
->add( TeamMember::create('john')->SetScore(182) )
->add( TeamMember::create('paul')->SetScore(212) );
$team2 = Team::create('Team 2')
->add( TeamMember::create('peter')->SetScore(200) )
->add( TeamMember::create('marry')->SetScore(300) );
foo($team1);
foo($team2);
function foo(Team $team) {
$score = $team->membersReduce(
function($v, $e) {
return $v+$e->getScore();
}
);
$members = $team->membersMap(
function($e) {
return $e->getName();
}
);
echo 'team : ', $team->getName(), "\r\n";
echo 'score: ', $score, "\r\n";
echo 'members: ', join(' | ', $members), "\r\n";
}
class TeamMember {
protected $score = 0;
protected $name;
public static function create($name) {
return new TeamMember($name);
}
public function __construct($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
public function SetScore($value) {
$this->score = $value;
return $this;
}
public function GetScore() {
return $this->score;
}
}
class Team {
protected $members = array();
protected $name;
public static function create($name) {
return new Team($name);
}
public function __construct($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
public function add(TeamMember $t) {
// <-- check if $t already member of team -->
$this->members[] = $t;
return $this;
}
public function membersReduce($fn) {
return array_reduce($this->members, $fn);
}
public function membersMap($fn) {
return array_map($fn, $this->members);
}
}
prints
team : Team 1
score: 394
members: john | paul
team : Team 2
score: 500
members: peter | marry

get set properties in php

I'm from the C# environment and I'm starting to learn PHP in school.
I'm used to set my properties in C# like this.
public int ID { get; set; }
What's the equivalent to this in php?
Thanks.
There is none, although there are some proposals for implementing that in future versions.
For now you unfortunately need to declare all getters and setters by hand.
private $ID;
public function setID($ID) {
$this->ID = $ID;
}
public function getID() {
return $this->ID;
}
for some magic (PHP likes magic), you can look up __set and __get magic methods.
Example
class MyClass {
private $ID;
private function setID($ID) {
$this->ID = $ID;
}
private function getID() {
return $this->ID;
}
public function __set($name,$value) {
switch($name) { //this is kind of silly example, bt shows the idea
case 'ID':
return $this->setID($value);
}
}
public function __get($name) {
switch($name) {
case 'ID':
return $this->getID();
}
}
}
$object = new MyClass();
$object->ID = 'foo'; //setID('foo') will be called
Thanks for your answers everyone. It helped me to create something like this:
In my parent class:
public function __get($name){
if (ObjectHelper::existsMethod($this,$name)){
return $this->$name();
}
return null;
}
public function __set($name, $value){
if (ObjectHelper::existsMethod($this,$name))
$this->$name($value);
}
ObjectHelper::existsMethod is a method which just check if given protected method exists.
private $_propertyName = null;
protected function PropertyName($value = ""){
if (empty($value)) // getter
{
if ($this-> _propertyName != null)
return $this->_propertyName;
}
else // setter
{
$this-> _propertyName = $value;
}
return null;
}
So I can use something like this in any class:
$class = new Class();
$class->PropertyName = "test";
echo $class->PropertyName;
I was inspired by C# :)
What do you think about this, guys?
Here is my ObjectHelper if someone would like to use it:
namespace Helpers;
use ReflectionMethod;
class ObjectHelper {
public static function existsMethod($obj, $methodName){
$methods = self::getMethods($obj);
$neededObject = array_filter(
$methods,
function ($e) use($methodName) {
return $e->Name == $methodName;
}
);
if (is_array($neededObject))
return true;
return false;
}
public static function getMethods($obj){
$var = new \ReflectionClass($obj);
return $var->getMethods(ReflectionMethod::IS_PROTECTED);
}
}
Mchi is right, but there is another way of doing it by using single function
private $ID;
public function ID( $value = "" )
{
if( empty( $value ) )
return $this->ID;
else
$this->ID = $value;
}
But yeah this approach is pretty much inline with what you do in c#. but this is only an alternative
Or try using php's __set and __get in your class more info here
http://php.net/manual/en/language.oop5.overloading.php
Another exampled using Variable function name
class MyClass {
private $ID;
protected $ID2;
private function setID($ID) {
$this->ID = $ID;
}
private function getID() {
return $this->ID;
}
private function setID2($ID2) {
$this->ID2 = $ID2;
}
private function getID2() {
return $this->ID2;
}
public function __set($name,$value) {
$functionname='set'.$name;
return $this->$functionname($value);
}
public function __get($name) {
$functionname='get'.$name;
return $this->$functionname();
}
}
$object = new MyClass();
$object->ID = 'foo'; //setID('foo') will be called
$object->ID2 = 'bar'; //setID2('bar') will be called
private $ID;
public function getsetID($value = NULL)
{
if ($value === NULL) {
return $this->ID;
} else {
$this->ID = $value;
}
}
I know I am a bit late to the party on this question, but I had the same question/thought myself. As a C# developer who does PHP, when the job requires, I want to have a simple way to create properties just I would be able to in C#.
I whipped up a first draft this afternoon which allows you to create the backing fields and specify their accessors or have pure accessors with no backing field. I will update my answer as the code evolves and provide a link when I get it to the state where it can be imported as a composer package.
For simplicity, I created the functionality as a PHP trait so you can drop it in to any class you want instead of having to extend a base class. Eventually I hope to extend this functionality to discern between external public calls to the properties and protected/private calls.
Here is the code for the trait itself:
trait PropertyAccessorTrait
{
private static $__propertyAccessors = [];
/* #property string $__propertyPrefix */
public function __get($name)
{
$this->__populatePropertyAcessors($name);
return $this->__performGet($name);
}
public function __set($name, $value)
{
$this->__populatePropertyAcessors($name);
$this->__performSet($name, $value);
}
public function __isset($name)
{
// TODO: Implement __isset() method.
}
public function __unset($name)
{
// TODO: Implement __unset() method.
}
protected function __getBackingFieldName($name)
{
if (property_exists(self::class, '__propertyPrefix')) {
$prefix = $this->__propertyPrefix;
} else {
$prefix = '';
}
return $prefix . $name;
}
protected function __canget($name)
{
$accessors = $this->__getPropertyAccessors($name);
return $accessors !== null && isset($accessors['get']);
}
protected function __canset($name)
{
$accessors = $this->__getPropertyAccessors($name);
return $accessors !== null && isset($accessors['set']);
}
protected function __performGet($name)
{
if (!$this->__canget($name)) {
throw new \Exception('Getter not allowed for property: ' . $name);
}
$accessors = $this->__getPropertyAccessors($name)['get'];
/* #var \ReflectionMethod $method */
$method = $accessors['method'];
if (!empty($method)) {
return $method->invoke($this);
}
return $this->{$this->__getBackingFieldName($name)};
}
protected function __performSet($name, $value)
{
if (!$this->__canset($name)) {
throw new \Exception('Setter not allowed for property: ' . $name);
}
$accessors = $this->__getPropertyAccessors($name)['set'];
/* #var \ReflectionMethod $method */
$method = $accessors['method'];
if (!empty($method)) {
return $method->invoke($this, $value);
}
$this->{$this->__getBackingFieldName($name)} = $value;
}
protected function __getPropertyAccessors($name)
{
return isset(self::$__propertyAccessors[$name])
? self::$__propertyAccessors[$name]
: null
;
}
protected function __getAccessorsFromDocBlock($docblock)
{
$accessors = [];
if (!empty(trim($docblock))) {
$doclines = null;
if (!empty($docblock)) {
$doclines = explode("\n", $docblock);
}
if (!empty($doclines)) {
foreach ($doclines as $line) {
if (preg_match('/#(get|set)\\s+(public|private|protected)/', $line, $matches)) {
$accessors[$matches[1]]['visibility'] = $matches[2];
}
}
}
}
return $accessors;
}
protected function __populatePropertyAcessors($name)
{
if ($this->__getPropertyAccessors($name) !== null) return;
try {
$property = new \ReflectionProperty(self::class, $this->__getBackingFieldName($name));
} catch (\ReflectionException $ex) {
$property = null;
}
$accessors = [];
if ($property != null) {
$accessors = $this->__getAccessorsFromDocBlock($property->getDocComment());
}
try {
$methodName = 'get' . ucfirst($name);
$method = new \ReflectionMethod(self::class, $methodName);
$method->setAccessible(true);
$accessors = array_merge($accessors, $this->__getAccessorsFromDocBlock($method->getDocComment()));
} catch (\ReflectionException $ex) {
$method = null;
}
if ($method !== null || isset($accessors['get'])) {
$accessors['get']['method'] = $method;
}
try {
$methodName = 'set' . ucfirst($name);
$method = new \ReflectionMethod(self::class, $methodName);
$method->setAccessible(true);
$accessors = array_merge($accessors, $this->__getAccessorsFromDocBlock($method->getDocComment()));
} catch (\ReflectionException $ex) {
$method = null;
}
if ($method !== null || isset($accessors['set'])) {
$accessors['set']['method'] = $method;
}
self::$__propertyAccessors[$name] = $accessors;
}
}
Here is a quick unit test I created using the Codeception format:
<?php
class PropertyAssesorTraitTestClass
{
use PropertyAccessorTrait;
private $__propertyPrefix = '_';
/**
* #get public
* #set public
*/
private $_integer = 1;
/**
* #get public
*/
private $_getonly = 100;
/**
* #set public
*/
private $_setonly;
private $_customDoubler;
private function getCustomDoubler()
{
return $this->_customDoubler * 2;
}
private function setCustomDoubler($value)
{
$this->_customDoubler = $value * 2;
}
public $publicField = 1234;
/**
* #return int
* #get public
*/
private function getPureAccessor()
{
return $this->publicField;
}
/**
* #param $value
* #set public
*/
private function setPureAccessor($value)
{
$this->publicField = $value;
}
private $_purePrivate = 256;
}
$I = new UnitTester($scenario);
$I->wantTo('Ensure properties are accessed correctly');
$instance = new PropertyAssesorTraitTestClass();
$I->assertSame(1, $instance->integer);
$instance->integer = 2;
$I->assertSame(2, $instance->integer);
$instance->integer = $instance->integer + 1;
$I->assertSame(3, $instance->integer);
$instance->integer++;
$I->assertSame(4, $instance->integer);
$I->assertSame(100, $instance->getonly);
$I->expectException('Exception', function () use ($instance) { $instance->getonly = 50; });
$instance->setonly = 50;
$I->expectException('Exception', function () use ($instance) { $a = $instance->setonly; });
$instance->customDoubler = 100;
$I->assertSame(400, $instance->customDoubler);
$I->assertSame(1234, $instance->publicField);
$instance->pureAccessor = 1000;
$I->assertSame(1000, $instance->publicField);
$instance->publicField = 1234;
$I->assertSame(1234, $instance->publicField);
$I->assertSame(1234, $instance->pureAccessor);
$I->expectException('Exception', function () use ($instance) { return $instance->purePrivate; });
I like to use this pattern:
class foo
{
//just add p as prefix to be different than method name.
protected $pData;
public funtion __construct() {}
public funtion __destruct() {}
public funtion __clone() {}
public function Data($value == "")
{
if ($value != "") {
$this->pData = $value;
}
return $this->pData;
}
}
$myVar = new foo();
//for SET
$myVar->Data("A Value");
//for GET
$item = $myVar->Data();
class MyClass
{
private $name = null;
public function __construct($name = null)
{
$this->name = $name;
}
public function __set($name, $value)
{
if (property_exists($this, $name)) {
$this->name = $value;
}
return $this;
}
public function __get($name)
{
if (property_exists($this, $name)) {
return $this->$name;
}
return null;
}
}
this is PHP ; you don't need get set
class MyClass {
public $ID;
}
$object = new MyClass();
$object->ID = 'foo';
echo $object->ID;
will work

How perform USort() on an Array of Objects class definition as a method?

class Contact{
public $name;
public $bgcolor;
public $lgcolor;
public $email;
public $element;
public function __construct($name, $bgcolor, $lgcolor, $email, $element)
{
$this->name = $name;
$this->bgcolor = $bgcolor;
$this->lgcolor = $lgcolor;
$this->email = $email;
$this->element = $element;
}
public static function sortByName(Contact $p1, Contact $p2)
{
return strcmp($p1->name, $p2->name);
}
}
class ContactList implements Iterator, ArrayAccess
{
protected $_label;
protected $_contacts = array();
public function __construct($label)
{
$this->_label = $label;
}
public function getLabel()
{
return $this->_label;
}
public function addContact(Contact $contact)
{
$this->_contacts[] = $contact;
}
public function current()
{
return current($this->_contacts);
}
public function key()
{
return key($this->_contacts);
}
public function next()
{
return next($this->_contacts);
}
public function rewind()
{
return reset($this->_contacts);
}
public function valid()
{
return current($this->_contacts);
}
public function offsetGet($offset)
{
return $this->_contacts[$offset];
}
public function offsetSet($offset, $data)
{
if (!$data instanceof Contact)
throw new InvalidArgumentException('Only Contact objects allowed in a ContactList');
if ($offset == '')
{
$this->_contacts[] = $data;
} else
{
$this->_contacts[$offset] = $data;
}
}
public function offsetUnset($offset)
{
unset($this->_contacts[$offset]);
}
public function offsetExists($offset) {
return isset($this->_contacts[$offset]);
}
public function sort($attribute = 'name')
{
$sortFct = 'sortBy' . ucfirst(strtolower($attribute));
if (!in_array($sortFct, get_class_methods('Contact')))
{
throw new Exception('contact->sort(): Can\'t sort by ' . $attribute);
}
usort($this->contact, 'ContactList::' . $sortFct);
}
}
public function Sort($property, $asc=true)
{
// this is where sorting logic takes place
$_pd = $this->_contact->getProperty($property);
if ($_pd == null)
{
user_error('Property '.$property.' does not exist in class '.$this->_contact->getName(), E_WARNING);
return;
}
// set sortDescriptor
ContactList::$sortProperty = $_pd;
// and apply sorting
usort($this->_array, array('ContactList', ($asc?'USortAsc':'USortDesc')));
}
function getItems(){
return $this->_array;
}
class SortableItem extends ContactList
{
static public $sortProperty;
static function USortAsc($a, $b)
{
/*#var $_pd ReflectionProperty*/
/*
$_pd = self::$sortProperty;
if ($_pd !== null)
{
if ($_pd->getValue($a) === $_pd->getValue($b))
return 0;
else
return (($_pd->getValue($a) < $_pd->getValue($b))?-1:1);
}
return 0;
}
static function USortDesc($a, $b)
{
return -(self::USortAsc($a,$b));
}
}
This approach keeps giving me PHP Warnings: usort() [function.usort]: of all kinds which I can provide later as needed to comment out those methods and definitions in order to test and fix some minor bugs of our program.
**$billy parameters are already defined.
$all -> addContact($billy);
// --> ended up adding each contact manually above
$all->Sort('name',true);
$items = $all->getItems();
foreach($items as $contact)
{
echo $contact->__toString();
}
$all->sort();
The reason for using usort is to re-arrange the order alphabetically by name but somehow is either stating that the function comparison needs to be an array or another errors which obviously I have seemed to pass. Any help would be greatly appreciated, thanks in advance.
It's happening because the variable inside the usort call is not a valid array. You use $this->_contacts everywhere, but your usort line is:
usort($this->contact, 'ContactList::' . $sortFct);
Try changing that to:
usort($this->_contacts, 'ContactList::' . $sortFct);
<?php
class Contact{
public $name;
public $bgcolor;
public $lgcolor;
public $email;
public $element;
public function __construct($name, $bgcolor, $lgcolor, $email, $element)
{
$this->name = $name;
$this->bgcolor = $bgcolor;
$this->lgcolor = $lgcolor;
$this->email = $email;
$this->element = $element;
}
}
class ContactList implements Iterator, ArrayAccess
{
public $_label;
public $_contacts = array();
public function __construct($label)
{
$this->_label = $label;
}
public function getLabel()
{
return $this->_label;
}
public function addContact(Contact $contact)
{
$this->_contacts[] = $contact;
}
public function current()
{
return current($this->_contacts);
}
public function key()
{
return key($this->_contacts);
}
public function next()
{
return next($this->_contacts);
}
public function rewind()
{
return reset($this->_contacts);
}
public function valid()
{
return current($this->_contacts);
}
public function offsetGet($offset)
{
return $this->_contacts[$offset];
}
public function offsetSet($offset, $data)
{
if (!$data instanceof Contact)
throw new InvalidArgumentException('Only Contact objects allowed in a ContactList');
if ($offset == '')
{
$this->_contacts[] = $data;
} else
{
$this->_contacts[$offset] = $data;
}
}
public function offsetUnset($offset)
{
unset($this->_contacts[$offset]);
}
public function offsetExists($offset) {
return isset($this->_contacts[$offset]);
}
/* This is the comparing function to be used with usort to make it alphabetically ordered for All Contacts */
public function sort_by($field, &$arr, $sorting='SORT_DSC', $case_insensitive=true){
if(is_array($arr) && (count($arr)>0) && ( ( is_array($arr[0]) && isset($arr[0][$field]) ) || ( is_object($arr[0]) && isset($arr[0]->$field) ) ) ){
if($case_insensitive==true) $strcmp_fn = "strnatcasecmp";
else $strcmp_fn = "strnatcmp";
if($sorting=='SORT_DSC'){
$fn = create_function('$a,$b', '
if(is_object($a) && is_object($b)){
return '.$strcmp_fn.'($a->'.$field.', $b->'.$field.');
}else if(is_array($a) && is_array($b)){
return '.$strcmp_fn.'($a["'.$field.'"], $b["'.$field.'"]);
}else return 0;
');
}else if($sorting=='SORT_ASC'){
$fn = create_function('$a,$b', '
if(is_object($a) && is_object($b)){
return '.$strcmp_fn.'($b->'.$field.', $a->'.$field.');
}else if(is_array($a) && is_array($b)){
return '.$strcmp_fn.'($b["'.$field.'"], $a["'.$field.'"]);
}else return 0;
');
}
usort($arr, $fn);
return true;
}else{
return false;
}
}
}
?
The call:
$all->sort_by('name',$all->_contacts,'SORT_DSC','false');

Categories