Strict standard declaration: should be compatible [duplicate] - php

I know there are a couple of similar questions here in StackOverflow like this question.
Why is overriding method parameters a violation of strict standards in PHP?
For instance:
class Foo
{
public function bar(Array $bar){}
}
class Baz extends Foo
{
public function bar($bar) {}
}
Strict standards: Declaration of Baz::bar() should be compatible with
that of Foo::bar()
In other OOP programming languages you can. Why is it bad in PHP?

In OOP, SOLID stands for Single responsibility, Open-closed, Liskov substitution, Interface segregation and Dependency inversion.
Liskov substitution principle states that, in a computer program, if Bar is a subtype of Foo, then objects of type Foo may be replaced with objects of type Bar without altering any of the desirable properties of that program (correctness, task performed, etc.).
In strong-typed programming languages, when overriding a Foo method, if you change the signature in Bar, you are actually overloading since the original method and the new method are available with different signatures. Since PHP is weak typed, this is not possible to achieve, because the compiler can't know which of the methods you are actually calling. (hence the reason you can't have 2 methods with the same name, even if their signatures are different).
So, to avoid the violation of Liskov Substituition principle, a strict standard warning is issued, telling the programmer something might break due to the change of the method signature in the child class.

I know I am late to the party but the answers don't really spell out the actual problem.
The problem is PHP doesn't support function/method overloading. It would be difficult to support function overloading in an untyped language.
Hinting helps. but in PHP it is very limited. Not sure why. For example you cannot hint a variable is an int or Boolean yet array is fine. Go figure!
Other object orientated languages implement this using function overloading. Which is to say the signature of the function is obviously different.
So for example if the following was possible we would not have an issue
class Foo
{
public function bar(Array $bar){
echo "Foo::bar";
}
}
class Baz extends Foo
{
public function bar(int $bar) {
echo "Baz::bar";
}
}
$foo = new Baz();
$bar = new Baz();
$ar = array();
$i = 100;
$foo->bar($ar);
$bar->bar((int)$i);
would output
Foo::bar
Baz::bar
Of course when it came to constructors the php developers realised they have to implement it, Like it or not! So they simply suppress the error or not raise it in the first case.
Which is silly.
An acquaintance once said PHP implemented objects only as a way of implementing namespaces. Now I am not quite that critical but some of the decisions taken do tend to support that theory.
I always have maximum warnings turned on when developing code, I never let a warning go by without understanding what it means and what the implications are. Personally I don't care for this warning. I know what I want to do and PHP doesn't do it right. I came here looking for a way to selectively suppress it. I haven't found a way yet.
So I will trap this warning and suppress it myself. Shame I need to do this. but I am strict about STRICT.

You can override parameters, but the signature should match. If you had put Array out in front of $bar, there would be no problem.
For example, if you had added an additional parameter, there would be no problem, provided the first parameter had the same type hinting. This is good practice in any language.

Because you declared on Foo that $bar should be of type array, while in the extending Bar, $bar's type isn't declared.
This isn't an error, it's a warning. You should make the method definition compatible with the original, base class. You can, however, safely ignore it if you know what you're doing (and only if you know what you're doing!!!)

Related

What is different between a function without start underscore and with an underscore in PHP? [duplicate]

While looking over various PHP libraries I've noticed that a lot of people choose to prefix some class methods with a single underscore, such as
public function _foo()
...instead of...
public function foo()
I realize that ultimately this comes down to personal preference, but I was wondering if anyone had some insight into where this habit comes from.
My thought is that it's probably being carried over from PHP 4, before class methods could be marked as protected or private, as a way of implying "do not call this method from outside the class". However, it also occurred to me that maybe it originates somewhere (a language) I'm not familiar with or that there may be good reasoning behind it that I would benefit from knowing.
Any thoughts, insights and/or opinions would be appreciated.
It's from the bad old days of Object Oriented PHP (PHP 4). That implementation of OO was pretty bad, and didn't include things like private methods. To compensate, PHP developers prefaced methods that were intended to be private with an underscore. In some older classes you'll see /**private*/ __foo() { to give it some extra weight.
I've never heard of developers prefacing all their methods with underscores, so I can't begin to explain what causes that.
I believe the most authoritative source for these kinds of conventions for PHP right now would be the PSR-2: Coding Style Guide because the Zend Framework is part of PSR:
Property names SHOULD NOT be prefixed with a single underscore to indicate protected or private visibility.
Now, in 2013, this is "officially" bad style by the PSR-2 coding guideline:
Property names SHOULD NOT be prefixed with a single underscore to indicate protected or private visibility`
Source: https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md
I was strongly against prefixing private/protected methods with underscore since you can use private/protected keyword for that and IDE will mark it for you.
And I still am, but, I found one reason why it can be a good practice. Imagine that you have public method addFoo() and inside that method you have some part of task which is common with other methods addFooWhenBar(), addFooWhenBaz()... Now, best name for that common method would be addFoo(), but it is already taken, so you must come up with some ugly name like addFooInternal() or addFooCommon() or ... but _addFoo() private method looks like best one.
Leading underscores are generally used for private properties and methods. Not a technique that I usually employ, but does remain popular among some programmers.
I use a leading underscore in the PHP 5 class I write for private methods. It's a small visual cue to the developer that a particular class member is private. This type of hinting isn't as useful when using an IDE that distinguishes public and private members for you. I picked it up from my C# days. Old habits...
I was looking for the same answer, I did some research, and I've just discovered that php frameworks suggest different styles:
Code Igniter
The official manual has a coding style section that encourages this practice:
Private Methods and Variables
Methods and variables that are only accessed internally, such as utility and helper functions that your public methods use for code abstraction, should be prefixed with an underscore.
public function convert_text()
private function _convert_text()
Other frameworks do the same, like
Cakephp:
does the same:
Member Visibility
Use PHP5’s private and protected keywords for methods and variables. Additionally, non-public method or variable names start with a single underscore (_). Example:
class A
{
protected $_iAmAProtectedVariable;
protected function _iAmAProtectedMethod()
{
/* ... */
}
private $_iAmAPrivateVariable;
private function _iAmAPrivateMethod()
{
/* ... */
}
}
And also
PEAR
does the same:
Private class members are preceded by a single underscore. For example:
$_status _sort() _initTree()
While
Drupal
code style specifically warns against this:
Protected or private properties and methods should not use an underscore prefix.
Symphony
on the other hand, declares:
Symfony follows the standards defined in the PSR-0, PSR-1, PSR-2 and PSR-4 documents.
I believe your original assumption was correct, I have found it to be common practice for some languages to prefix an underscore to methods/members etc that are meant to be kept private to the "object". Just a visual way to say although you can, you shouldn't be calling this!
I know it from python, where prefixing your variables with an underscore causes the compiler to translate some random sequence of letters and numbers in front of the actual variable name.
This means that any attempt to access the variable from outside the class would result in a "variable undefined" error.
I don't know if this is still the convention to use in python, though
In Drupal (a php CMS) underscores can be used to prevent hooks from being called (https://api.drupal.org/api/drupal/includes!module.inc/group/hooks/7).
If I have a module called "my_module" and want to name a function my_module_insert it would "hook" on the function hook_insert. To prevent that I can rename my function to _my_module_insert.
ps
The way hooks works in Drupal it's possible to implement a hook by mistake, which is very bad.
Drupal, and using underscore:
In a general way the underscore is to simple mark the fact that a function would probably only be called by a related parent function...
function mymodule_tool($sting="page title"){
$out ='';
//do stuff
$out .= _mymodule_tool_decor($sting);
return $out;
}
function _mymodule_tool_decor($sting){
return '<h1>'.$string.'</h1>';
}
Of course, just a simple example...
Using underscore in just for remembering purpose that we will not 'modify the variable'/'call the function' outside the class.
As we declare const variables in all uppercase so that while seeing the name of variable can guess that it is a const variable. Similar the variable that we don't want to modify outside the class, we declare it with underscore for our own convention.
That means that this method is private.
"I realize that ultimately this comes down to personal preference, but I was wondering if anyone had some insight into where this habit comes from." - it shouldn't be personal preference because every language or framework has it's own coding standards. Some FW coding standards is starting private methods with an _ and some FW discourage that.
You shoud use coding standard of a FW in which you program. To check if your code is according to the coding standard, you have a tool PHP_CodeSniffer: https://github.com/squizlabs/PHP_CodeSniffer
Very useful, detects errors regarding coding standard.
They are called "magic methods".

$var::staticfunction() OK but $this->var::staticfunction() NOT. What's the rationale?

In PHP, a static member or function can be accessed so long as the class name is a valid object or a string. This is mostly true. When the class name string is a property of an object, it can't be used directly. It must be copied to a simple variable before it can be used to access a static member. Here's an example:
class Foo {
protected $otherclass='Bar'; //string!
function out(){
$class=$this->otherclass;
echo $class::ALIAS; //Where everyone knows your name.
}
function noout_err(){
echo $this->otherclass::ALIAS; //syntax error, unexpected '::'
}
}
class Bar {
const ALIAS='Where everyone knows your name.'
}
This quirk has bothered me for a while now. So I've been wondering:
Is this a common limitation among OOP languages?
Can someone familiar with the internals of PHP explain why $this->classname::somefunction() is not desirable syntax?
This isn't meant to provoke a storm of 'because php sux' comments. I'm well aware of the language's peculiarities. I'd just like to know if there is a reason for this one other than 'it just grew that way'.
It is a limitation indeed and there's a reason for it:
The :: scope operator has an higher precedence over -> which means that:
$this->otherclass::ALIAS;
will be read as:
($this->(otherclass::ALIAS));
therefore triggering the error.
This is actually a feature that PHP inherited probably by C++.
Yeah, you can't do this, and there's no explicit reason for it. There's simply no syntax, messing up the grammar, to provide for this extreme edge case for which you've already demonstrated that there's a trivial workaround.
I'd hardly go so far as to call it a "limitation", and it's certainly no "quirk". PHP can't bake bread, either.
Really, if you see the code $this->classname::somefunction(), does it immediately make intuitive sense to you? Nah. It's good that you can't do this.

Why is overriding method parameters a violation of strict standards in PHP?

I know there are a couple of similar questions here in StackOverflow like this question.
Why is overriding method parameters a violation of strict standards in PHP?
For instance:
class Foo
{
public function bar(Array $bar){}
}
class Baz extends Foo
{
public function bar($bar) {}
}
Strict standards: Declaration of Baz::bar() should be compatible with
that of Foo::bar()
In other OOP programming languages you can. Why is it bad in PHP?
In OOP, SOLID stands for Single responsibility, Open-closed, Liskov substitution, Interface segregation and Dependency inversion.
Liskov substitution principle states that, in a computer program, if Bar is a subtype of Foo, then objects of type Foo may be replaced with objects of type Bar without altering any of the desirable properties of that program (correctness, task performed, etc.).
In strong-typed programming languages, when overriding a Foo method, if you change the signature in Bar, you are actually overloading since the original method and the new method are available with different signatures. Since PHP is weak typed, this is not possible to achieve, because the compiler can't know which of the methods you are actually calling. (hence the reason you can't have 2 methods with the same name, even if their signatures are different).
So, to avoid the violation of Liskov Substituition principle, a strict standard warning is issued, telling the programmer something might break due to the change of the method signature in the child class.
I know I am late to the party but the answers don't really spell out the actual problem.
The problem is PHP doesn't support function/method overloading. It would be difficult to support function overloading in an untyped language.
Hinting helps. but in PHP it is very limited. Not sure why. For example you cannot hint a variable is an int or Boolean yet array is fine. Go figure!
Other object orientated languages implement this using function overloading. Which is to say the signature of the function is obviously different.
So for example if the following was possible we would not have an issue
class Foo
{
public function bar(Array $bar){
echo "Foo::bar";
}
}
class Baz extends Foo
{
public function bar(int $bar) {
echo "Baz::bar";
}
}
$foo = new Baz();
$bar = new Baz();
$ar = array();
$i = 100;
$foo->bar($ar);
$bar->bar((int)$i);
would output
Foo::bar
Baz::bar
Of course when it came to constructors the php developers realised they have to implement it, Like it or not! So they simply suppress the error or not raise it in the first case.
Which is silly.
An acquaintance once said PHP implemented objects only as a way of implementing namespaces. Now I am not quite that critical but some of the decisions taken do tend to support that theory.
I always have maximum warnings turned on when developing code, I never let a warning go by without understanding what it means and what the implications are. Personally I don't care for this warning. I know what I want to do and PHP doesn't do it right. I came here looking for a way to selectively suppress it. I haven't found a way yet.
So I will trap this warning and suppress it myself. Shame I need to do this. but I am strict about STRICT.
You can override parameters, but the signature should match. If you had put Array out in front of $bar, there would be no problem.
For example, if you had added an additional parameter, there would be no problem, provided the first parameter had the same type hinting. This is good practice in any language.
Because you declared on Foo that $bar should be of type array, while in the extending Bar, $bar's type isn't declared.
This isn't an error, it's a warning. You should make the method definition compatible with the original, base class. You can, however, safely ignore it if you know what you're doing (and only if you know what you're doing!!!)

Why class declared constants needs to be retrived staticly?

class foo
{
const bar;
}
and to access it we have to do: self::bar; and not, $this->bar;
Is this correct? If so, why?
Yes this is correct. The reason is that a constant is class-bound whereas a property is instance-bound so it wouldn't make much sense to access it through a reference. No matter how many instances you create there will always only be one foo::bar const.
It's just a language design decision that it's not possible to access a const through a reference though, in Java for example you can indeed access a static final property through a reference but you will usually get a compiler warning.
Well, because they are constants that means they are static (constant and static are synonyms) and also it makes no sense in having one for each instance if they don't ever change, so you have them per class. Static members are accessed with ::.
A good point to note, which has been missed thus far is the fact that constants can contain only primitive values. They also cannot be changed once they are set, an attempt to set a value after its already declared will result in a parse error.
You should essentially use constants only when your property is needed across every instance of the class, and of course if it needs to be fixed.

Is type hinting helping the performance of PHP scripts?

Type hinting helps the compiler to assume the type of the variable, but, as the PHP is a dynamic scripting interpreted language, the question came to my mind if it's possible that type hinting even makes the runtime faster or not?
PHP is a dynamic language.
Dynamic languages only support runtime checking.
Type hinting is runtime type checking.
Runtime type checking is bad for performance.
Therefore, type hinting is bad for performance.
Type hinting only hinders performance because it requires (for objects) to test the inheritance hierarchy. To make things worse, this kind of check is expensive in PHP because it is done in time proportional to the depth of the hierarchy.
A test for type, such the one done for the array hint is a much smaller overhead, though.
Furthermore, it is currently not used for any optimization purposes.
It is however, a useful defensive programming feature.
I did a benchmark
https://github.com/EFTEC/php-benchmarks#type-hinting (you can check the whole code, test it and check it by yourself).
/**
* #param DummyClass $arg1
* #param DummyClass $arg2
*
* #return DummyClass
*/
function php5($arg1,$arg2){
return new DummyClass();
}
function php7(DummyClass $arg1,DummyClass $arg2): DummyClass {
return new DummyClass();
}
php5 0.0006339550018310547 seconds
php7 0.0007991790771484375 seconds
And type hinting is around 10% slower than without type hinting. It is not considerably slow unless it is required in a vital part of the code (a huge loop for example) or we need raw performance.
I prefer PHPdoc, it works similar, it's more complete and it doesn't affect the performance.
The accepted answer and the other answers as well as the original question are wrong on an important aspect / technicality:
/**
* #param string|null $input <--- this is a type hint
*/
function test($input): string <--- this is a type declaration
{
return $input;
}
type hinting is an IDE feature (built on top of language functionality such as types, typed declarations, meta constructs, xDoc etc)
it is intended for development-time, typically for documentation and (before attributes) for metaprogramming
as such, the performance hit at run-time is probably negligible (if all you have is a bunch of PHPDocs) and the IDE, depending on implementation, might actually get faster (e.g. hinting small specific types instead of god objects as is typical in a javascript environment)
unless you're doing some sort of meta programming (doing stuff with PHPDoc), (bad) type hinting should not cause any compile-time or run-time problems
type declarations are a language feature
it is intended for the application run-time
bad/wrong type declarations will cause compile-time or run-time errors
some type declarations will (negligibly) slow down the application:
function test(): SomeClass {
return $x; // $x can only be checked at run-time
}
some type declarations are actually checked at compile-time and incur no additional performance hits (although in this case, the previous point still applies):
interface IParent {
public function test(): SomeClass;
}
interface IChild extends IParent {
public function test(): SomeUnrelatedClass; // 💥
}
As others have said, the benefits of types far outweigh the disadvantages and eventually there may be a point where a stricter typing regime would actually improve performance (by offloading all type checks to compile time and optimising flow based on types).
TL;DR Bottom line: No, type hinting does not make the runtime any slower.
All type hinting in PHP does is add code that tests the type of the parameters and fails if its not what's expected, so type hinting NEVER helps performance. Its only real use is for debugging, so if you have a function that's called very often, removing the type hint in the production code can speed things up, especially since checking the type of an object isn't the fastest thing in the world.
also see when should I use type hinting in PHP?

Categories