...

View Full Version : Advanced OOP Question



srule_
12-26-2007, 10:52 PM
Sorry for all these questions, I'll try to make this my last one for a while ;).

Anyway, I made an object of a Warrior from my ArmyUnit Class. This warrior has 100 Hit Points, and does 20Damage.



$warrior = new ArmyUnit('100', '20');


now I have another class called "ArmyStats". This class has a function called "getAttack($unitType)" that looks into a database for the number of units each person has and multiplies it against the attack strength per unit to get the total attack.

Is there a way to pass the "$warrior" object I created into the getAttack() function and then get the attack strength that I assigned to the object.

for example something like the following but then be able to retrieve info about the object i pass into it:


//Make New Unit - A Warrior
$warrior = new ArmyUnit('100', '20');

//Get The Attack Damage of All Warriors
$army = new ArmyStats();
$army->getAttack($warrior);


perhaps I'm building my classes wrong and should Have my attack Strength function right in my ArmyUnit class? I'm not to sure...

oesxyl
12-26-2007, 11:37 PM
Sorry for all these questions, I'll try to make this my last one for a while ;).

I don't think this is a problem, could be very usefull, :)

could you post the declaration of ArmyUnit and ArmyStats? is more easy to use your code as example then inventing my own, :)


perhaps I'm building my classes wrong and should Have my attack Strength function right in my ArmyUnit class? I'm not to sure...
In this case attackStrength probably is better to be method of ArmyUnit because "attack strength" is a property of "army unit".

the function of a class is "method". You can have functions, that operate with objects without being methods of any class.

best regards

Fou-Lu
12-27-2007, 12:50 AM
OOP ftw, and php is getting better at it too!
You can always do 'something' to make the results you want, it just depends on how you have coded it.
Now, if I were you, I would probably create an interface for my 'pieces' or the class you have made (warrior for example). Just don't call it class cause that won't work. For a quick example:


interface Pieces // You can really call it whatever you want, doesn't matter just make sure it makes sense to you :P
{
public function getHitPoints();
public function setHitPoints($hitPoints);
public function getDamage();
public function setDamage($damage);
}

// Declare your ArmyUnit as implementing Pieces (or whatever you named your interface)

// KK, now we have an interface to use, lets create a class:
// lol, almost declared it public, which php does not support :P
// Obviously you would want to error handle as you see fit
class Warrior extends ArmyUnit
{
public function __construct($hitPoints, $damage)
{
parent::__construct($hitPoints, $damage);
}
}

Now the fun begins, and one of the many advantages of abstracting your objects.
PHP is a loose datatyped language. This means that you do not need to explicitly define a datatype. This is a disadvantage in my opinion (as a java/c# developer).
However, it does have typehinting, which is pretty nice. Now that all of you 'classes' are interfaced (warrior is a piece, whateverotherclass is a piece), you can specifically request these as the objects:


class ArmyStats
{
// ... whatever you've got
public function getAttack(Pieces $objPiece) //<-- This is typehinted [Pieces]
{
// Do whatever you gotta do. Since this is interfaced, you can also include:
$objPiece->getDamage();
// as a part of your code, yay!
}
}

Now for some explaining :P
The interface is like a contract, it says, you are a type of this interface, and must implement these methods. It is up to the developer to do the work.
Notice that I now have a warrior class instead of an army unit class. I would recommend that you create armyunit as an abstract class containing these methods. Abstracts are great for inheritance models, and you can easily create additional children for it and all of the inherited methods are intact. Now, why have an army unit class implementing an interface? Can't you just do the abstract? Thats true, you can. However, this method says you can get the damage from ANY type of 'Piece', and that now means it does not require itself to be an armyunit.
Above is a demonstration of polymorphism. The object you have given it is a 'Piece', and you are requesting its getDamage method. Since piece is an interface, we know that anything that 'is a' piece also has a getDamage method. The intepreter will 'bubble up' the chain to find the closest usable getDamage method to the object that has been provided (warrior). Warrior does not contain this method, but its parent ArmyUnit does. It will still use the information provided in the ArmyUnit class.
Neat huh?
Hope that confusing mess I gave you helps out!

srule_
12-27-2007, 02:47 PM
Wow, Thank you for that great response! Very Helpful. I Started to design my class before I read it though so I am not making use of some of the more advanced topics you covered. This is the code I got done yesterday:

ArmyClass.php:


<?php

class Army {

//Variable Declatiation
private $hp;
private $dmg;
private $range;
private $cost;

//constructure
function __construct($hp, $dmg, $range, $cost){
$this->hp=$hp;
$this->dmg=$dmg;
$this->range=$range;
$this->cost=$cost;
}

//Memeber Functions

function getHP(){
return $this->hp;
}

function getDmg(){
return $this->dmg;
}

function getRange(){
return $this->range;
}

function getCost(){
return $this->cost;
}



}



?>


index.php:


<?php

include('armyClass.php');

//Make a unit of type Warrior
$warrior = new Army('100', '10', '0', '90');
echo $militia->getHP();

//Make a unit of type Wizard
$wizard = New Army('150', '14', '0', '130');

//Test the get Methods
echo $warrior->getHP();
echo $wizard->getHP();
echo $warrior->getHP()*$wizard->getHP();

?>


How does that look so far? And thanks for the help I'm going to head over to php.net read up on the topics you mentioned and then incorporate them into my code.

oesxyl
12-27-2007, 09:33 PM
Wow, Thank you for that great response! Very Helpful. I Started to design my class before I read it though so I am not making use of some of the more advanced topics you covered.
I hope that you cover later, because has no meaning to use OOP if you don't take advantage of inheritance, polymorphism, abstraction and other thing mentionated by Fou-Lu.



This is the code I got done yesterday:

ArmyClass.php:


<?php

class Army {

//Variable Declatiation
private $hp;
private $dmg;
private $range;
private $cost;

//constructure
function __construct($hp, $dmg, $range, $cost){
$this->hp=$hp;
$this->dmg=$dmg;
$this->range=$range;
$this->cost=$cost;
}

//Memeber Functions

function getHP(){
return $this->hp;
}

function getDmg(){
return $this->dmg;
}

function getRange(){
return $this->range;
}

function getCost(){
return $this->cost;
}
}
?>


- why don't you use a readable name for attributes? for example $hp, why $dmg and not $damage, few year later probably you forget what is the meaning of $dmg
- why do you make the attributes private? this will force you to write a getXXX method, for each, do you really need that?
- where are the setXXX methods, many times you need to change some values of the attributes after you call the constructor.



index.php:


<?php
include('armyClass.php');

//Make a unit of type Warrior
$warrior = new Army('100', '10', '0', '90');
echo $militia->getHP();

//Make a unit of type Wizard
$wizard = New Army('150', '14', '0', '130');

//Test the get Methods
echo $warrior->getHP();
echo $wizard->getHP();
echo $warrior->getHP()*$wizard->getHP();

?>



same example with public attributes:



<?php
echo $warrior->hp * $wizard->hp;
?>


but you must avoid to have something as:



echo $army->warrior->hp * $army->wizard->hp;


the main advantage of oop is, IMO:
- you know who is responsable for what, so you can track bugs, extend code, do what you want, :)
- you write less code then using other paradigm



How does that look so far? And thanks for the help I'm going to head over to php.net read up on the topics you mentioned and then incorporate them into my code.
is not bad at all, :).
you allready know this link, I guess, but just in case:

http://www.php.net/manual/en/language.oop5.php

best regards

Fou-Lu
12-28-2007, 04:13 AM
This is a good start on object oriented programming. Yes the primary advantages are the dynamic binding and inheritance, but hey, you gotta start somewhere right ;)
I will mention however that your attributes should be at the lightest scope: protected, where the order from lightest to heaviest is public, protected, private. I rarely allow any application to make use of a public attribute in any object oriented language, but that does depend on the data typing you allow.
Consider as well using setters for your data, and invoking the setters within your actual constructors. This allows a firm control of error checking and handling that will prevent system errors.
Consider a scenario, calculating a percentage based on a given mark and a given worth. I will assume that getters exist within the object:


class CalcPercent
{
private $given;
public $outOf;

public function __construct($given, $outOf)
{
$this->given = $given;
$this->outOf = $outOf;
}

public function calculate()
{
return ($this->given / $this->outOf) * 100;
}
}

Now, two problems exist within this. Fortunately php doesn't whine too much about zero division (unlike java or c# which will crash), but it will still toss a warning. The constructor has no error checking for the value itself, so its perfectly fine to do:


$perc = new CalcPercent(0, 0);
$earnedPercent = $perc->calculate();

This will toss an error. The other disadvantages is that it contains a public scope on the actual out of mark, so its also possible to do:


$perc = new CalcPercent(100, 100);
$perc->outOf = 0;
$earnedPercent = $perc->calculate();

Which will also toss an error. This is why error checking is important, and hence specific setters:


public function setOutOf($outOf)
{
if (!is_float($outOf) || $outOf <= 0)
{
throw new Exception('Invalid outOf specified!');
}
$this->outOf = $outOf;
}

And this can of course be used when specifying values within a constructor. Of course, this does depend a lot on the data involved, sometimes public scope is fine, but I still prefer control nonetheless.
PHP has a fantastic feature to it - a generic get/set method. That makes these fantastic, and are done like so:


public function __get($getWhat)
{
if (isset($this->$getWhat))
{
return $this->$getWhat;
}
return null;
}

public function __set($setWhat, $setVal)
{
// this is trickier to do correctly, but can be done like:
if (isset($this->$setWhat))
{
$this->$setWhat = $setVal;
}
}

And if your really tricky and use a consistent naming convention for your methods, you can actually generate a call to the setter from the magic set method - really handy trust me on that one. That will allow you to do the following:


$perc = new CalcPercent(0, 100);
try
{
$perc->outOf = 0;
}
catch (Exception $ex)
{
die($ex->getMessage());
}
$perc->calculate();

If you properly chain the magic set to each setter, this will die with a message of: Invalid outOf specified!

This is a lot of information for a new OOP programmer to absorb, but its nice to be aware of some of the things available to you in the near future. I switched to oop in php version 5.2.1, since my first attempts in the 5.0.1 core were... well, a good attempt from zend, and have been sufficiently satisfied with most of the oop performance in php. Version 5.0.1 had very poor polymorphism which caused enormous problems with their object core, and just recently I had to request a confirmation from the forums here about the correct use on requesting a parent overriden method to ensure I was being accurate.
For php 6, I'm crossing my fingers for scoping on my classes (and of course this would result in inner classes!), and that the reflection classes will be capable of reading default values for protected members (which boggles me to no end as to why it cannot :P).

Oh, a couple of quick other notes (I know I've gone on an on, lol).
Your formatting is nice, personally I wrap my opening brace to the next line, but it really is personal preference. You have everything nicely aligned and easily readable. Another one to add for you though is this, use doc comments for commenting. That is:
/**
*/
Style of commenting, with the two stars (and yes only two stars relflection cannot pick up on more for some reason). This will make your life easier in the future!
Have fun and keep cracking down on it!

srule_
01-02-2008, 01:17 AM
Fou-Lu, I do not understand what you were trying to get at in your first post. I have been reading php.net and playing with code to try and implement the topics you dicussed. I came up with some new code, but in reality it does exactly what my old code did. I will show you what I did. Hopefully you or someone else can look over it and see where I'm getting confused.

my Interface:


<?php
interface ArmyPieces
{
public function getHitPoints();
public function setHitPoints($hitpoints);
public function getDamade();
public function setDamage($damage);
public function getRange();
public function setRange($range);
public function getGold();
public function setGold($gold);
public function getWood();
public function setWood($wood);
public function getFood();
public function setFood($food);
}


My Main Class:


class ArmyUnits implements ArmyPieces {


//Variable Declatiation
private $hitPoints;
private $damage;
private $range;
private $gold;
private $wood;
private $food;

//constructure
function __construct($hitPoints, $damage, $range, $food, $gold, $wood){
$this->hitPoints=$hitPoints;
$this->damage=$damage;
$this->range=$range;
$this->food=$food;
$this->gold=$gold;
$this->wood=$wood;
}

//Memeber Functions
//------------------------------------------
//Get and set Hitpoint functions
public function getHitPoints(){
return $this->hitPoints;
}

public function setHitPoints($hitpoints){
$this->hitPoints=$hitPoints;
}


//------------------------------------------
//Get and set damage functions
public function getDamade(){
return $this->damage;
}

public function setDamage($damage){
$this->damage=$damge;
}


//------------------------------------------
//Get and set Range functions
public function getRange(){
return $this->range;
}

public function setRange($range){
$this->range=$range;
}



//------------------------------------------
//Get and set Gold Cost functions
public function getGold(){
return $this->gold;
}

public function setGold($gold){
$this->gold=$gold;
}


//------------------------------------------
//Get and set Wood Cost functions
public function getWood(){
return $this->wood;
}

public function setWood($wood){
$this->wood = $wood;
}


//------------------------------------------
//Get and set Food Cost functions
public function getFood(){
return $this->food;
}

public function setFood($food){
$this->food=$food;
}

}
?>


My Sub Class:


<?php
class Warrior extends ArmyUnits {

public function __construct($hitPoints, $damage, $range, $food, $gold, $wood)
{
parent::__construct($hitPoints, $damage, $range, $food, $gold, $wood);
}
}
?>


The other thing you talked about, lol:


<?php
class ArmyStats
{
// ... whatever you've got
public function getAttack(Warrior $objPiece) //<-- This is typehinted [Pieces]
{
// Do whatever you gotta do. Since this is interfaced, you can also include:
$objPiece->getDamage();
// as a part of your code, yay!
}
}
?>

index.php:


<?php

include('armyClass.php');

//Make a unit of type warrior and test a function
$Warrior = New Warrior(100,10,0,100,76,0);
echo "this unit cost ". $Warrior->getFood() ." food";

$WarriorStats = new ArmyStats();
echo getAttack($Warrior);

?>

Fou-Lu
01-02-2008, 02:57 AM
This is the right idea, except for the typehinted section you want either ArmyUnit or ArmyPieces as your type (otherwise you will always be stuck with having only Warriors you can get the attack for).
Lets see if I can quickly sketch your model:


+------------+ +-----------+ +----------+
| ArmyPieces | <|........... | ArmyUnits | <|--------- | Warrior |
+------------+ +-----------+ +----------+
/\
\/
|
+-----------+
| ArmyStats |
+-----------+

This looks about right. See, with this method of programming that you are following, ArmyStats has access to anything that inherits from the ArmyUnits (Warrior atm). So, if you create more unit types (lets take a chess game for example, a 'Knight', 'Rook/Castle', 'Bishop', 'Pawn', 'Queen', and 'King' would each extend from the ArmyUnits), they can all share the common code - Your army stats class does not care what the subclass in use is, it only cares about the parent being an ArmyUnit. Plus, the advantage if the inheritance model (which I've sooo poorly done up above ;)) is that you can also override given protected/public attributes / methods.
Just remember, inheritance is often your friend so long as two objects share common functionality. For example, you may also create an 'Infantry' unit, or 'Knight' unit, or something of the sorts - The army stats won't care what it is as long as it inherits from the ArmyUnits object.
Which brings me to my next mention. Remember that in OOP, these are all considered an object or a single entity. With this in mind, standard naming conventions tend (since there is no set criteria, I will use 'tend') to lean against a singular naming convention: ArmyUnit, Warrior, ArmyPiece. The armyStats sounds correct since its an aggregate of the ArmyUnit (possibly containing multiple units).

Inheritance is great, there is literally no depth to what you can use (as many grandparents as you want [to memory limitations]), the only downside is you can only inherit from one class - it would be quite boggling to use multiple inheritance lol.
Interfaces and Abstracts you will learn through experience are saving graces. They will both provide serious code cutdowns for you. In fact, tack the word 'abstract' in front of your armyUnit class - chances are, you will never be invoking ArmyUnit from a base anymore, only from the child classes. Then you take each of your attributes ($gold, $wood, etc), and you change its scope from private to protected. Protected means that this class (ArmyUnit) and any subclass (warrior) can directly access the attribute without having to use a method (so, warrior can go $this->gold = 0, without having to call $this->setGold(0)).
And thats my rant for now :D

Edit. Lol, completely missed the point of this one ;)
It does seem confusing your right. And best I can see right now, you don't technically need an interface for this example. I would recommend leaving it though, in case you want to create more instances of similar objects that are not quite considered an ArmyUnit. Inheritance is all about expansion, making things easier in the future. If you only have a Warrior piece, and never plan on adding more types of pieces - your right, the work you have is overboard. But if you think you may have more may make more pieces in the future, this is the best method to go by. Waaaayyyy back to your first post, the only thing you need to do is provide the typehinting on the method for its parameter. If you use the interface as the option - ArmyPiece, we know without a doubt that the object given to it has the method required for calling, and don't need to worry about how it gets there.

Does my above discussion help to answer some of your questions?
If not, you can PM me we can discuss more outside of the message board.

aedrin
01-03-2008, 04:42 PM
- why do you make the attributes private? this will force you to write a getXXX method, for each, do you really need that?
- where are the setXXX methods, many times you need to change some values of the attributes after you call the constructor.


Isn't this contradicting?

First you tell the user to use all the OOP techniques that are available, otherwise the benefit is not as great. That's correct.

With these 2 statements however you are first saying you don't want to be writing getXXX statements. Then you ask where all the setXXX attributes are.

You should either use setters/getters, or not. Don't use only one. You only get the full benefit when using both.

oesxyl
01-03-2008, 10:48 PM
Isn't this contradicting?
no, is the same thing as You should either use setters/getters, or not. Don't use only one. You only get the full benefit when using both.

best regards

ralph l mayo
01-04-2008, 01:49 AM
Making attributes private and writing getters and/or setters is better OO-design than using public data.

What are you guys on about re: use both or use none? Make all your data private and use the minimum number of getters and setters possible. It's quite useful to use only one when it's appropriate to expose a representation of some data without allowing it to be changed or, less commonly, when it's appropriate to allow some data to be changed but to hide the internal representation of it from examination from the outside. Encapsulation ftw.

aedrin
01-04-2008, 03:20 PM
Making attributes private and writing getters and/or setters is better OO-design than using public data.

What are you guys on about re: use both or use none? Make all your data private and use the minimum number of getters and setters possible. It's quite useful to use only one when it's appropriate to expose a representation of some data without allowing it to be changed or, less commonly, when it's appropriate to allow some data to be changed but to hide the internal representation of it from examination from the outside. Encapsulation ftw.

What I was getting at is that you should either use both getters and setters, or not at all (i.e. make the variables public). There is little gain from making your variables public and then only writing setter methods (which is what the user was suggesting).


no, is the same thing as You should either use setters/getters, or not. Don't use only one. You only get the full benefit when using both.

You weren't referring to the same thing.


- why do you make the attributes private? this will force you to write a getXXX method, for each, do you really need that?

First you say that you shouldn't make them private and not write getter methods.


- where are the setXXX methods, many times you need to change some values of the attributes after you call the constructor.

Then you ask why the user is not using setter methods.

That sounds contradicting to me.

oesxyl
01-07-2008, 04:34 AM
Making attributes private and writing getters and/or setters is better OO-design than using public data.

What are you guys on about re: use both or use none? Make all your data private and use the minimum number of getters and setters possible. It's quite useful to use only one when it's appropriate to expose a representation of some data without allowing it to be changed or, less commonly, when it's appropriate to allow some data to be changed but to hide the internal representation of it from examination from the outside. Encapsulation ftw.

I don't answer until now to this post first because I was busy and second because I don't want to start a useless discution.

Long story:
we have two rules "reuse the code" and "encapsulate data, let's user access them thru the interface" and most of the programmer obey this rules.
- "reuse the code" => all most 80% can't be used because:
* bed design or very specific, game versus email form
* missing documentation
* hard to use, you must steer on each method to see what it intend to do

- "encapsulate data, let's user access them thru the interface" => useless in many cases:
* programmer tends to modify the classes not inherit, see this forum
* bad access choice
* useless code, don't protect anything

Short story:



class A {
private $x;

function get_x(){
return $this->x;
}
function set_x($ax){
$this->x = $ax;
}
}


what's bad?

1. get_x and set_x don't do anything, checking values, compute, nothing
2. nothing make them more "safe" but you have 6 line more as with public x:



$a = new A();
$a->set_x('what ever I want');
echo $a->get_x();


3. every time you use get_x and set_x, if is not documented, you must go
back and search to see how it work.

multiply this with the number of attributes of each class guess what we have.

I'm not against reuse and encapsulation but IMO you can't learn somebody to write good code if you don't explain why you must sometimes break rules and, and this is the reason I answer.

best regards

oesxyl
01-07-2008, 04:48 AM
Happy new year,



You weren't referring to the same thing.

First you say that you shouldn't make them private and not write getter methods.

Then you ask why the user is not using setter methods.

That sounds contradicting to me.

maybe but the intention was to say what you say. That's why, I replay that is same thing.
Anyway srule_ understand what I say, have setxx now, that's first important thing and you make more clear what I say, that's second. :)

That's all, :)

best regards

srule_
01-07-2008, 04:58 AM
yes, thanks very much for the help :-)

I do understand what I am supposed to be achieving with OOP (reusable code as oesxyl mentioned) however I still have trouble thinking in the OOP mind set resulting in code that does not achieve many of the benefits of OOP. How ever I think I am getting better, and I will post an updated version of my code later for some critique.

Thanks for all the help!

aedrin
01-07-2008, 03:47 PM
Using 'most programmers don't do X' as an argument is a surefire way to look like you have no good experience with OOP.

If used properly (not that many do) it really is a benefit. Every day I save hours of time by reusing my code.

You can't take an existing piece of code, apply OOP and expect to reuse it. You have to abstract things. Make it a generic piece of code. Then for your current project, create an inherited version that has the specifics that you need.

ralph l mayo
01-08-2008, 12:57 AM
- "encapsulate data, let's user access them thru the interface" => useless in many cases:
* programmer tends to modify the classes not inherit, see this forum
* bad access choice


#1 is a problem, which is partly PHP's fault for not implementing final/sealed but mostly a personnel problem if you can't get your team to respect the OO paradigm.

#2 is a non-issue. You choose an access level whether you provide accessors or not, right?



* useless code, don't protect anything



Short story:



class A {
private $x;

function get_x(){
return $this->x;
}
function set_x($ax){
$this->x = $ax;
}
}


what's bad?

1. get_x and set_x don't do anything, checking values, compute, nothing
2. nothing make them more "safe" but you have 6 line more as with public x:

They don't do much now, but they don't hurt anything either.

They don't do nothing, though, they provide insurance against future constraint changes.

If it turns out later on that set_x() does need to check, for example, that x is not zero: behold, there is one, correct, place to insert this check. Drop it in the setter and close the bug ticket. If you allowed direct access to x in the same position you would be faced with trawling through who knows how many lines of client code looking for violations of the non-zero protocol.

Optimizing for line count is not a good use of anyone's time.



3. every time you use get_x and set_x, if is not documented, you must go
back and search to see how it work.

On the contrary, always using get_x() and set_x() is more consistent than sometimes directly interacting with x and sometimes not.

C# and Ruby and others get this right by providing lvalue-eligible methods, which standardize one 'print class.property; class.property = foo;' style even when 'property' is actually a method, but given php the slightly verbose method-call syntax is worth the futureproofing, even if your accessors don't contain any logic.

Fou-Lu
01-08-2008, 01:19 AM
Oy.
Sigh, I hate to recommend this (I'm a accessor/mutator kinda guy myself :P), you can actually force PHP to act similar to a C# property access model.
This is where I mentioned a pure standard for your choice on method naming, I use getX and setX as my names. Err, I can't test this right now, and I cannot remember off hand if its *****y about object function case, but I believe this will still work ok.


public function __get($getWhat)
{
$result = null;
if (method_exists($this, 'get' . $getWhat))
{
$result = call_user_func(array($this, 'get' . $getWhat));
}
else if (isset($this->$getWhat))
{
$result = $this->$getWhat;
}
return $result;
}

public function __set($setWhat, $setParams)
{
if (method_exists($this, 'set' . $setWhat))
{
call_user_func(array($this, 'set' . $setWhat), $setParams);
}
else if (isset($this->$setWhat))
{
$this->$setWhat = $setParams;
}
}

public function __call($callWhat, $callParams)
{
// K, we are here cause the method call doesn't exist:
$doWhat = substr($callWhat, 0, 3);
$attribute = substr($callWhat, 3, strlen($callWhat));
if ($doWhat == 'set')
{
$this->$attribute = $callParams; // This will chain it to __set
return;
}
else if ($doWhat == 'get')
{
return $this->$attribute;
}
throw new Exception('Method: ' . $callWhat . ' not found in class: ' . get_class($this));
}

Hmm, I'll need to check when I get home if thats the shortcut code I use, but it looks pretty close, need to check for the case sensitive since I cannot remember if the oo complains, but if it does, its a simple ucfirst to run. As well, technically you can work around and not use the call_user_func method and go with a variable function, but I do find its more readable. One additional stipulation is required for this to work - The attributes MUST be initialized to something other than null. I know I figured out a way around that one too, but I can't remember what it was >.<. isset will not return true if the value is null, as its the opposite of !is_null.
This is the best of both worlds. Now you can run like so:


$obj = new MyObj();
$obj->setVal('This is my new value');
$obj->val = 'This is my new value, through property accessors!';

If setVal() does not exist, it will pass it to __call and that will trim off the first three characters (set) and pass it into the __set call, or __get if its a getter, and if the direct access of val is executed, it will pass to the __set call, if the setVal method exists it will direct it to the appropriate method.
This way is sort of nice, lets you have the best of both worlds, and allows easy control on the setters for error checking and control.
I'll post back when I get home and confirm that is the way to do it.

EDIT
Oops, missed this (not going to change it but does need mentioning)! The __call method will require that the attribute be in the same case as the object itself. Chances are, you will need to lowercase the first remaining character for the attribute, otherwise it will not find it.



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum