Say I have a class which represents a person, a variable within that class would be $name.
Previously, In my scripts I would create an instance of the object then set the name by just using:
$object->name = "x";
However, I was told this was not best practice? That I should have a function set_name() or something similar like this:
function set_name($name)
{
$this->name=$name;
}
Is this correct?
If in this example I want to insert a new "person" record into the db, how do I pass all the information about the person ie $name, $age, $address, $phone etc to the class in order to insert it, should I do:
function set($data)
{
$this->name= $data['name'];
$this->age = $data['age'];
etc
etc
}
Then send it an array? Would this be best practice? or could someone please recommend best practice?
You should have setter/getter methods. They are a pain but you don't necessarily have to write them yourself. An IDE (for example Eclipse or Netbeans) can generate these for you automatically as long as you provide the class member. If, however, you don't want to deal with this at all and you're on PHP5 you can use its magic methods to address the issue:
protected $_data=array();
public function __call($method, $args) {
switch (substr($method, 0, 3)) {
case 'get' :
$key = strtolower(substr($method,3));
$data = $this->_data[$key];
return $data;
break;
case 'set' :
$key = strtolower(substr($method,3));
$this->_data[$key] = isset($args[0]) ? $args[0] : null;
return $this;
break;
default :
die("Fatal error: Call to undefined function " . $method);
}
}
This code will run every time you use a nonexistent method starting with set or get. So you can now set/get (and implicitly declare) variables like so:
$object->setName('Bob');
$object->setHairColor('green');
echo $object->getName(); //Outputs Bob
echo $object->getHairColor(); //Outputs Green
No need to declare members or setter/getter functions. If in the future you need to add functionality to a set/get method you simply declare it, essentially overriding the magic method.
Also since the setter method returns $this you can chain them like so:
$object->setName('Bob')
->setHairColor('green')
->setAddress('someplace');
which makes for code that is both easy to write and read.
The only downside to this approach is that it makes your class structure more difficult to discern. Since you're essentially declaring members and methods on run time, you have to dump the object during execution to see what it contains, rather than reading the class.
If your class needs to declare a clearly defined interface (because it's a library and/or you want phpdoc to generate the API documentation) I'd strongly advise declaring public facing set/get methods along with the above code.
Using explicit getters and setters for properties on the object (like the example you gave for set_name) instead of directly accessing them gives you (among others) the following advantages:
You can change the 'internal' implementation without having to modify any external calls. This way 'outside' code does not need change so often (because you provide a consistent means of access).
You provide very explicitly which properties are meant to be used / called from outside the class. This will prove very useful if other people start using your class.
The above reasons is why this could be considered best practice although it's not really necessary to do so (and could be considered overkill for some uses ; for example when your object is doing very little 'processing' but merely acts as a placeholder for 'data').
I perfectly agree with CristopheD (voted up). I'd just add a good practice when creating a new person.
Usually, a use a constructor which accept the mandatory fields and set the default values for the optional fields. Something like:
class Person
{
private $name;
private $surname;
private $sex;
// Male is the default sex, in this case
function Person($name, $surname, $sex='m'){
$this->name = $name;
$this->surname = $surname;
$this->sex = $sex;
}
// Getter for name
function getName()
{
return $this->name;
}
// Might be needed after a trip to Casablanca
function setSex($sex)
{
$this->sex = $sex;
}
}
Obviously, you could use the setter method in the constructor (note the duplicate code for the sex setter).
To go full OOP, you should do something similar to:
class User {
private $_username;
private $_email;
public function getUsername() {
return $this->_username;
}
public function setUsername($p) {
$this->_username = $p;
}
...
public function __construct() {
$this->setId(-1);
$this->setUsername("guest");
$this->setEmail("");
}
public function saveOrUpdate() {
System::getInstance()->saveOrUpdate($this);
}
}
If you want to save a user, you just create one, assign its values using Setters and do $user->saveOrUpdate(), and have another class to handle all the saving logic.
As a counterpoint to ChristopheD's answer, if your instance variable is strictly for private use, I wouldn't bother with writing a getter & setter, and just declare the instance variable private.
If other objects need to access the object, you can always add a getter. (This exposes another problem, in that other classes might be able to change the object returned by the getter. But your getter could always return a copy of the instance variable.)
In addition using a getter/setter also shields other parts of the same class from knowing about its own implementation, which I've found very useful on occasion!
From a more general point of view both direct access ($person->name) and accessor methods ($person->getName) are considered harmful. In OOP, objects should not share any knowledge about their internal structure, and only execute messages sent to them. Example:
// BAD
function drawPerson($person) {
echo $person->name; // or ->getName(), doesn't matter
}
$me = getPersonFromDB();
drawPerson($me);
// BETTER
class Person ....
function draw() {
echo $this->name;
}
$me = getPersonFromDB();
$me->draw();
more reading: http://www.javaworld.com/javaworld/jw-09-2003/jw-0905-toolbox.html
Related
I have these classes:
class User{
private $user_ID;
private $first_name;
private $surname;
...
private $website;
private $company;
function __construct($array){
$this->user_ID = $array["userId"];
$this->first_name = $array["first"];
$this->surname = $array["last"];
$this->telephone = $array["tele"];
...
}
public function addWebsite($array){
$this->website = $array;
}
public function addCompany($array){
$this->company = $array;
}
public function getData(){
$array = array();
foreach($this as $var => $value) {
$array[$var] = $value;
}
return $array;
}
}
class Website{
private $webId;
private $url;
private $description;
...
function __contruct($array){
$this->webId = $array["webId"];
$this->url = $array["url"];
$this->description = $array["desc"];
...
}
}
the getData() method in User is exactly the same for the Website class.
so how can i get the website class to implement this method? But ONLY the getData() method
While inheritance forms an behaves-as relationship, this is not a situation for Inheritance. Your Website is not related to the User in any way, so there shouldn't be a relationship between them.
Having base classes like suggested elsewhere here will quickly lead to monolithic architecture and god objects. Those in turn lead to less maintainability, high coupling, fragile code and hampers reuse. Likewise, making everything public or resorting to similar means that defeat information hiding and widen the public API lead to similar problems and you will want to avoid them.
What you are looking for is Traits, but these are only supported as of PHP 5.4. The easiest approach is really just to duplicate that method in both classes. Keep in mind that you usually want to avoid code duplication, but in this case its the lesser evil over the other suggested alternatives.
A viable alternative would be to use an Introspection Service that uses Reflection to fetch the data from the object into an array. Although in general, you should put methods on the objects having the data the methods operate on.
if you are using php5.4 you can use traits instead of classes. It´s solve the cases witch you need the implementation of one method in two diferents classes.
To make it type save you can define an interface for example "arraySerializable" which has the getData method. You can use this interface later in TypeHints instead of the class.
But this still doesn't give you the functionality. I suppose a common base class is not the thing you want here. So if you can't use traits you have to duplicate the code. This might be one of the rare cases where some lines duplicated code is ok.
Make another class that only has the getData method, and make both of your existing classes extend that new class.
If you do not have Traits there was an older implementation of Mixins that you could use.
You may know that:
<?php
class A {
public function B() {
var_dump($this->data);
}
}
class X {
protected $data;
public function Y() {
A::B()
}
}
$x = new X;
$x->Y(); // will execute the code for A::B
// but will assume the object context
// of $x (of class X) and will have
// access to $this->data
// ! this is not a static call
Using this principle you can create a static array of class names and/or method names that you can "mix-in" or "use" (like traits) via the magic method __get.
?>
As opposed to the other answerers, I think I should comment on your design. You want to create a method that exposes all private properties of any object. An object is, in most cases, somewhat more than simply a property bag, so in what situations would you need to know all properties? And why do you then mark them as private?
To solve the real problem, you should take a look at public properties, or private ones with getters and setters if you want to control the incoming and outgoing data.
If you however think you need all properties of a given object (and are willing to accept "hacks" like copypaste-programming, traits and whatnot), why not simply mark them as public and call get_object_vars()?
I want to set initial values of fields in an object, using $config. Which approach is better in terms of cleaner and more maintainable code?
Also, I would like to add that object will be initialized in a factory and not directly by client.
1. I pass $config to the object
<?php
class UserGreeting {
private $config;
public function __construct($config){
$this->config=$config;
}
public function greetings(){
echo 'Hello, '.$this->config->get('username');
}
}
?>
Pros:
Easy to pass multiple parameters
Cons:
The class is coupled with $config ( is it?). What I mean is that
apart from particular $config interface and parameters naming
conventions, I can't just plug this class into another program
without introducing $config
Client code doesn't have to know which parameters are used by the
object, but that is more general thought
2. I set fields manually outside the object
<?php
class UserGreetingFactory{
public function __construct($config){
$this->config=$config;
}
public function getUserGreeting(){
$userGreeting=new UserGreeting();
$userGreeting->setUserName='John Doe';
return $userGreeing;
}
}
class UserGreeting {
private userName;
public function setUserName($userName){
$this->userName=$userName;
}
public function greetings(){
echo "Hello, {$this->userName}";
}
}
?>
Pros:
The class doesn't care where his parameters are coming from
Can reuse easily
Easier to test(is it?). I mean that I don't have to deal with setting
up $config
Cons:
Factory\Builder has to know which parameers to pass
Lots of extra code for setters and passing parameters
First solution with ctor injection. But instead of a special config i would just pass the actual objects. In your case an User object.
<?php
class UserGreeting
{
private $user;
public function __construct(User $user)
{
$this->user = $user;
}
public function greet()
{
printf('Hello, %s!', $this->user->getName());
}
}
Considering your idea's, I'd stick to a single variable. If you want to pass the variables per-method you'll have a lot of excessive code.
From an OOP point of view, you shouldn't put it in a single variable. An object has properties. An username is in fact a property so you should use it as property. That means that in PHP classes you'd need to make it a public variable and set the variables when you create the object.
The first way is better because of dependency injection. This code will be easier to test and to maintain.
The third way is to use Visitor pattern to inject dependencies.
You could use a static class with static methods. In effect they are like CONSTS, but you can enforce all kinds of rules within the static config class - that they conform to an interface for example.
Config::getUserName();
That way if you are going to be faced with a family of config objects, you can be assured they all have at least an entry for each expected value - otherwise a warning is chucked.
Might depend on your situation of course, and I expect there are many situations where you would not want to do this - but I will offer it up all the same.
I'm currently needing to extend a class to add functionality to it (I do not have access to the base class to modify it), and I'm running into an isssue with it.
Basically, I need the magic getter function to return a set of private variables if they are requested, but otherwise default to the default behaviour. I need these properties to be private so as to use the magic setter function to automatically sync some data.
That said, here's some example code:
class newClass extends baseClass {
private $private1;
private $private2;
...
public function __get($name) {
if($name == 'private1') return $this->private1;
if($name == 'private2') return $this->private2;
... (and so on)
// and here, it should default back to it's default behavior (throwing
// an error on getting invalid/inaccessable property, etc.)
// I cannot just use property_exists, because there may or may not be
// private variables in the base class that should not be exposed.
}
public function __set($name,$val) {
// I use this to do some automatic syncing when the two private variables
// above are set. This needs to be triggered, hence the private variables
// in the first place.
}
}
I know, I could use getProperty/setProperty functions, but I would like this to remain as intuitive as possible, despite the argument that performing such operations is counter-intuitive. The two private properties are very much connected to each other. When one of them is set, it is logically going to affect the others.
As of right now, this is the only logical way I can think of to avoid getter/setter functions and maintain the closely bonded sync between properties. If you guys can think of anything else that may be a viable solution, feel free to suggest options :)
PHP does not have a property builtin like other languages, __get and __set are indeed what you should use here. But it's a bit more work to accomplish therefore.
Your problem seems to be property_exists foremost. It's not easily possible to determine the publicity of properties from within the class (except with introspection). But you can use get_object_vars to filter out private variables from the base class at least:
function __get($name) {
static $r; if (!isset($r)) { $r = new ReflectionClass($this); }
if (($p = $r->getProperty($name)) and $p->isPublic()) {
return $this->$name;
}
elseif (method_exists($this, "get_$name")) {
return $this->{"get_$name"}();
}
else trigger_error("inaccessible property ->$name", E_USER_NOTICE);
}
For reverting back to default behaviour the best you can do is to manually output an error message.
Don't do this, use getter/setters. They are exactly the same amount of work as what you are doing here.
What is encapsulation with simple example in php?
Encapsulation is just wrapping some data in an object. The term "encapsulation" is often used interchangeably with "information hiding". Wikipedia has a pretty thorough article.
Here's an example from the first link in a Google search for 'php encapsulation':
<?php
class App {
private static $_user;
public function User( ) {
if( $this->_user == null ) {
$this->_user = new User();
}
return $this->_user;
}
}
class User {
private $_name;
public function __construct() {
$this->_name = "Joseph Crawford Jr.";
}
public function GetName() {
return $this->_name;
}
}
$app = new App();
echo $app->User()->GetName();
?>
Encapsulation is protection mechanism for your class and data structure. It makes your life much easier. With Encapsulation you have a control to access and set class parameters and methods. You have a control to say which part is visible to outsiders and how one can set your objects parameters.
Access and sett class parameters
(Good Way)
<?php
class User
{
private $gender;
public function getGender()
{
return $this->gender;
}
public function setGender($gender)
{
if ('male' !== $gender and 'female' !== $gender) {
throw new \Exception('Set male or female for gender');
}
$this->gender = $gender;
}
}
Now you can create an object from your User class and you can safely set gender parameters. If you set anything that is wrong for your class then it will throw and exception. You may think it is unnecessary but when your code grows you would love to see a meaningful exception message rather than awkward logical issue in the system with no exception.
$user = new User();
$user->setGender('male');
// An exception will throw and you can not set 'Y' to user gender
$user->setGender('Y');
(Bad Way)
If you do not follow Encapsulation roles then your code would be something like this. Very hard to maintain. Notice that we can set anything to the user gender property.
<?php
class User
{
public $gender;
}
$user = new User();
$user->gender = 'male';
// No exception will throw and you can set 'Y' to user gender however
// eventually you will face some logical issue in your system that is
// very hard to detect
$user->gender = 'Y';
Access class methods
(Good Way)
<?php
class User
{
public function doSomethingComplex()
{
$this->doThis(...);
...
$this->doThat(...);
...
$this->doThisExtra(...);
}
private function doThis(...some Parameters...)
{
...
}
private function doThat(...some Parameters...)
{
...
}
private function doThisExtra(...some Parameters...)
{
...
}
}
We all know that we should not make a function with 200 line of code instead we should break it to some individual function that breaks the code and improve the readability of code. Now with encapsulation you can get these functions to be private it means it is not accessible by outsiders and later when you want to modify a function you would be sooo happy when you see the private keyword.
(Bad Way)
class User
{
public function doSomethingComplex()
{
// do everything here
...
...
...
...
}
}
Encapsulation is the mechanism that binds together code and the data it manipulates, and keeps both safe from outside interference and misuse. The wrapping up of data and methods into a single unit (called class) is known as encapsulation. The benefit of encapsulating is that it performs the task inside without making you worry.
Encapsulation is a way of storing an object or data as a property within another object, so that the outer object has full control over what how the internal data or object can be accessed.
For example
class OuterClass
{
private var $innerobject;
function increment()
{
return $this->innerobject->increment();
}
}
You have an extra layer around the object that is encapsulated, which allows the outer object to control how the inner object may be accessed. This, in combination with making the inner object/property private, enables information hiding.
/* class that covers all ATM related operations */
class ATM {
private $customerId;
private $atmPinNumber;
private $amount;
// Verify ATM card user
public function verifyCustomer($customerId, $atmPinNumber) {
... function body ...
}
// Withdraw Cash function
public function withdrawCash($amount) {
... function body ...
}
// Retrieve mini statement of our account
public function miniStatement() {
... function body ...
}
}
In the above example, we have declared all the ATM class properties (variables) with private access modifiers. It simply means that ATM class properties are not directly accessible to the outer world end-user. So, the outer world end-user cannot change or update them directly.
The only possible way to change a class property (data) is a method (function). That’s why we have declared ATM class methods with public access modifier. The user can pass the required arguments to a class method to do a specific operation.
It means users do not have whole implementation details for ATM class. It’s simply known as data hiding.
Reference:
http://www.thecreativedev.com/php-encapsulation-with-simple-example/
People seem to be mixing up details of object orientation with encapsulation, which is a much older and wider concept. An encapsulated data structure
can be passed around with a single reference, eg increment(myDate)
rather than increment(year,month,day)
has a set of applicable operations stored in a single program unit
(class, module, file etc)
does not allow any client to see or manipulate its sub-components
EXCEPT by calling the applicable operations
You can do encapsulation in almost any language, and you gain huge benefits in terms of modularisation and maintainability.
Wrapping up data member and method together into a single unit (i.e. Class) is called Encapsulation.
Encapsulation is like enclosing in a capsule. That is enclosing the related operations and data related to an object into that object.
Encapsulation is like your bag in which you can keep your pen, book etc. It means this is the property of encapsulating members and functions.
<?php
class YourMarks
{
private $mark;
public Marks
{
get { return $mark; }
set { if ($mark > 0) $mark = 10; else $mark = 0; }
}
}
?>
I am giving an another example of real life (daily use) that is “TV operation”. Many peoples operate TV in daily life.
It is encapsulated with cover and we can operate with remote and no need to open TV and change the channel.
Here everything is in private except remote so that anyone can access not to operate and change the things in TV.
The opposite of encapsulation would be something like passing a variable to every method (like a file handle to every file-related method) or global variables.
Encapsulation is the process of hidding the data of the object from outside world and accessed to it is restricted to members of the class.
Encapsulation: - wrapping of data in single unit. also we can say hiding the information of essential details.
Example: You have a mobile phone.... there it some interface which helps u to interact with cell phone and u can uses the services of mobile phone. But the actually working in cell phone is hide. u don't know how it works internally.
Simply I prefer that is visibility of your class's property and method. For example-
- public
- private
- protected
Let's take a look real life example for encapsulation.
class MyClass{
private $name;
public function showName($newName){
$this->name = $newName;
return $this->name;
}
}
//instantiate object
$obj = new MyClass();
echo $obj->showName("tisuchi");
In this case, encapsulation means, we restrict some properties. Like, name property, we can not access from outside of the class. On the other hand, we can access public function entitled showName() with one private parameter.
Simply what I prefer of encapsulation is-
visibility of your property and method.
Although, if you have any intension to understand encapsulation further, I refer to my special tutorial based on encapsulation.
http://tisuchi.com/object-oriented-php-part-3-encapsulation-php/
Hope, it will make your concept more clear. Have fun!
In basic terms, it’s the way we define the visibility of our properties and methods. When you’re creating classes, you have to ask yourself what properties and methods can be accessed outside of the class. Let’s say we had a property named foo. If a class extends your class, is it allowed to manipulate and access foo? What if someone creates an instances of your class? Are they allowed to manipulate and access foo?
Encapsulation is just how you wanted your objects/methods or properties/variables to be visible in your application.
for example, :
class ecap {
public $name;
private $id;
protected $tax;
}
If you want to access private or protected properties, then you have to use getter and setter methods in your class that will be accessible from outside of your class. Meaning, you cannot access your private or protected properties directly from outside of your class but you can use through any methods. Let’s take a look-
in the class, add the following method:
class ecap
{
public function userId(){
return $this->id;
}
}
and we can access it like:
$obj = new ecap();
echo $obj->userId();
Wrapping up of data inside single unit is called encapsulation. Means class members such as method and properties binds together inside a class to avoid accessibility from outside.This is done by making variables and functions of class private.
Another approach for encapsulation with function (without class) + usage of "use"(optional), to use outer variables inside encapsulation function
<?php
$abc = 'ABC';
// Encapsulation Function
(function () use ($abc){
echo $abc; // prints ABC
$xyz = 'XYZ';
})();
echo $xyz; // warning: undefined
I'm going to try something with the format of this question and I'm very open to suggestions about a better way to handle it.
I didn't want to just dump a bunch of code in the question so I've posted the code for the class on refactormycode.
base class for easy class property handling
My thought was that people can either post code snippets here or make changes on refactormycode and post links back to their refactorings. I'll make upvotes and accept an answer (assuming there's a clear "winner") based on that.
At any rate, on to the class itself:
I see a lot of debate about getter/setter class methods and is it better to just access simple property variables directly or should every class have explicit get/set methods defined, blah blah blah. I like the idea of having explicit methods in case you have to add more logic later. Then you don't have to modify any code that uses the class. However I hate having a million functions that look like this:
public function getFirstName()
{
return $this->firstName;
}
public function setFirstName($firstName)
{
return $this->firstName;
}
Now I'm sure I'm not the first person to do this (I'm hoping that there's a better way of doing it that someone can suggest to me).
Basically, the PropertyHandler class has a __call magic method. Any methods that come through __call that start with "get" or "set" are then routed to functions that set or retrieve values into an associative array. The key into the array is the name of the calling method after getting or setting. So, if the method coming into __call is "getFirstName", the array key is "FirstName".
I liked using __call because it will automatically take care of the case where the subclass already has a "getFirstName" method defined. My impression (and I may be wrong) is that the __get & __set magic methods don't do that.
So here's an example of how it would work:
class PropTest extends PropertyHandler
{
public function __construct()
{
parent::__construct();
}
}
$props = new PropTest();
$props->setFirstName("Mark");
echo $props->getFirstName();
Notice that PropTest doesn't actually have "setFirstName" or "getFirstName" methods and neither does PropertyHandler. All that's doing is manipulating array values.
The other case would be where your subclass is already extending something else. Since you can't have true multiple inheritances in PHP, you can make your subclass have a PropertyHandler instance as a private variable. You have to add one more function but then things behave in exactly the same way.
class PropTest2
{
private $props;
public function __construct()
{
$this->props = new PropertyHandler();
}
public function __call($method, $arguments)
{
return $this->props->__call($method, $arguments);
}
}
$props2 = new PropTest2();
$props2->setFirstName('Mark');
echo $props2->getFirstName();
Notice how the subclass has a __call method that just passes everything along to the PropertyHandler __call method.
Another good argument against handling getters and setters this way is that it makes it really hard to document.
In fact, it's basically impossible to use any sort of document generation tool since the explicit methods to be don't documented don't exist.
I've pretty much abandoned this approach for now. It was an interesting learning exercise but I think it sacrifices too much clarity.
The way I do it is the following:
class test {
protected $x='';
protected $y='';
function set_y ($y) {
print "specific function set_y\n";
$this->y = $y;
}
function __call($function , $args) {
print "generic function $function\n";
list ($name , $var ) = split ('_' , $function );
if ($name == 'get' && isset($this->$var)) {
return $this->$var;
}
if ($name == 'set' && isset($this->$var)) {
$this->$var= $args[0];
return;
}
trigger_error ("Fatal error: Call to undefined method test::$function()");
}
}
$p = new test();
$p->set_x(20);
$p->set_y(30);
print $p->get_x();
print $p->get_y();
$p->set_z(40);
Which will output (line breaks added for clarity)
generic function set_x
specific function set_y
generic function get_x
20
generic function get_y
30
generic function set_z
Notice: Fatal error: Call to undefined method set_z() in [...] on line 16
#Brian
My problem with this is that adding "more logic later" requires that you add blanket logic that applies to all properties accessed with the getter/setter or that you use if or switch statements to evaluate which property you're accessing so that you can apply specific logic.
That's not quite true. Take my first example:
class PropTest extends PropertyHandler
{
public function __construct()
{
parent::__construct();
}
}
$props = new PropTest();
$props->setFirstName("Mark");
echo $props->getFirstName();
Let's say that I need to add some logic for validating FirstNames. All I have to do is add a setFirstName method to my subclass and that method is automatically used instead.
class PropTest extends PropertyHandler
{
public function __construct()
{
parent::__construct();
}
public function setFirstName($name)
{
if($name == 'Mark')
{
echo "I love you, Mark!";
}
}
}
I'm just not satisfied with the limitations that PHP has when it comes to implicit accessor methods.
I agree completely. I like the Python way of handling this (my implementation is just a clumsy rip-off of it).
Yes that's right the variables have to be manually declared but i find that better since I fear a typo in the setter
$props2->setFristName('Mark');
will auto-generate a new property (FristName instead of FirstName) which will make debugging harder.
I like having methods instead of just using public fields, as well, but my problem with PHP's default implementation (using __get() and __set()) or your custom implementation is that you aren't establishing getters and setters on a per-property basis. My problem with this is that adding "more logic later" requires that you add blanket logic that applies to all properties accessed with the getter/setter or that you use if or switch statements to evaluate which property you're accessing so that you can apply specific logic.
I like your solution, and I applaud you for it--I'm just not satisfied with the limitations that PHP has when it comes to implicit accessor methods.
#Mark
But even your method requires a fresh declaration of the method, and it somewhat takes away the advantage of putting it in a method so that you can add more logic, because to add more logic requires the old-fashioned declaration of the method, anyway. In its default state (which is where it is impressive in what it detects/does), your technique is offering no advantage (in PHP) over public fields. You're restricting access to the field but giving carte blanche through accessor methods that don't have any restrictions of their own. I'm not aware that unchecked explicit accessors offer any advantage over public fields in any language, but people can and should feel free to correct me if I'm wrong.
I've always handled this issue in a similar with a __call which ends up pretty much as boiler plate code in many of my classes. However, it's compact, and uses the reflection classes to only add getters / setters for properties you have already set (won't add new ones). Simply adding the getter / setter explicitly will add more complex functionality. It expects to be
Code looks like this:
/**
* Handles default set and get calls
*/
public function __call($method, $params) {
//did you call get or set
if ( preg_match( "|^[gs]et([A-Z][\w]+)|", $method, $matches ) ) {
//which var?
$var = strtolower($matches[1]);
$r = new ReflectionClass($this);
$properties = $r->getdefaultProperties();
//if it exists
if ( array_key_exists($var,$properties) ) {
//set
if ( 's' == $method[0] ) {
$this->$var = $params[0];
}
//get
elseif ( 'g' == $method[0] ) {
return $this->$var;
}
}
}
}
Adding this to a class where you have declared default properties like:
class MyClass {
public $myvar = null;
}
$test = new MyClass;
$test->setMyvar = "arapaho";
echo $test->getMyvar; //echos arapaho
The reflection class may add something of use to what you were proposing. Neat solution #Mark.
Just recently, I also thought about handling getters and setters the way you suggested (the second approach was my favorite, i.e. the private $props array), but I discarded it for it wouldn't have worked out in my app.
I am working on a rather large SoapServer-based application and the soap interface of PHP 5 injects the values that are transmitted via soap directly into the associated class, without bothering about existing or non-existing properties in the class.
I can't help putting in my 2 cents...
I have taken to using __get and __set in this manor http://gist.github.com/351387 (similar to the way that doctrine does it), then only ever accessing the properties via the $obj->var in an outside of the class. That way you can override functionality as needed instead of making a huge __get or __set function, or overriding __get and __set in the child classes.