Variable encapsulation, Set/Get methods are best practices but why do we have a chance to declare a variable public if it's not meant to be used anyway? Would it have been better if variables were always private by default with no chance of making them public since all of the tutorials I read says they should be encapsulated with set/get methods? Is there any valid use case for public variables at least in PHP OOP?
In fact it's just the other way round: Theoretically getters/setters are wrong. The properties defines the state of an object, where the methods defines the behaviour. Getters/Setters only intercept the read and write access to properties, but they break the semantic meaning completely: Now reading the status of an object is a behaviour of the object.
To make properties to look like properties again there is a RFC on the road :)
https://wiki.php.net/rfc/propertygetsetsyntax
Set/Get methods are best practices but why do we have a chance to declare a variable public if it's not meant to be used anyway?
Best practices and not meant to be used is not the same. A language needs to offer different tools for different use-cases and should be consistent.
PHP objects always supported public members and when differentiated visibility was introduced, for backwards compatible reasons public members are very useful.
Would it have been better if variables were always private by default with no chance of making them public since all of the tutorials I read says they should be encapsulated with set/get methods?
That question can not be specifically answered, it's too subjective and there are too many different use-cases that would result in a different answers.
Is there any valid use case for public variables at least in PHP OOP?
Start with backwards compatiblity. If you can not refactor your code but would need to rewrite it completely all the time, this would be very expensive.
let's see..
this's a real world Email API class from CakePHP EmailComponent. to use this class you only need to "set" some property then just send()
$this->Email->to = 'ss#b.co';
$this->Email->from = 'me#b.co';
$this->Email->title = 'xxx';
$this->Email->msg = 'blabla..';
$this->Email->send();
in fact there is a lot of private properties and function inside this class but it's private.
Class has (single) responsibility to do something.
Encapsulation is to publish only what people use to do that thing and keep technical/infrastructure inside as private.
Problem
Suppose you have a class user. You want to be able to return this user object to others so they can use it to extract information using getters. However, you don't want people to be able to readily set the internal state because the internal information should directly relate to a row in the database. Does it make sense to have protected mutators (setters) so that only an extended class could set the variables? Is this a bad practice, irrelevant, overkill or useless?
I have considered trying to limit __construct to one use ( I believe this is sometimes refereed to as a singleton pattern - although I am not sure if I understand entirely. )
I am an amateur programer, forgive any ignorance. Thanks.
Example:
<?php
class user
{
private username;
protected function set_username($username)
{
$this->username = $username;
}
public function get_username()
{
return $this->username;
}
?>
Depends. If nothing in particular needs to happen when the state is changed then you can leave the setters out altogether. Any subclass will have direct access to the properties that are set protected or looser.
If you need something to happen when the state changes (for example having a database UPDATE happen when the state changes) then the setters will make your life a lot easier, as the call to the database updating code be put in the setter. This means if you always go through the setter then the DB will always update when you change the object's state.
So in short, it depends.
If you have a constructor that accepts an id for instance, why would you want to have setters at all. There is no rule forcing you to give an object setters just because it has getters. If your usecase is constructing the object somewhere and after that only use it to extract data from it, simply create no setter at all.
Extending objects can manipulate the protected class variables itself so they don't require any form of setter as well. If you don't want the "outside world" to be able to set something to the class, don't allow it.
Your code is totaly fine and IMHO it encapsulates perfectly. Tt also supports loose coupling.
For easier use, you can add all needed (must have) members as constructor parameters.
Regarding the singleton pattern, use it with care. Users in common aren't singletons. Refer to Refactoring to Patterns (Joshua Kerievsky).
Why shouldn't one leave all methods and attributes accessible from anywhere (i.e. public)?
Can you give me an example of a problem I can run into if I declared an attribute as public?
Think of McDonald's as an object. There's a well known public method to order a BigMac.
Internally there's going to be a few zillion other calls to actually GET the materials for making that Bigmac. They don't want you to know how their supply chain works, so all you get is the public Gimme_a_BigMac() call, and would never ever allow you to get access to the Slaughter_a_cow() or Buy_potatoes_for_fries() methods.
For your own code, that no one will ever see, go ahead and leave everything public. But if you're doing a library for others to reuse, then you go and protect the internal details. That leaves McDonald's free to switch to having Scotty beam over a patty rather than having to call up a Trucking company to deliver the meat by land. The end-user never knows the difference - they just get their BigMac. But internally everything could fundamentally change.
Why shouldn't one leave all methods and attributes accessible from anywhere (i.e. public)?
Because that is far too expensive.
Every public method that I make has to be carefully designed and then approved by a team of architects, it has to be implemented to be robust in the face of arbitrarily hostile or buggy callers, it has to be fully tested, all problems found during testing have to have regression suites added, the method has to be documented, the documentation has to be translated into at least twelve different languages.
The biggest cost of all though is: the method has to be maintained, unchanged, forever and ever, amen. If I decide in the next version that I didn't like what that method did, I can't change it because customers now rely on it. Breaking backwards compatibility of a public method imposes costs on users and I am loathe to do that. Living with a bad design or implementation of a public method imposes high costs on the designers, testers and implementers of the next version.
A public method can easily cost thousands or even tens of thousands of dollars. Make a hundred of them in a class and that's a million dollar class right there.
Private methods have none of those costs. Spend shareholder money wisely; make everything private that you possibly can.
Think of visibility scopes as inner circles of trust.
Take yourself as an example, and think about what activities are public and what are private or protected. There are number of things that you are not delegating for anybody to do on your behalf. There are some that are fine others to trigger and there are some with limited access.
Similarly, in programming, scopes give you tools for creating different circles of trust. Additionally, making things private/protected, give you more control on what's happening. For example, you can allow 3rd-party plugins that can extend some of your code, while they can be limited to the scope of how far they can go.
So, to generalize, scopes give you the extra level of security and keeps things more organized that they would be otherwise.
Because that violates the concept of encapsulation, a key tenet of OOP.
A risk you run, you say?
<?php
class Foo
{
/**
* #var SomeObject
*/
public $bar;
}
Your code states that $bar should contain an object instanceof SomeObject. However, anyone using your code could do
$myFoo->bar = new SomeOtherObject();
... and any code relying on Foo::$bar being a SomeObject would break. With getters and setters and protected properties, you can enforce this expectation:
<?php
class Foo
{
/**
* #var SomeObject
*/
protected $bar;
public function setBar(SomeObject $bar)
{
$this->bar = $bar;
}
}
Now you can be certain that any time Foo::$bar is set, it will be with an object instanceof SomeObject.
By hiding implementation details, it is also preventing an object from getting into an inconsistent state.
Here is an contrived example of a stack (pseudo code).
public class Stack {
public List stack = new List();
public int currentStackPosition = 0;
public String pop() {
if (currentStackPosition-1 >= 0) {
currentStackPosition--;
return stack.remove(currentStackPosition + 1);
} else {
return null;
}
}
public void push(String value) {
currentStackPosition++;
stack.add(value);
}
}
If you make both variables private the implementation works fine. But if public you can easily break it by just setting an incorrect value for currentStackPosition or directly modifying the List.
If you only expose the functions you provide a reliable contract that others can use and trust. Exposing the implementation just make it a thing that might work of nobody messes with it.
Encapsulation is not needed in any language, but it's useful.
Encapsulation is used to minimise the number of potential dependencies with the highest probability of change propagation also it helps preventing inconsistencies :
Simple example: Assume we made a Rectangle class that contained four variables - length, width, area, perimeter. Please note that area and perimeter are derived from length and width (normally I wouldn't make variables for them), so that changing length would change both area and perimeter.
If you did not use proper information hiding (encapsulation), then another program utilizing that Rectangle class could alter the length without altering the area, and you would have an inconsistent Rectangle. Without encapsulation, it would be possible to create a Rectangle with a length of 1 and a width of 3, and have an area of 32345.
Using encapsulation, we can create a function that, if a program wanted to change the length of the rectangle, that the object would appropriately update its area and perimeter without being inconsistent.
Encapsulation eliminates the possibilities for inconsistency, and shifts the responsibility of staying consistent onto the object itself rather than a program utilizing it.
However at the same time encapsulation is sometimes a bad idea, and motion planning and collision (in game programming) are areas where this is particularly likely to be the case.
the problem is that encapsulation is fantastic in places where it is needed, but it is terrible when applied in places where it isn’t needed like when there are global properties that need to be maintained by a group of encapsulation, Since OOP enforced encapsulation no matter what, you are stuck. For example, there are many properties of objects that are non-local, for example, any kind of global consistency. What tends to happen in OOP is that every object has to encode its view of the global consistency condition, and do its part to help maintain the right global properties. This can be fun if you really need the encapsulation, to allow alternative implementations. But if you don’t need it, you end up writing lots of very tricky code in multiple places that basically does the same thing. Everything seems encapsulated, but is in fact completely interdependent.
Well, in fact you can have everything public and it doesn't break encapsulation when you state clearly, what is the contract, the correct way to use objects. Maybe not attributes, but methods are often more hidden than they have to be.
Remember, that it is not you, the API designer, that is breaking the encapsulation by making things public. It is the users of the class that can do so, by calling internal methods in their application. You can either slap their hands for trying to do so (i.e. declaring methods private), or pass the responsibility to them (e.g. by prefixing non-API methods with "_"). Do you really care whether someone breaks his code by using your library the other way you advice him to do? I don't.
Making almost everything private or final -- or leaving them without API documentation, on the other hand -- is a way of discouraging extendability and feedback in open source. Your code can be used in a ways you even didn't think of, which might not be the case when everything is locked (e.g. sealed-by-default methods in C#).
The only problem you can run into is that people will see you as "uncool" if you don't use Private or Protected or Abstract Static Final Interface or whatever. This stuff is like designer clothes or Apple gadgets - people buy them not because they need to, but just to keep up with others.
Yes, encapsulation is an important theoretical concept, but in the practice "private" and friends rarely make sense. They might make some sense in Java or C#, but in a scripting language like PHP using "private" or "protected" is sheer stupid, because encapsulation is invented to be checked by a compiler, which doesn't exist in PHP. More details.
See also this excellent response and #troelskn and #mario comments over here
The visibility is just something that you can use for your own good, to help you not break your own code. And if you use it right, you will help others (who are using your code) that don't break their own code (by not using your code right).
The simplest, widely known example, in my opinion is the Singleton pattern. It's a pattern, because it's a common problem. (Definition of pattern from Wikipedia:
is a formal way of documenting a solution to a design problem
Definition of the Singleton pattern in Wikipedia:
In software engineering, the singleton pattern is a design pattern used to implement the mathematical concept of a singleton, by restricting the instantiation of a class to one object. This is useful when exactly one object is needed to coordinate actions across the system.
http://en.wikipedia.org/wiki/Singleton_pattern
The implementation of the pattern uses a private constructor. If you don't make the constructor private, anyone could mistakenly create a new instance, and break the whole point of having only one instance.
You may think that the previous answers are "theoretical", if you use public properties in Doctrine2 Entities, you break lazy loading.
To save you from yourself!
There's been some excellent answers above, but I wanted to add a bit. This is called principle of least privilege. With less privilege, less entities have authority to break things. Breaking things is bad.
If you follow the principle of least privilege, the principle of least knowledge (or Law of Demeter) and single responsibility principle aren't far behind. Since your class you wrote to download the latest football scores has followed this principle, and you have to poll it's data instead of it being dumped straight to your interface, you copy and paste the whole class into your next project, saving development time. Saving development time is good.
If you're lucky, you'll be coming back to this code in 6 months to fix a small bug, after you've made gigaquads of money from it. Future self will take prior self's name in vain for not following the above principles, and he will fall victim to a violation of the principle of least astonishment. That is, your bug is a parse error in the football score model, but since you didn't follow LOD and SRP, you're astonished at the fact that you're doing XML parsing inline with your output generation. There are much better things in life to be astonished by than the horrificness of your own code. Trust me, I know.
Since you followed all the principles and documented your code, you work two hours every Thursday afternoon on maintenance programming, and the rest of the time surfing.
I'm just getting started with OOP PHP with PHP Object-Oriented Solutions by David Powers, and am a little curious about the notion of protection in OOP.
The author clearly explains how protection works, but the bit about not wanting others to be able to change properties falls a bit flat. I'm having a hard time imagining a situation where it is ever possible to prevent others from altering your classes, since they could just open up your class.php and manually tweak whatever they pleased seeing as how PHP is always in plain text.
Caution: all of the above written by a beginner with a beginner's understanding of programming.
From yourself!
You use various levels of protection to indicate how you want a class to be used. If a class member is protected or private, it can only be accessed by the class itself. There's no chance you can screw up the value of that member accidentally from "external" code (code outside the class).
Say you have a class member that is only supposed to contain numbers. You make it protected and add a setter which checks that its value can only be numeric:
class Foo {
protected $num = 0;
public function setNum($num) {
if (!is_int($num)) {
throw new Exception('Not a number!!!');
}
$this->num = $num;
}
}
Now you can be sure that Foo::$num will always contain a number when you want to work with it. You can skip a lot of extra error checking code whenever you want to use it. Any time you try to assign anything but a number to it, you'll get a very loud error message, which makes it very easy to find bugs.
It's a restriction you put on yourself to ease your own work. Because programmers make mistakes. Especially dynamically typed languages like PHP let you silently make a lot of mistakes without you noticing, which turn into very hard to debug, very serious errors later on.
By its very nature, software is very soft and easily degrades into an unmaintainable Rube Goldberg logic machine. OOP, encapsulation, visibility modifiers, type hinting etc are tools PHP gives you to make your code "harder", to express your intent of what you want certain pieces of your code to be and enable PHP to enforce this intent for you.
Protected is not really protecting from anyone to change the source code, but is just a class method visibility in PHP OOP
Class members declared public can be accessed everywhere. Members declared protected can be accessed only within the class itself and by inherited and parent classes. Members declared as private may only be accessed by the class that defines the member.
They mean they are protected in different ways...
Private variables are not visible to anywhere except from within the class.
Protected variables are not visible to the instantiated object, but are visible to classes which inherit from that class, as well as the class itself.
Nothing stops another programmer from opening a class file and changing the access modifiers.
The hiding of data is a good thing because the less you expose, the more you can control and less bugs you can potentially introduce.
I'm currently working on an oophp application. I have a site class which will contain all of the configuration settings for the app. Originally, I was going to use the singleton pattern to allow each object to reference a single instance of the site object, however mainly due to testing issues involved in this pattern, I've decided to try a different approach.
I would like to make the site class the main parent class in my app and call it's constructor from within the constructors of the child classes, in order to make all the properties available whenever needed.
When run for the first time, the class will only contain the db details for the app. To get the remaining values a query must be performed using the db details. However, any subsequent instances will be clones of the original (with all values). I may also set a Boolean flag to perform the query again a completely new instance is required.
Would this be a viable alternative to the singleton and would it solve the testing issues it causes? This is all theory atm, I haven't started to code anything yet,
Any thoughts or advice greatly appreciated.
Thanks.
I think a better way is to have an 'configuration' object that will get passed to the constructors of all your other classes. So, almost something like a singleton, except it's explicitly created and passed only to classes that need it. This approach is usually called dependency injection.
After trying many different techniques, what I have found functional and reliable is this method:
Use a bootstrap, or initialization file. It is located in the ROOT of the site with the proper permission and safe-guards against direct access.
All pages in the site first include this file. Within it, I create all my global objects (settings, user), and reference them from there.
For example:
// OBJECT CREATION
$Config = new Configuration();
$User = new User();
Then within classes that require these objects:
public function __construct($id = NULL) {
global $Config; // DEPENDENCY INJECTION SOUNDS LIKE AN ADDICTION!
if($Config->allow_something) {
$this->can_do_something = true;
}
if(NULL !== $id) {
$this->load_record($id);
}
}
Notice that I just access these global objects from within the class, and how I don't have to include the object variables as the first constructor parameter each and every time. That gets old.
Also, having a static Database class has been very helpful. There are no objects I have to worry about passing, I can just call $row = DB::select_row($sql_statement);; check out the PhpConsole class.
UPDATE
Thanks for the upvote, whoever did that. It has called attention to the fact that my answer is not something I am proud of. While it might help the OP accomplish what they wanted, it is NOT a good practice.
Passing objects to new object constructors is a good practice (dependency injection), and while "inconvenient," as with other things in life, the extra effort is worth it.
The only redeeming part of my answer is use of the facade pattern (eg. DB::select_row()). This is not necessarily a singleton (something the OP wanted to avoid), and gives you an opportunity to present a slimmed down interface.
Laravel is a modern PHP framework that uses dependency injection and facades, among other proven design patterns. I suggest that any novice developer review these and other such design practices thoroughly.