I could find the default visibility of a property and a method in the PHP manual. But i couldn't find any info regarding the class itself.
My guess is that it's public. But if someone could link to the part where this is written in the manual i would appreciate it.
Simply Put
Public. PHP doesn't support anything other than public classes.
Unlike Java/.NET/etc, there isn't any concept of packages, assemblies, internal or nested classes. Namespaces are essentially just syntactic sugar to avoid IncrediblyLongClassNames, and can't provide any actual changes to visibility.
The entire idea makes much less sense in a non-compiled language, since regardless of what scope you use, anyone could still just take your class and declare it in public.
A PHP 7 Proviso: Anonymous Classes
PHP 7 introduced the concept of anonymous classes*, allowing on-the-fly class definitions. As a very basic example:
<?php
$foo = new class {
public function hello($what)
{
echo 'Hello ', $what, PHP_EOL;
}
};
(new $foo)->hello('world');
# Hello world
Because these can be assigned to variables, they can be limited to the scope of that variable, and passed around like any other.
Unlike most language that allow anonymous classes, in PHP they do not inherit anything from the scope in which they are defined. The linked documentation has some examples of how to work around this, by defining the anonymous class as inheriting from a parent or passing in constructor arguments.
*Strictly speaking, under the hood they do have names, and as such if someone can run get_class() on an instance then they can then instantiate their own copy, since they aren't garbage collected.
PHP are always public "by default", but the most accurate answer here is that PHP classes don't have such concept anyway.
Related
I would like to believe that I understand the concept of static/early binding vs late/dynamic binding as well as late static binding but I found some conflicting definitions after reading few articles about it.
From my understanding the following:
<?php
class A {
protected $greeting = 'Hello from A';
public function hello() {
echo $this->greeting;
}
}
$obj = new A();
$obj->hello();
is an example of static or early binding which happens at compile time (even though PHP is interpreted language). It is early binding because all information about the class is known & nothing needs to be dynamically figured out, so class & method binding happens at compile time.
Dynamic binding or also known as late binding happens at runtime where class & method binding happens at runtime. If we take the same example as above but use something like inheritance, that would be late or dynamic binding:
<?php
class B extends A {
protected $greeting = 'Hello from B';
}
$obj = new B();
$obj->hello();
so my question is, is my assumption/understanding of static/dynamic binding correct in PHP? I know there is also late static binding which combines static & late binding and makes static properties & methods work with inheritance, so instead of using self:: you would use static:: which would wait for runtime to do the binding.
For reference, these are the articles I've read after having doubts about my own understanding of this concept:
This article states that
Static binding happens when you use the scope resolution operator ::.
but per my understanding that is not always the case, isn't my example above the one without inheritance a version of static binding as well? Static in terms of binding does not necessarily mean static variables.
The following articles are the ones with conflicting information, so this is why I am kind of confused & want to know whether I understand it correctly & if my examples are correct or not. I could not find the original RFC on PHP to get more insight as to how exactly this works.
https://www.codeproject.com/Articles/853792/A-Walk-Through-Into-Late-Static-Binding-in-PHP
https://joshduck.com/blog/2010/03/19/exploring-phps-static-scoping/
https://blog.julien-maury.dev/en/php-late-static-binding/
Which one of these articles is more on point as to how binding really works in PHP?
... is an example of static or early binding which happens at compile time (even though PHP is interpreted language).
You've managed to fit quite a lot of confusion into one sentence here.
Firstly, PHP is a compiled language, it is just compiled "on demand", into a high-level intermediate representation. What's more relevant is that PHP is a highly dynamic language, which doesn't do very much analysis during compilation.
Secondly, the example code you show could be optimised to a known method at compile-time, but it might not be. As far as the language is concerned, the statement $obj->hello(); is evaluated at run-time based on the current value of $obj. The fact that you can see the class to use on the line above, and know that that class has no parents, doesn't mean the compiler will definitely know those things and compile the code differently.
Thirdly, "early" and "static" can't just be used as synonyms - otherwise, the term "late static binding" would mean "late early binding", and make no sense. A "static" call is one that references a particular class; a "non-static" call is one which references an instance.
The important difference from the user's point of view is that given these three lines of code:
$someObject->methodOne();
self::methodTwo();
static::methodThree();
The definition of methodOne used will be whichever class $someObject is an instance of at the time that code runs. It might be a different method each time the line of code runs, if $someObject has a different value. This is late binding.
It will also reference the specific instance in $someObject, placing it in the magic variable $this. It is a non-static call.
The definition of methodTwo used will be the one in the class where that line of code is written. Every time that line of code runs, it will reference the same class. This is early binding.
The definition of methodThree used will depend on how the code was called - if it was called with the name of a child class with its own version of methodThree, that version will be used. Like methodOne, the line might run a different method each time. This is late binding.
Both methodTwo and methodThree will only reference a class, not an instance. They will not populate the magic variable $this. They are static calls.
yes your understanding is correct, because after creating class B and extending it from A, there two different versions of function hello(), which one is called at runtime depends on the type of object(A or B - to be determined by the context) calling it. Another way to look at it is that it is polymorphism.
This question already has answers here:
Are private constants possible in PHP? [duplicate]
(4 answers)
Why doesn't PHP permit private const?
(2 answers)
Closed 8 years ago.
Why doesn't PHP permit private constants?
I am aware that there are workarounds, such as using a private static property instead.
However, from an OOP or software design perspective, what was the reasoning?
tl;tr
What was the reasoning to not implement private constants?
This is a good question.
Did they really consider this?
I don't know.
When searching through the PHP internals mailing list, i found nothing about this topic.
Unless a internal's member speaks up, we'll never know.
With regard to the history of the language - a bit 1:1 C method wrapping, some bits from Perl (regexp), some bits Java (oop) - it's possible that this idea popped up, while looking for new language features.
I would relate the concept of a "private constant" to VisualBasic or Java. I doubt that VB has a big or any influence on PHP. VB allows the definition of "private constants" in "Modules" - it's the default access scope. Visual Basic doesn't allow constants in Interfaces and Namespaces (but PHP does).
PHP might include some OOP concepts from Java, but there is one big difference: constants are variables in Java. Their access modifiers / visibility levels are: "public, private, final and static". A private constant declaration looks like this: "private static final String MYCONST = "My Constant"; It's OOP - end of story. PHP constant access feels more hackish compared to that - BUT it's more simple and you still have the workaround at hand.
The first comment in the PHP manual for Class Constants is:
It may seem obvious, but class constants are always publicly visible.
They cannot be made private or protected. I do not see it state that
in the docs anywhere.
Why is this obvious? "Why is a class constant public by default and not private?"
Maybe, it's a missing language feature, because not all class members can be hidden properly.
And he is right, when you come from Java or VB to PHP this question pops up.
Let's take a look at the PHP spec. The current state of implementation in PHP is: class constants are always public and static. So, again and again, thumbs up for Facebook for writing such detailed document: the author considered different visibility or access-control levels.
Let's take a look at interface, class, constant and visibility:
How does the concept "const" differ from "private static"?
The static variable can be changed, the constant cannot be changed.
You cannot assign the runtime value of a function to a const (const A = sprintf('foo %s', 'bar');), but to a private static var.
An interface might have constants - they cannot be overridden.
A class might have a constant - which might be overridden by a inheriting class/interface.
There is also an OOP pattern called "constant interface pattern" - it describes the use of an interface solely to define constants, and having classes implement that interface in order to achieve convenient syntactic access to those constants.
An interface is provided so you can describe a set of functions and then hide the final implementation of the functions in an implementing class. This allows you to change the implementation of the functions, without changing how you use it. Interfaces exist to expose an API.
And by defining constants in an interface and implementing the interface by a class, the constants become part of the API. In fact, you are leaking implementations details into the API. That's why some consider this being an anti-pattern, among them Joshua Bloch (Java).
Now, let's try to combine some concepts and see if they fit.
Let's pretend we try to avoid the critique from above, then you need to introduce a syntax, which allows qualified access to the constant, but hides the constant in the API. You could come up with "Access control" via visibility levels: "public, private, protected, friend, foe". The goal is to prevent the users of a package or class from depending on unnecessary details of the implementation of that package or class. It is all about hiding implementation details, right?
What about "private constants" in "interfaces"?
That would actually solve the critique from above, right?
But the combination of interface with "private", doesn't make sense. The concepts are contrary.
That's why interface do not allow "private" access/visibility-levels.
And a "private" constant in an "interface" would be mutually exclusive, too.
What about "private constants" in "classes"?
class a {
/*private*/ const k = 'Class private constant k from a';
}
class b extends a
{
const k = 'Overridden private constant a::k with Class constant k from b';
const k_a = parent::k;
// fatal error: self-referencing constant
#const k_selfref = self::k . ' + ' . self::k_selfref;
// fatal error: "static::" is not allowed in compile-time constants
#const k_staticref = static::k;
}
// direct static access would no longer work, if private
// you need an instance of the parent class or an inheriting class instance
echo a::k;
echo b::k;
echo b::k_a;
$obj_b = new b;
echo $obj_b::k;
echo $obj_b::k_a;
Is there a benefit?
The private constant in the class wouldn't be exposed in the API. This is good OOP.
The access to the parent constant from outside would be a class and/or inheritance access.
echo a::k, which now works - could respond with "Fatal error: Trying to access a private constant without a class instance or inheritance.".
(This might still work solely at compile-time, if there is no run-time value assignment to a const. But i'm not sure about this one.)
Are there caveats?
We would lose direct static access to constants.
Requiring that an instance of a class is created, just to access constants, is a waste of resources. Direct static access saves resources and is simple. If we introduce private, that's lost and the access would be bound to the instance.
A "private const" is implicitly a "private static const". The access operator is still "::".
A possible follow-up change would be the switch to implicitly non-static constants.
That's a BC break.
If you switch the default behavior to non-static, the access operator changes from "::" to "->".
This establishes a proper OOP object access to constants, which is comparable to Java's concept of "constants as variables with access level". This would work a bit like this: http://3v4l.org/UgEEm. The access operator changes to static, when the constant is declared as "public static const", right?
Is the benefit good enough to implement it?
I don't know. It's up for discussion.
I like both: the const static access, because it's dead simple and the concept of "constants as variables" and proper access levels.
After that's implemented, in order to save resources and keep going fast, everyone starts to (re-)declare "public static const", to drop the instance requirement and violate OOP ;)
And btw: i found an HHVM overflow, while experimenting with code of this answer.
Why doesn't PHP permit private constants?
In PHP constants are part of the interface and the interface is public, always (that's what an interface is for).
See as well PHP Interfaces.
I'm pretty sure this is the reason design-wise.
Regarding the comment under your question that someone wants to reduce the visibility of constants to change them later, I'd say this sounds more like a variable than a constant which does not change it's value. It's constant.
Starting a new PHP project and deciding that after a few years of PHP development, I'm thinking I should really start using PHP classes. I'm used to classes in the C++ world, so there's a few things I'm not quite sure about when porting this knowledge over to PHP.
In C++, you can automatically access any class variables without a prefix, in PHP, it appears that you need to prefix all such accesses (variables and function) with this->. I know what this is (or at least I think so, a pointer to the current class instance), but I'm not sure whether its required or preferred, or if there is any alternatives. My class will be using other functions within the same class (ie, itself) fairly heavily, so having to type this-> every time is going to get time consuming quite quickly.
The classes themselves are likely to be singletons, so I'm not sure whether to actually use a class, or just prefix the functions with an identifier.
It is required that you reference the object to which the member belongs in order to access the member.
Every method call or property access is prefixed with $variable-> - $this is a magic variable that refers to the current object instance. Its use is not optional.
This is (amongst other reasons) because not every function in PHP is a method, there are also global functions. If you reference a function without associating it with an object, it is assumed to be a global function.
As a side note, you should avoid the use of singletons in PHP - there is no performance/memory gain to be found from using them because each concurrently executing script is garden-walled into its own memory space.
The "pointer" (->) != C++ pointer.
$this means the current class and instance. All variables are accessed by using $this->variable; or $this->function();.
Static variables, and functions can be accessed using self::$variable or self::function()
Outside the class instance, you must indicate the class instance: $foo->variable; or $foo->function();
As far as I know, there is no way to access public/private/static/constant variables inside the class without using $this-> or self::
In reference to using an object of functions... up to you. Are you planning on expanding the code later to add more functions? Are all the functions somewhat related? If they are singleton functions, there is no harm in just writing a function instead of a class. It really just depends on what you are trying to accomplish.
Yes, you do have to use $this when accessing class method's or variables.
You need to remember that PHP doesn't require that variables be declared, so image the following situation:
<?
class A {
public $a = 'Hello World!';
function hello() {
$a = 'hello';
echo $a;
}
}
$object = new A();
echo $object->hello();
$a would be local scope and $this->a would be the class variable.
I found out that object constants in PHP always have public visibility so it is not possible to set them to protected or private like this:
<?php
class MyClass {
protected const constant = "this won't work";
}
?>
What's the explanation for this? I can't think of a good reason to force constants to be public.
That's a rather philosophical question, which is discussed in the comments for Class constants in the PHP Manual. The argument seems to be that Visibility identifies who has the right to change members, not who has the right to read them. Since constants cannot be changed, there is no point in having them support visibility when visibility is understood as access modifiers. If you follow that argumentation or go with the linked feature request below your question is up to you.
I can't think of a good reason to force constants to be public.
Well, constants are static definitions, bound to the class and not instantiated objects. They can be addressed only using classname::constname, and they cannot be altered. It stands to reason they are part of the blueprint of a class, and thus it doesn't really make sense to apply visibility rules to them.
That's just my rather subjective opinion, though. Interested to see whether anything based on hard OOP theory comes up.
Is there any advantage to using __construct() instead of the class's name for a constructor in PHP?
Example (__construct):
class Foo {
function __construct(){
//do stuff
}
}
Example (named):
class Foo {
function Foo(){
//do stuff
}
}
Having the __construct method (first example) is possible since PHP 5.
Having a method with the same name as the class as constructor (second example) is possible from PHP version 4 until version 7.
I agree with gizmo, the advantage is so you don't have to rename it if you rename your class. DRY.
Similarly, if you have a child class you can call
parent::__construct()
to call the parent constructor. If further down the track you change the class the child class inherits from, you don't have to change the construct call to the parent.
It seems like a small thing, but missing changing the constructor call name to your parents classes could create subtle (and not so subtle) bugs.
For example, if you inserted a class into your heirachy, but forgot to change the constructor calls, you could started calling constructors of grandparents instead of parents. This could often cause undesirable results which might be difficult to notice.
Also note that
As of PHP 5.3.3, methods with the same name as the last element of a namespaced class name will no longer be treated as constructor. This change doesn't affect non-namespaced classes.
Source: http://php.net/manual/en/language.oop5.decon.php
__construct was introduced in PHP5. It is the way you are supposed to do it now. I am not aware of any advantages per se, though.
From the PHP manual:
For backwards compatibility, if PHP 5 cannot find a __construct() function for a given class, it will search for the old-style constructor function, by the name of the class. Effectively, it means that the only case that would have compatibility issues is if the class had a method named __construct() which was used for different semantics
If you're on PHP5 I would recommend using __construct to avoid making PHP look elsewhere.
The main advantage I see for __construct, is that you don't have to rename your constructor if you change your class name.
Today, the accepted answer is obsolete.
Renaming classes is bad practice: you have to remember what and where to rename everytime you upgrade to newer version. Sometimes (like using Reflection or complex dependence structure) it can be impossible without radical refactoring. And this is accidental complexity you want to avoid. That's why namespaces were introduced into PHP. Java, C++ or C# don't use __construct, they use named constructor and there's no issue with them.
As of PHP 5.3.3, methods with the same name as the last element of a namespaced class name will no longer be treated as constructor. This change doesn't affect non-namespaced classes.
Example
namespace Foo;
class Test {
var $a = 3;
function Test($a) {
$this->a = $a;
}
function getA() {
return $this->a;
}
}
$test = new Test(4);
echo $test->getA(); // 3, Test is not a constructor, just ordinary function
Note that named constructors are not deprecated (PHP 5.5 today). However, you can't predict that your class won't be used in namespace, therefore __construct should be preffered.
Clarification about the bad practice mentioned above (for Dennis)
Somewhere in your code you could use ReflectionClass::getName(); when you rename the class, you need to remember where you used Reflection and check if the getName() result is still consistent in your app. The more you need to remember something specific, the more likely something is forgotten which results in bugs in the app.
The parents can't have control about all the classes in the world which depends on them. If allow_url_include is enabled, some other web might be using the class from your server, which may crash if you rename some class. It is even worse in compiled languages mentioned above: the library can be copied and bundled in other code.
There is no reason why to rename class:
if the class name conflicts, use namespaces
if the class responsibility shifts, derive some other class instead
In PHP classes in namespace, the method with the same name should be avoided anyway: intuitively it should produce an object created the class; if it does something else, why to give it the same name? It should be a constructor and nothing else. The main issue is that the behavior of such a method depends on namespace usage.
There is no issue with __construct constructors in PHP. But it wasn't the smartest idea to alter the named constructors.
The best advantage of using __contruct() instead of ClassName() is when extending classes. It is much easier to call parent::__construct() instead of parent::ClassName(), as it is reusable among classes and the parent can be changed easily.
In your example Foo::Foo is sometimes called a PHP 4 or old-style constructor because it comes from the days of PHP 4:
class Foo {
// PHP 4 constructor
function Foo(){
//do stuff
}
}
PHP 4 constructors will be deprecated but not removed in PHP 7. They will be no longer be considered as constructors in any situation in PHP 8. Future compatibility is definitely a big reason to not use this feature.
Well it has been a few years since this question was asked, but I think I have to answer this one still, because things has changed and for readers in the future I want to keep the information up to date!
So in php-7 they will remove the option to create the constructor as a function with the same name as the class. If you still do it you will get a E_DEPRECATED.
You can read more about this proposal (the proposal is accepted) here:
https://wiki.php.net/rfc/remove_php4_constructors
And a quote from there:
PHP 7 will emit E_DEPRECATED whenever a PHP 4 constructor is defined. When the method name matches the class name, the class is not in a namespace, and a PHP 5 constructor (__construct) is not present then an E_DEPRECATED will be emitted. PHP 8 will stop emitting E_DEPRECATED and the methods will not be recognized as constructors.
Also you won't get a E_STRICT in php-7 if you define a method with the same name as the class AND a __construct().
You can see this also here:
PHP 7 will also stop emitting E_STRICT when a method with the same name as the class is present as well as __construct.
So I would recommend you to use __construct(), since you will have less issues with this in the future.
In PHP 5 the advantage would be that performance would be better. It will look for a constructor by the name of __construct first and if it doesn't find that, it will look for constructors by the name of className. So if it finds a constructor by the name __construct it does not need to search for a constructor by the name className.
Forward compatibility. There's always a chance that legacy code that's left in the language for backwards compatibility's sake will be removed in a future version.
If there is methods __construct and SameAsClassName method then __construct will be executed, SameAsClassName method will be skipped.
I think that the main reason is that is the language convention.
You don't need to force a language to act like someone else.
I mean, in Objective-C you prefix the constructors with -init, for example. You can make your own constructor using your class name but why? Are ther some reason to use this schema instead of the language convention?