Why do these lines of code execute successfully - php

I'm very familiar with OOP in C++ and Java and I'm new to it in PHP, afterall PHP claims to support OOP. I'm refactoring some codes given to me in my internship and I came across the following style of coding, in PHP.
<?php
class A {
public function echoVar(){
$this->__();
echo $this->var;
}
}
class B extends A{
function __(){
$this->var = 1;
}
}
$v = new B();
$v->echoVar();
Following my experience with C++ and especially Java, this wouldn't even try to compile, but the execution is fine in PHP. I understand that all languages aren't the same but why does PHP support this style. Is this style good or bad practices? how is this OOP?
With my knowledge, the following are what I think is wrong with this code.
var is not a defined attribute of the class B, and yet was accessed and given a value.
How/Why did super class A have access to method __ of subclass B without casting or abstraction.
I would ask how class A got access to the attribute var but the attribute itself was created out of magic. On a serious note, why did it have access to var.
I'm a OOP newbie in PHP, so please help me clarify these things.

This is an example of, uhm, not so great coding. First, I would suggest activating strict error reporting (E_ALL | E_STRICT | E_NOTICE).
If an class/object property which hasn't been declared before, is assigned a value, it is going to be created as public property of the object. However, with strict error reporting, you'd get thrown an E_NOTICE.
Although the __ belongs to the B class, it can be called from A, when B is instantiated. The method is not declared as public/protected/private, so it's public by default, therefore accessible by parents/children as well as from the outside.
Of course, this is generally poor coding style, at least A would demand the implementation of __ in child classes with the following line: abstract public function __();.
Last, but not least, the function name __ is against PHP conventions, as methods starting with two underscores are reserved.

I would describe PHP as a language that tends to make assumptions when things are unclear, whereas C++ and Java are languages that force you to explicitly write everything out, or else they will throw errors.
Question #1 - In PHP you do not explicitly need to declare class properties in order to be able to assign them later, as you have discovered. Obviously though, if you immediately tried to echo $this->var; inside a class without assigning it, it would be undefined.
Question #2 - So this one's a little weird, but basically, if you create a superclass from a subclass, and you call a method inside a method defined in the subclass, the superclass version will get called. So even though __() is not defined in A, it is in defined in B, so if you create an A object, and called echoVar(); you will get a message about the method __() is undefined, you can still call echoVar(); in an object of type B, as __(); is defined there.
Question #3 - Similar to #2, even when used in the subclass, the superclass version of variables will be used.
I personally would try to never use this style of coding, however. As I'm sure you're already aware, it's not a good idea to make a class dependent on its superclass like that. It would be better to explicitly declare these things.
As for how it is OOP, the code you posted is primarily using objects as opposed to free floating functions or lines of code.

Related

Static/Early binding vs Dynamic/Late binding in PHP

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.

Why does PHP support calling static functions as non-static member methods?

Code beforehand fully valid code from 5.0.0 (without E_STRICT or E_DEPRECATED)
class A{
static public function b() {
}
public function c(){
$this->b();
}
}
$d = new A();
$d->c();
$d->b();
It's looks like inconsistent behaviour because you cannot use static properties from instance.
The PHP way is to steal and borrow from other languages whenever
possible ...
But I cannot find any programming language that supports similar behavior.
Why does PHP support it? What is the point of calling static methods as non-static?
Some explanation from support: Expected behavior
Actually, C++ and Java support this. It seems the PHP developers, after discussion, decided on implementation to match them.
After a bit of digging, I found this thread from February 2004, which is essentially their discussion about the implementation choices. Important tidbits from the discussion:
From Cristiano Duarte:
C++ allows $a->bar() when bar() is a static method (yes, it is called
in a static context there too).
IMO, there should be no error, warning or notice here.
I Agree. PHP is fine the way it is.
From Art:
Regardless of the final implementation, I think access to static methods and
static class variables should be consistent. Currently, you cannot access a
class variable via an object instance.
And for what it's worth, I see no reason why static methods cannot be called
from objects. Follow Java/C++ in this case.
Ultimately, a final decision From Wez:
Please drop this thread; we're not changing the behaviour of static.
It looks to me that it is just a syntax consideration here. Nothing here is inconsistent with the logic of static methods, it's still impossible to use $this in your static function, and therefore the function will not have access to instance properties or methods. It feels more like a shortcut than an inconsistency to me.
I have no use case of that, but I guess someone may find it useful with objects created with dynamic class names: you can still use the function even if you don't know it's class name.

What's the visibility of a class by default in PHP?

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.

Static methods in PHP: what for?

I'm terribly sorry for asking such a silly question, but I'm new to OOP and trying to figure out what static methods are used for. Here's an example PHP code:
class foo{
static function bar(){
//do something here
}
public function baz(){
//do something different
}
}
Documentation says:
Declaring class properties or methods as static makes them accessible without needing an instantiation of the class
However, the both methods from the example above can be accessed from outside of the class with like:
foo::bar();
foo::baz();
It works (at least for PHP 5.3 that I'm using) without instantiation of the class foo.
So, what's the point of using static methods, if the both ways work??
Forgive me once again for such a noob question. I've been really trying hard to find it out myself with no success. Thanks.
Static methods are globally available tools (helpers) and are often overused. Static methods are death to testability and should be avoided almost completely.
Their advantage as well as disadvantage is that they live in the global scope, you can call them from anywhere, which makes them code smells in most cases because they break encapsulation.
On language level, as Kolink mentions, things like mysqli:real_escape_string() make sense of course, but on application level, you usually don't want to pollute your global scope and break encapsulation like that. You'd rather think of what tools you really need and where and inject them bundled into meaningful groups (classes).
Your foo::baz() raises a warning in strict mode (which should always be on):
Strict standards: Non-static method foo:baz() should
not be called statically in yourfile.php on line x
Generally they can be used for "helper" functions, such as mysqli::real_escape_string(), where the function is relevant to the class but not locked to any specific instance of it.

__construct() vs SameAsClassName() for constructor in PHP

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?

Categories