Why Directly Accesing property is not recommended in OOPs PHP? - php

If I have a class "person" with a property $name and its getter(get_name()) and setter(set_name()) methods, then after instantiating the objects and setting the property i.e.
$paddy = new person();
$paddy->set_name("Padyster Dave");
echo "Paddy's full name: ".$paddy->name; //WHY THIS IS NOT RECOMMENDED...
In the above code $paddy->name;WHY THIS IS NOT RECOMMENDED
EDIT
Above code is a sample code without assigning any accessifiers.. Its just to understand the $paddy->name concept

The thing that's weird is that you have a setter, but are leaving the property public. (Assuming there's no __get magic going on.)
You usually want to use getters/setters to get more control over what can be assigned to a property and what can't. Or, you may want to execute code when the property is accessed or changed. In either case, you should force the use of the getters/setters by making the property private or protected, otherwise it's pretty pointless. It's about preventing yourself or others that will use the class from shooting their own foot.
If the setter in your example only sets the value without doing anything else, it's superfluous. If it does do something else that is required whenever the value is set, you have a flaw in your class design since it's possible to change the value without using the setter.
class Foo {
public $bar = 0; // is only allowed to contain numeric values
public function setBar($val) {
if (is_numeric($val)) {
$this->bar = $val;
}
}
}
$obj = new Foo();
$obj->bar = 'some value'; // set a string, which is not allowed
If you'd make $bar protected, that wouldn't be possible.

Because you might someday get rid of the $name member, replacing it with (e.g.) $first_name, $last_name and a fullname() method (not that that's a good idea). Of course, with __get and __set, it doesn't matter so much.
More generally, setting a property might not be so simple as storing a value. Giving direct access to member fields can result in other functions causing an object to be in an inconsistent state. Imagine you store an array that needs to remain sorted; if the array were public, something else could assign an unsorted array to the field.

Exposing public fields would be a bad habit.From a good artical about OO principle in PHP
If anything changes with the object, any code that uses it needs to change as well. For instance, if the person's given, family, and other names were to be encapsulated in a PersonName object, you would need to modify all your code to accommodate the change.

Obviously I'm doing 'bad' things too as I use this sort of code all the time.
But what if $this->name (or as I would do $this->nameFormatted) is constructed like:
protected var $name;
$this->name = $this->getSalutation() . ' ' . $this->nameFirst . ' ' . $this->nameLast;
or something along those lines.
You're using $this->name out in the public context, but it's still constructed in the class and if it's protected it won't be overwritten.
Or am I missing the point and the 'bad' thing is actually set-ting the name in the public scope?

Related

Why is it possible to access private variables from outside class by reference?

If I have a public class method that is returning a reference to a non-visible (private or protected) property, I can use that reference to gain direct access:
PHP code
class A
{
private $property = 'orange';
public function &ExposeProperty()
{
return $this->property;
}
public function Output()
{
echo $this->property;
}
}
$obj = new A();
# prints 'orange'
$obj->Output();
$var = &$obj->ExposeProperty();
$var = 'apple';
# prints 'apple'
$obj->Output();
Is there a reasoning behind this functionality in PHP? Or is it just a design oversight, failing to keep track of access violations through references?
It obviously comes in handy when you want to achieve something like:
PHP code
$this->load->resource();
Where load is an object that modifies given properties of $this. But apart from this shortcut, I don't see many possible uses which wouldn't be possible with valid OOP patterns otherwise.
Well, you are explicitly returning a reference to a value. You're locking the front door, but are then opening a side entrance. You are very deliberately taking aim and shooting your own foot here. If $property was an object, and you'd return this object with or without & reference, any modifications to this object would be reflected on $property as well. That's how a reference works, it always modifies the one and only existing value that the reference points to.
Visibility modifiers aren't magic iron clad "protections". There are any number of ways how you can circumvent a private visibility to access and modify the property. They're mostly there as a flag to yourself and other developers that this property should not be accessed directly, it's for internal use and not a publicly sanctioned API. And PHP will slap you on the wrist should you forget that. Nothing more, nothing less.
Also, nothing is really being violated here. Outside code is at no point accessing or modifying $obj->property. That's the only thing private is supposed to prohibit. You're essentially exposing a public API on your object which modifies a private property. Usually this is done with getter and setter functions, but a by-reference API obviously works as well.

Pre-declare all private/local variables?

This may be a basic question, but it has kept me wondering for quite some time now.
Should I declare all private/local variables being private? Or is this only necessary for "important" variables?
For instance, I have the (temporary) result of a calculation. Should I pre-declare this variable?
Hope someone can point this out.
Since you're talking about private, protected and public I take it you're talking about properties, instead of variables.
In that case: yes, you should declare them beforehand.
Because of how PHP objects are designed, an array (properties_table) is created on compile time. This array ensures that accessing a given property is as fast as possible. However, if you add properties as you go along, PHP needs to keep track of this, too. For that reason, an object has a simple properties table, too.
Whereas the first (properties_table) is an array of pointers, the latter is a simple key => value table.
So what? Well, because the properties_table contains only pointers (which are of a fixed size), they're stored in a simple array, and the pointers are fetched using their respective offsets. The offsets are stored in yet another HashTable, which is the ce->properties_info pointer.
As bwoebi pointed out to me in the comments: getting the offset (HashTable lookup) is a worst-case linear operation (O(n)) and predefined property lookups are constant-time complex operations (O(1)). Dynamic properties, on the other hand need another HashTable lookup, a worst-case linear operation (O(n)). Which means that, accessing a dynamic property takes in average about twice as long. Authors of the Wikipedia can explain Time-Complexity far better than I can, though.
At first, access modifiers might seem irrelevant. As you go along, you'll soon find that sometimes, you just don't want to take the chance that some property of some object gets modified by some bit of code. That's when you see the value of private.
If an object contains another object, that holds all sorts of settings that your code will rely upon, for example, you'll probably use a getter method to access those settings from the outside, but you'll leave that actual property tucked away nicely using private.
If, further down the line, you're going to add data models and a service layer to your project, there's a good change you'll write an (abstract) parent class, if only for type-hinting.
If those service instances contain something like a config property, you'll probably define that getter in the parent class (to only define it once). private means that only the current class has access to a property, but since you're not going to have an instance of the parent to work with, but an instance of the child, you'll see why protected is invaluable when dealing with larger projects, too.
As far as temporary variables are concerned, be it in methods, functions or anywhere else, you don't have to predeclare them, except for, in certain cases arrays:
public function foo()
{
$temp = $this->getSomeValue();
return $temp ? $temp +1 : null;
}
Is perfectly valid, and wouldn't work any better if you were to write
public function foo()
{
$temp;// or $temp = null;
$temp = $this->getSomeValue();
return $temp ? $temp +1 : null;
}
However, it's not uncommon to see simething like this:
public function bar($length = 1)
{
for ($i=0;$i<$length;$i++)
{
$return[] = rand($i+1, $length*10);
}
return $return;
}
This code relies on PHP being kind enough to create an array, and assign it to $return when the $return[] = rand(); statement is reached. PHP will do so, but setting your ini to E_STRICT | E_ALL will reveal that it doesn't do so without complaining about it. When passing 0 to the method, the array won't be created, and PHP will also complain when it reaches the return $return; statement: undeclared variable. Not only is it messy, it's also slowing you down! You're better off declaring $return as an array at the top of the scope:
public function bar($length = 1)
{
$return = array();//that's it
for ($i=0;$i<$length;$i++)
{
$return[] = rand($i+1, $length*10);
}
return $return;
}
To be on the safe side, I'd also check the argument type:
/**
* construct an array with random values
* #param int $length = 1
* #return array
**/
public function bar($length = 1)
{
$length = (int) ((int) $length > 0 ? $length : 1);//make length > 0
$return = array();
for ($i=0;$i<$length;$i++)
{
$return[] = rand($i+1, $length*10);
}
return $return;
}
In most if not all cases: yes.
If the variables are class properties they absolutely should be declared before use.
If the variable is local to a function, declare it in that function before you use it. Function variables are confined to the function's scope (local variables). They don't have to be declared before use but it's good practice to do so, and it gets rid of a warning message if you do. If they are not used anywhere else, they should not be properties though,
If you are using it in the context of the whole class, then yes, you should define your variable as a member of the class.
However, if you are talking about a local variable within the context of a single function and the variable does not need to be used elsewhere (or is not returned), then no.
Essentially you need to determine the importance and scope of your variable before deciding whether to make it a class property or not.
For example:
<?php
class Test {
private $test; // Private property, for use in the class only
public $public_test; // Public Property, for use both internally and external to the class as a whole
public function testing() {
$local = 5; // Local variable, not needed outside of this function ever
$this->test = rand(1, 5);
$calc = $local * $this->test; // Local variable, not needed outside of this function ever
$this->public_test = $calc / 2; // The only thing that the whole class, or public use cares about, is the result of the calculation divided by 2
}
}
It's generally a good rule of thumb for variables to define and initialize them before use. That includes not only definition and initial value but also validation and filtering of input values so that all pre-conditions a chunk of code is based on are established before the concrete processing of the data those variables contain.
Same naturally applies to object members (properties) as those are the variables of the whole object. So they should be defined in the class already (by default their value is NULL in PHP). Dynamic values / filtering can be done in the constructor and/or setter methods.
The rule for visibility is similar to any rule in code: as little as necessary (the easy rule that is so hard to achieve). So keep things local, then private - depending if it's a function variable or an object property.
And perhaps keep in the back of your mind that in PHP you can access private properties from within the same class - not only the same object. This can be useful to know because it allows you to keep things private a little bit longer.
For instance, I have the (temporary) result of a calculation. Should I pre-declare this variable?
This is normally a local variable in a function or method. It's defined when it receives the return value of the calculation method. So there is no need to pre-declare it (per-se).
...
function hasCalculation() {
$temp = $this->calculate();
return (bool) $temp;
}
...
If the calculation is/was expensive it may make sense to store (cache) the value. That works easily when you encapsulate that, for example within an object. In that case you'll use a private property to store that value once calculated.
Take these rule with a grain of salt, they are for general orientation, you can easily modify from that, so this is open to extend, so a good way to keep things flexible.

Is PHP class variable definition necessary?

Im new to PHP Object Oriented Programming but I know to code in procedural way.
If this is my PHP Class
<?php
class person {
var $name;
function __construct($persons_name) {
$this->name = $persons_name;
}
function get_name() {
return $this->name;
}
}
?>
and if I access it in my PHP page
$jane = new person("Jane Doe");
echo "Her name is : ".$jane->get_name();
Question:
Is it really necessary to put the var $name; in my PHP class since
I can correctly get an output of Her name is : Jane Doe even without the var $name; in my PHP class?
Not technically, no, PHP is very forgiving to things like this. But it is good practice, if only for documentation purposes.
Probably more importantly, declaring the property explicitly lets you set its visibility. In your example $name is a public property (public is the default visibility in PHP). If you don't need it to be public (it's often safer not to, due to getters/setters allowing better control over what values can be assigned) then you should declare if protected or private.
Semantically, you should, as $name is indeed an attribute of your class. Your constructor already assigns $persons_name to the attribute, but if you left the var $name; out, the rest of your script wouldn't really know that there's such an attribute in your class. Additionally if your constructor didn't assign it right away, person::get_name() would attempt to retrieve an undeclared $name attribute and trigger a notice.
As Brenton Alker says, declaring your class attributes explicitly allows you to set their visibility. For instance, since you have get_name() as a getter for $name, you can set $name as private so a person's name can't be changed from outside the class after you create a person object.
Also, attempting to assign to undeclared class attributes causes them to be declared as public before being assigned.
it is very useful.
imagine you write a bunch of person objects with different names in an array and you will call the names of all objects at another place in your website. this is just possible when you store the name of every particular person.
If i understand correctly, you don't need to declare var $name. You can use PHP's magic methods instead, in this case __set and __get.
Edit: there's a small introduction about magic methods # Nettuts.

Object Oriented PHP Best Practices

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

How do I use PHP's __get() and __set() for defined fields in my class?

I've had a good read of the PHP specs on overloading, and most of the examples appear to be intended to simply allow defining of custom fields (similar to stdClass).
But what about the private fields defined in my class? How should these be retrieved/assigned? I could do a switch on possible values and act on certain values:
class A
{
private $name;
private $age;
public function __get( $var )
{
switch ( $var )
{
case 'name':
return $this->name;
break;
case 'age':
return $this->age+10; // just to do something different ;)
break;
default:
break;
}
}
}
Is this the best method, or is there another generally accepted best practice? (I don't know if it's possible to loop class variables inside a class, but regardless that's not appropriate in most situations since you don't want to return everything.)
I make extensive use of __get() and __set() AND I have my properties declared public. I wanted the best of both worlds, so my IDE could list public properties for me when I type the name of a class instance. How did I get the PHP interceptor methods to work, even though the properties are public and visible outside the class?unset() the properties I want __get() and __set() to be used for in the class __construct().Figuring this method out took a couple evenings of frustration :-)
This would effectively make them public, and usually this gains you nothing over simply using public properties (but you pay performance penalty and have to write more code, risk bugs).
Use that only if you have existing code that uses public property and you suddenly need getter/setter for it (like your example with age).
If you need to execute some code when property is read/written (e.g. make it read-only or lazily fetch from the database), then you should use normal getters/setters (getAge()/setAge()).
I don't see many people using them, but here is what I think.
For retrieving private variables, you probably want to give a list of defined variables that are able to be accessed by the outside. Then, check to see if the requested variable is in that array. If it is, allow it to be changed/gotten. If not, either error or return null.
Honestly, the implementations for this are really case-by-case. If you had a user class that you stored all the info in a single array, you could have $user->name be pulled from $user->account['name'], or something like that.
Also, in a more case-by-case, you could do some modification before giving them values, like hashing a password.

Categories