Is it a good idea to have logic inside __constructor?
public class someClass
{
public function __construct()
{
//some logic here
}
So far I thought that it is fine; however, this reddit comment suggests the opposite.
As #Barry wrote, one of the reasons is related to unit-testing, but it's just a side-effect.
Let's take the worst case scenario: you have a "class", which only has a constructor (you probably have seen such examples). So ... why was it even written as a class? You cannot alter it's state, you cannot request it to perform any task and you have no way to check, that it did what you wanted. You could as well used a linear file and just included it. This is just bad.
Now for a more reasonable example: let's assume you have a class, which has some validation checks in the constructor and makes a new DB connection in it. And and then it also has some public methods for performing various tasks
The most obvious problem is the "makes a new DB connection" - there is no way to affect or prevent this operation from outside the class. And that new connection is going off to do who-knows-what (probably loading some configuration and trying to throw exceptions). It also constitutes a hidden dependency, for which you have no indication, without inspecting the class's code.
And there is a similar problem with code, that does validations and/or transformations of passed parameters. It constitutes hidden logic (and thus violating PoLA. It also makes your class harder to extend, because you probably will want to retain some of that validation functionality, while replacing other part. And you don't have that option. Because all of that code gets run whenever you crate a new instance.
Bottom line is this - logic in constructor is considered to be a "code smell". It's not a mortal sin (like using eval() on a global variable), but it's a sign of bad design.
No it isn't a good idea for automated testing. When testing you want to be able to "mock" objects that allow you to control the logic especially in terms of interfaces. So if you place logic in the constructor then it is very hard to test as you must use the real object.
here is a fantastic talk with much more detail on why not to put logic in constructor (google tech talk by Misko Hevery)
https://www.youtube.com/watch?v=RlfLCWKxHJ0
I think this question is little bit unclear because i don't think that __construct is bad place to logic, the question is what kind of logic you have here? Some kind of logic can be placed in constructor but another must not be present in constructor. For example Symfony Response - constructor contains logic, but this logic is necessary for this object, and this constructor doesn't make some implicit actions. This constructor doesn't print content to output or something else - so this is good example (as for me)...
Also it is important to understand what you object must to do, if it will be immutable object - constructor can have little bit another view...
Also it's important to follow SOLID and appropriate design pattern...
I access my MySQL database via PDO. I'm setting up access to the database, and my first attempt was to use the following:
The first thing I thought of is global:
$db = new PDO('mysql:host=127.0.0.1;dbname=toto', 'root', 'pwd');
function some_function() {
global $db;
$db->query('...');
}
This is considered a bad practice. After a little search, I ended up with the Singleton pattern, which
"applies to situations in which there needs to be a single instance of a class."
According to the example in the manual, we should do this:
class Database {
private static $instance, $db;
private function __construct(){}
static function singleton() {
if(!isset(self::$instance))
self::$instance = new __CLASS__;
return self:$instance;
}
function get() {
if(!isset(self::$db))
self::$db = new PDO('mysql:host=127.0.0.1;dbname=toto', 'user', 'pwd')
return self::$db;
}
}
function some_function() {
$db = Database::singleton();
$db->get()->query('...');
}
some_function();
Why do I need that relatively large class when I can do this?
class Database {
private static $db;
private function __construct(){}
static function get() {
if(!isset(self::$db))
self::$db = new PDO('mysql:host=127.0.0.1;dbname=toto', 'user', 'pwd');
return self::$db;
}
}
function some_function() {
Database::get()->query('...');
}
some_function();
This last one works perfectly and I don't need to worry about $db anymore.
How can I create a smaller singleton class, or is there a use-case for singletons that I'm missing in PHP?
Singletons have very little - if not to say no - use in PHP.
In languages where objects live in shared memory, Singletons can be used to keep memory usage low. Instead of creating two objects, you reference an existing instance from the globally shared application memory. In PHP there is no such application memory. A Singleton created in one Request lives for exactly that request. A Singleton created in another Request done at the same time is still a completely different instance. Thus, one of the two main purposes of a Singleton is not applicable here.
In addition, many of the objects that can conceptually exist only once in your application do not necessarily require a language mechanism to enforce this. If you need only one instance, then don't instantiate another. It's only when you may have no other instance, e.g. when kittens die when you create a second instance, that you might have a valid Use Case for a Singleton.
The other purpose would be to have a global access point to an instance within the same Request. While this might sound desirable, it really isnt, because it creates coupling to the global scope (like any globals and statics). This makes Unit-Testing harder and your application in general less maintainable. There is ways to mitigate this, but in general, if you need to have the same instance in many classes, use Dependency Injection.
See my slides for Singletons in PHP - Why they are bad and how you can eliminate them from your applications for additional information.
Even Erich Gamma, one of the Singleton pattern's inventors, doubts this pattern nowadays:
"I'm in favor of dropping Singleton. Its use is almost always a design smell"
Further reading
How is testing the registry pattern or singleton hard in PHP?
What are the disadvantages of using a PHP database class as a singleton?
Database abstraction class design using PHP PDO
Would singleton be a good design pattern for a microblogging site?
Modifying a class to encapsulate instead of inherit
How to access an object from another class?
Why Singletons have no use in PHP
The Clean Code Talks - Singletons and Global State
If, after the above, you still need help deciding:
Okay, I wondered over that one for a while when I first started my career. Implemented it different ways and came up with two reasons to choose not to use static classes, but they are pretty big ones.
One is that you will find that very often something that you are absolutely sure that you'll never have more than one instance of, you eventually have a second. You may end up with a second monitor, a second database, a second server--whatever.
When this happens, if you have used a static class you're in for a much worse refactor than if you had used a singleton. A singleton is an iffy pattern in itself, but it converts fairly easily to an intelligent factory pattern--can even be converted to use dependency injection without too much trouble. For instance, if your singleton is gotten through getInstance(), you can pretty easily change that to getInstance(databaseName) and allow for multiple databases--no other code changes.
The second issue is testing (And honestly, this is the same as the first issue). Sometimes you want to replace your database with a mock database. In effect this is a second instance of the database object. This is much harder to do with static classes than it is with a singleton, you only have to mock out the getInstance() method, not every single method in a static class (which in some languages can be very difficult).
It really comes down to habits--and when people say "Globals" are bad, they have very good reasons to say so, but it may not always be obvious until you've hit the problem yourself.
The best thing you can do is ask (like you did) then make a choice and observe the ramifications of your decision. Having the knowledge to interpret your code's evolution over time is much more important than doing it right in the first place.
Who needs singletons in PHP?
Notice that almost all of the objections to singletons come from technical standpoints - but they are also VERY limited in their scope. Especially for PHP. First, I will list some of the reasons for using singletons, and then I will analyze the objections to usage of singletons. First, people who need them:
- People who are coding a large framework/codebase, which will be used in many different environments, will have to work with previously existing, different frameworks/codebases, with the necessity of implementing many different, changing, even whimsical requests from clients/bosses/management/unit leaders do.
See, the singleton pattern is self inclusive. When done, a singleton class is rigid across any code you include it in, and it acts exactly like how you created its methods and variables. And it is always the same object in a given request. Since it cannot be created twice to be two different objects, you know what a singleton object is at any given point in a code - even if the singleton is inserted to two, three different, old, even spaghetti codebases. Therefore, it makes it easier in terms of development purposes - even if there are many people working in that project, when you see a singleton being initialized in one point in any given codebase, you know what it is, what it does, how it does, and the state it is in. If it was the traditional class, you would need to keep track of where was that object first created, what methods were invoked in it until that point in the code, and its particular state. But, drop a singleton there, and if you dropped proper debugging and information methods and tracking into the singleton while coding it, you know exactly what it is. So therefore, it makes it easier for people who have to work with differing codebases, with the necessity of integrating code which was done earlier with different philosophies, or done by people who you have no contact with. (that is, vendor-project-company-whatever is there no more, no support nothing).
- People who need to work with third-party APIs, services and websites.
If you look closer, this is not too different than the earlier case - third-party APIs, services, websites, are just like external, isolated codebases over which you have NO control. Anything can happen. So, with a singleton session/user class, you can manage ANY kind of session/authorization implementation from third-party providers like OpenID, Facebook, Twitter and many more - and you can do these ALL at the same time from the SAME singleton object - which is easily accessible, in a known state at any given point in whatever code you plug it into. You can even create multiple sessions to multiple different, third-party APIs/services for the SAME user in your own website/application, and do whatever you want to do with them.
Of course, all of this also can be tone with traditional methods by using normal classes and objects - the catch here is, singleton is tidier, neater and therefore because of that manageable/testable easier compared to traditional class/object usage in such situations.
- People who need to do rapid development
The global-like behavior of singletons make it easier to build any kind of code with a framework which has a collection of singletons to build on, because once you construct your singleton classes well, the established, mature and set methods will be easily available and usable anywhere, anytime, in a consistent fashion. It takes some time to mature your classes, but after that, they are rock solid and consistent, and useful. You can have as many methods in a singleton doing whatever you want, and, though this may increase the memory footprint of the object, it brings much more savings in time required for rapid development - a method you are not using in one given instance of an application can be used in another integrated one, and you can just slap a new feature which client/boss/project manager asks just by a few modifications.
You get the idea. Now lets move on to the objections to singletons and
the unholy crusade against something that is useful:
- Foremost objection is that it makes testing harder.
And really, it does to some extent, even if it can be easily mitigated by taking proper precautions and coding debugging routines into your singletons WITH the realization that you will be debugging a singleton. But see, this isnt too different than ANY other coding philosophy/method/pattern that is out there - it's just that, singletons are relatively new and not widespread, so the current testing methods are ending up comparably incompatible with them. But that is not different in any aspect of programming languages - different styles require different approaches.
One point this objection falls flat in that, it ignores the fact that the reasons applications developed is not for 'testing', and testing is not the only phase/process that goes into an application development. Applications are developed for production use. And as I explained in the 'who needs singletons' section, singletons can cut a GREAT deal from the complexity of having to make a code work WITH and INSIDE many different codebases/applications/third-party services. The time which may be lost in testing, is time gained in development and deployment. This is especially useful in this era of third-party authentication/application/integration - Facebook, Twitter, OpenID, many more and who knows what's next.
Though it is understandable - programmers work in very different circumstances depending on their career. And for people who work in relatively big companies with defined departments tending different, defined software/applications in a comfortable fashion and without the impending doom of budget cuts/layoffs and the accompanying need to do a LOT of stuff with a lot of different stuff in a cheap/fast/reliable fashion, singletons may not seem so necessary. And it may even be nuisance/impediment to what they ALREADY have.
But for those who needs to work in the dirty trenches of 'agile' development, having to implement many different requests (sometimes unreasonable) from their client/manager/project, singletons are a saving grace due to reasons explained earlier.
- Another objection is that its memory footprint is higher
Because a new singleton will exist for each request from each client, this MAY be an objection for PHP. With badly constructed and used singletons, the memory footprint of an application can be higher if many users are served by the application at any given point.
Though, this is valid for ANY kind of approach you can take while coding things. The questions which should be asked are, are the methods, data which are held and processed by these singletons unnecessary? For, if they ARE necessary across many of the requests application is getting, then even if you don't use singletons, those methods and data WILL be present in your application in some form or another through the code. So, it all becomes a question of how much memory will you be saving, when you initialize a traditional class object 1/3 into the code processing, and destroy it 3/4 into it.
See, when put this way, the question becomes quite irrelevant - there should not be unnecessary methods, data held in objects in your code ANYway - regardless of you use singletons or not. So, this objection to singletons becomes really hilarious in that, it ASSUMES that there will be unnecessary methods, data in the objects created from the classes you use.
- Some invalid objections like 'makes maintaining multiple database connnections impossible/harder'
I can't even begin to comprehend this objection, when all one needs to maintain multiple database connections, multiple database selections, multiple database queries, multiple result sets in a given singleton is just keeping them in variables/arrays in the singleton as long as they are needed. This can be as simple as keeping them in arrays, though you can invent whatever method you want to use to effect that. But let's examine the simplest case, use of variables and arrays in a given singleton:
Imagine the below is inside a given database singleton:
$this->connections = array(); (wrong syntax, I just typed it like this to give you the picture - the proper declaration of the variable is public $connections = array(); and its usage is $this->connections['connectionkey'] naturally )
You can set up, and keep multiple connections at any given time in an array in this fashion. And same goes for queries, result sets and so forth.
$this->query(QUERYSTRING,'queryname',$this->connections['particulrconnection']);
Which can just do a query to a selected database with a selected connection, and just store in your
$this->results
array with the key 'queryname'. Of course, you will need to have your query method coded for this - which is trivial to do.
This enables you to maintain a virtually infinite number of (as much as the resource limits allow of course) different database connections and result sets as much as you need them. And they are available to ANY piece of code in any given point in any given codebase into which this singleton class has been instantiated.
OF COURSE, you would naturally need to free the result sets, and connections when not needed - but that goes without saying, and it's not specific to singletons or any other coding method/style/concept.
At this point, you can see how you can maintain multiple connections/states to third-party applications or services in the same singleton. Not so different.
Long story short, in the end, singleton patterns are just another method/style/philosophy to program with, and they are as useful as ANY other when they are used in the correct place, in the correct fashion. Which is not different from anything.
You will notice that in most of the articles in which singletons are bashed, you will also see references to 'globals' being 'evil'.
Let's face it - ANYthing that is not used properly, abused, misused, IS evil. That is not limited to any language, any coding concept, any method. Whenever you see someone issuing blanket statements like 'X is evil', run away from that article. Chances are very high that it's the product of a limited viewpoint - even if the viewpoint is the result of years of experience in something particular - which generally ends up being the result of working too much in a given style/method - typical intellectual conservatism.
Endless examples can be given for that, ranging from 'globals are evil' to 'iframes are evil'. Back around 10 years ago, even proposing the use of an iframe in any given application was heresy. Then comes Facebook, iframes everywhere, and look what has happened - iframes are not so evil anymore.
There are still people who stubbornly insist that they are 'evil' - and sometimes for good reason too - but, as you can see, there is a need, iframes fill that need and work well, and therefore the entire world just moves on.
The foremost asset of a programmer/coder/software engineer is a free, open and flexible mind.
Singletons are considered by many to be anti-patterns as they're really just glorified global variables. In practice there are relatively few scenarios where it's necessary for a class to have only one instance; usually it's just that one instance is sufficient, in which case implementing it as a singleton is completely unnecessary.
To answer the question, you're right that singletons are overkill here. A simple variable or function will do. A better (more robust) approach, however, would be to use dependency injection to remove the need for global variables altogether.
In your example you're dealing with a single piece of seemingly unchanging information. For this example a Singleton would be overkill and just using a static function in a class will do just fine.
More thoughts: You might be experiencing a case of implementing patterns for the sake of patterns and your gut is telling you "no, you don't have to" for the reasons you spelled out.
BUT: We have no idea of the size and scope of your project. If this is simple code, perhaps throw away, that isn't likely to need to change then yes, go ahead and use static members. But, if you think that your project might need to scale or be prepped for maintenance coding down the road then, yes, you might want to use the Singleton pattern.
First, I just want to say that I don't find much uses to the Singleton pattern. Why would one want to keep a single object thorough the whole application? Especially for databases, what if I want to connect to another database server? I have to disconnect and reconnect every time...? Anyway...
There are several drawbacks to using globals in an application (which is what the traditional use of the Singleton pattern does):
Difficult to unit test
Dependency injection issues
Can create locking issues (multi-threaded application)
Use static classes instead of a singleton instance provides some of the same drawbacks as well, because the biggest problem of singleton is the static getInstance method.
You can limit the number of instances a class can have without using the traditional getInstance method:
class Single {
static private $_instance = false;
public function __construct() {
if (self::$_instance)
throw new RuntimeException('An instance of '.__CLASS__.' already exists');
self::$_instance = true;
}
private function __clone() {
throw new RuntimeException('Cannot clone a singleton class');
}
public function __destruct() {
self::$_instance = false;
}
}
$a = new Single;
$b = new Single; // error
$b = clone($a); // error
unset($a);
$b = new Single; // works
This will help on the first the points mentioned above: unit testing and dependency injection; while still making sure a single instance of the class exist in your application. You could, per example, just pass the resulting object to your models (MVC pattern) for them to use.
Consider simply how your solution differs from the one presented in the PHP docs. In fact, there is just one "small" difference: your solution provides callers of the getter with a PDO instance, while the one in the docs provides callers of Database::singleton with a Database instance (they then use the getter on that to get a PDO instance).
So what conclusion do we reach?
In the documentation code, callers get a Database instance. The Database class may expose (in fact, it should expose if you 're going to all this trouble) a richer or higher-level interface than the PDO object it wraps.
If you change your implementation to return another (richer) type than PDO, then the two implementations are equivalent. There's no gain to be had from following the manual implementation.
On the practical side, Singleton is a pretty controversial pattern. This is mainly because:
It's overused. Novice programmers grok Singleton much easier than they grok other patterns. They then go on to apply their newfound knowledge everywhere, even if the problem at hand can be solved better without Singleton (when you 're holding a hammer, everything looks like a nail).
Depending on the programming language, implementing a Singleton in an airtight, non-leaky manner can prove to be a titanic task (especially if we have advanced scenarios: a singleton depending on another singleton, singletons that can be destroyed and re-created, etc). Just try to search for "the definitive" Singleton implementation in C++, I dare you (I own Andrei Alexandrescu's groundbreaking Modern C++ Design, which documents much of the mess).
It imposes additional workload both when coding the Singleton and when writing code to access it, workload which you can do without by following a few self-imposed constraints on what you try to do with your program variables.
So, as a final conclusion: your singleton is just fine. Not using Singleton at all is just fine most of the time as well.
Your interpretation is correct. Singletons have their place but are overused. Often, accessing static member functions is sufficient (notably, when you do not need to control time-of-construction in any way). Better, you can just put some free functions and variables in a namespace.
When programming there is not "right" and "wrong"; there is "good practice" and "bad practice".
Singletons are generally created as a class to be reused later. They need to be created in such a way that the programmer doesn't accidentally instantiate two instances while drunkenly coding at midnight.
If you have a simple little class that shouldn't be instantiated more than once, you don't need to make it a singleton. It's just a safety net if you do.
it's not always bad practice to have global objects. If you know that you're going to use it globally/everywhere/all the time, it may be one of the few exceptions. However, globals are generally considered "bad practice" in the same way that goto is considered bad practice.
I don't see any point to this at all. If you implemented the class in such a way that the connection string was taken as a parameter to the constructor and maintained a list of PDO objects (one for each unique connection string) then maybe there would be some benefit, but the implementation of singleton in this instance seems like a pointless exercise.
You are not missing anything, as far as I can see. The example is pretty flawed.
It would make difference, if the singleton class had some non-static instance variables.
In a theoretical database access class, I found that there are quite a few helper functions that I use in the class, which have nothing to do the class's instance (and others, that could be manipulated to be unrelated to the class's instance using dependency injection).
For example, I have a function that gets a string between two other strings in a variable. I've been thinking of moving that to a String_Helper class, or something of the sort. This function has already been made static.
Also, I have a function that queries a database, query($sql). The connection details are provided by the instance, but I've been considering making it static, and using query($sql, $connection). Developers would then be able to call it statically and not need to instantiate the database class at all.
For me, the questions are:
Is it worth it to do something like this? Functions like the query function make me wonder if this is not just me trying to make everything as static as possible, without any real need to. Under what circumstances would you consider this useful?
I know static functions are harder to test, but if I make sure that their code is completely dependency free (or uses dependency injection where necessary), then they're just as easy to test as everything else, surely?
It isn't a concern at the moment, but if, in the future, I decided to extend the classes with the static functions, it would be impossible for me to make the current code use my extended functions. I've thought of Singletons, but the same problem arises: the code would be calling Singleton_Class::getInstance(), and not My_Extended_Singleton_Class::getInstance(). Dependency Injection seems to be the only way to solve this issue, but it might lead to a clunkier API, as every dependency has to be given to an object on __construct().
I have a container class, which holds certain pieces of information statically so that they can be accessed anywhere in the script (global scope). If I can't use static functions or singletons, a class that contained instances of different variables would be great. One could use for example Container::$objects['MyClass'] = $MyClass_object;, and then the rest of the code could just access Container::$objects['MyClass']. If I extended the MyClass class, I could use Container::$objects['MyClass'] = $MyExtendedClass_object;, and the code that used Container::$objects['MyClass'] would use MyExtendedClass, rather than MyClass. This is by far the best way to do it, in my opinion, but I'd like to know what you think about it.
Ok, let me answer these one by one...
1. Is it worth doing something like this
Yes and no. Splitting out the helper functions into their own classes is a good idea. It keeps the "scope" of each of the classes rigidly defined, and you don't get creap. However, don't make a method static just because you can. The query method is there to make your life easier by managing the connection, so why would you want to lose that benefit?
2. They are harder to test
They are not harder to test. Static methods that depend on state are harder to test (that access static member variables or global variables). But static methods in general are just as easy to test as instance methods (in fact, they can be easier since you don't need to worry about instantiation).
3. Extending the classes
This is a valid concern. If you put String_Helper::foo() in the class itself, you'll run into issues. But an option would be to set the name of the string helper as a class variable. So you could then do {$this->stringHelper}::foo() (note, PHP 5.3 only). That way to override the class, all you need to do is change the string helper class in that instance. The Lithium framework does this a lot...
4. Global Registry
I would stay away from this. You're basically just making every class a singleton without enforcing it. Testing will be a nightmare since you're now dependent on global scope. Instead, I'd create a registry object and pass it to classes via the constructor (Dependency Injection). You still accomplish the same thing since you have a store for the objects/classes, but you're no longer dependent on a global scope. This makes testing much easier.
In general
When you're looking at doing things like this, I like to stop when I hit questions like this. Stop and sit down and think *What actual problem am I trying to solve?". Enumerate the problem explicitly. Then pull our your supposed solutions and see if they actually solve them. If they do, then think about the future and if those solutions are really maintainable in the long run (Both from a bug fix standpoint, and with respect to feature additions). Only if you're happy with both of those answers should you even consider doing it. Oh, and also remember to keep it simple. Programming is not about making the most complex, most clever or most amazing solution. It's about making the simplest solution that solves the problem...
I hope that helps...
Good Luck!
I'm obviously brand new to these concepts. I just don't understand why you would limit access to properties or methods. It seems that you would just write the code according to intended results. Why would you create a private method instead of simply not calling that method? Is it for iterative object creation (if I'm stating that correctly), a multiple developer situation (don't mess up other people's work), or just so you don't mess up your own work accidentally?
Your last two points are quite accurate - you don't need multiple developers to have your stuff messed with. If you work on a project long enough, you'll realize you've forgotten much of what you did at the beginning.
One of the most important reasons for hiding something is so that you can safely change it later. If a field is public, and several months later you want to change it so that every time the field changes, something else happens, you're in trouble. Because it was public, there's no way to know or remember how many other places accessed that field directly. If it's private, you have a guarantee that it isn't being touched outside of this class. You likely have a public method wrapped around it, and you can easily change the behavior of that method.
In general, more you things make public, the more you have to worry about compatibility with other code.
We create private methods so that consumers of our classes don't have to care about implementation details - they can focus on the few nifty things our classes provide for them.
Moreover, we're obligated to consider every possible use of public methods. By making methods private, we reduce the number of features a class has to support, and we have more freedom to change them.
Say you have a Queue class - every time a caller adds an item to the queue, it may be necessary to to increase the queue's capacity. Because of the underlying implementation, setting the capacity isn't trivial, so you break it out into a separate function to improve the readability of your Enqueue function. Since callers don't care about a queue's capacity (you're handling it for them), you can make the method private: callers don't get distracted by superfluous methods, you don't have to worry that callers will do ridiculous things to the capacity, and you can change the implementation any time you like without breaking code that uses your class (as long as it still sets the capacity within the limited use cases defined by your class).
It all comes down to encapsulation. This means hiding the insides of the class and just caring about what it does. If you want to have a credit card processing class, you don't really care 'how' it processes the credit card. You just want to be able to go: $creditCardProcessor->charge(10.99, $creditCardNumber); and expect it to work.
By making some methods public and others private or protected, we leave an entry way for others so they know where it is safe to call code from. The public methods and variables are called an 'interface'.
For any class, you have an implementation. This is how the class carries out its duty. If it is a smoothie making class, how the class adds the ingredients, what ingredients it adds, etc are all part of the implementation. The outside code shouldn't know and/or care about the implementation.
The other side of the class it its interface. The interface is the public methods that the developer of the class intended to be called by outside code. This means that you should be able to call any public method and it will work properly.
There are several reasons for using encapsulation, one of the strongest is: Imagine using a large, complicated library written by someone else. If every object was unprotected you could unknowingly be accessing or changing values that the developer never intended to be manipulated in that way.
Hiding data makes the program easier to conceptualize and easier to implement.
It's all about encapsulation. Methods are private that do the inner grunt work while exposing graceful functions that make things easy. E.g. you might have an $product->insert() function that utilizes 4 inner functions to validate a singleton db object, make the query safe, etc - those are inner functions that don't need to be exposed and if called, might mess up other structures or flows you, the developer, have put in place.
a multiple developer situation (don't
mess up other people's work), or just
so you don't mess up your own work
accidentally?
Mainly these two things. Making a method public says "this is how the class is supposed to be used by its clients", making it private says "this is an implementation detail that may change without warning and which clients should not care about" AND forces clients to follow that advice.
A class with a few, well documented public methods is much easier to use by someone who's not familiar with it (which may well be its original author, looking at it for the first time in 6 months) than one where everything is public, including all the little implementation details that you don't care about.
It makes collaboration easier, you tell the users of your classes what parts should not change so often and you can guarantee that your object will be in a meaningful state if they use only public methods.
It does not need to be so strict as distinguishing between private/public/whatever (I mean enforced by the language). For example, in Python, this is accomplished by a naming convention. You know you shouldn't mess with anything marked as not public.
For example - private/protected method may be part of some class which is called in another (public) method. If that part is called in more public methods, it makes sense. And yet you don't want these methods to be called anywhere else.
It's quite the same with class properties. Yes, you can write all-public classes, but whats the fun in that?