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.
Related
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!!!)
In PHP, I cannot assign a value to a variable unless I access its property without using a getter method, is it by design or I missed something?
Simply put, when I do $article->content->value[$some_value] = 'hello' it works, but $article->get_value()[$some_value] = 'hello' sets nothing, the array remains empty.
What the get_value does is just return $this->content->value, and when used as a getter, it does what it supposed to do as expected.
I feel like I missed some basic here, if someone could share me why setting value doesn't work, it'll be great.
Unlike objects, arrays aren't returned by reference in PHP, so when you call the getter method, you're getting back a copy.
If you want to modify the object property itself then you can change the method definition to return a reference by prepending the method name with an ampersand, e.g.
public function &getArray()
{
return $this->array;
}
See https://3v4l.org/1YK9H for a demo
I should stress that this is absolutely not a common pattern in PHP, other than perhaps a long way back into the PHP 4 days when OOP was a lot less ubiquitous. I certainly wouldn't expect a class I was using to return arrays by reference, and neither would I recommend anyone else doing it. Note that it's not possible to ask the class for a reference, in order to prevent unwanted modifications to private properties - the class has to define the behaviour.
The PHP documentation has more information about returning by reference here: http://php.net/manual/en/language.references.return.php
I have some code I'm working with that was written by the guy before me and I'm trying to look it over and get a feel for the system and how it all works. I am also fairly new to PHP, so I have a few questions for those willing and able to provide.
The basic breakdown of the code in question is this:
$__CMS_CONN__ = new PDO(DB_DSN, DB_USER, DB_PASS);
Record::connection($__CMS_CONN__);
First question, I know the double underscore makes it magic, but I haven't been able to find anywhere exactly what properties that extends to it, beyond that it behaves like a constant, kind of. So what does that mean?
class Record
{
public static $__CONN__ = false;
final public static function connection($connection)
{
self::$__CONN__ = $connection;
}
}
Second, these two pieces go together. They are each in separate files. From what I've read, static variables can be referenced in the same way as static functions, so couldn't you just call the variable and set it directly instead of using the function?
I get the feeling it's more involved than I am aware, but I need to start somewhere.
This isn't a magic variable. The person who wrote that shouldn't really use double underscores for variable names like that because it can cause confusion.
This is just a static property on a class. Which means it is shared between instances of that class (in the same php request).
Have a look at the docs for static properties if you're unsure on how these work.
There are several predefined "magic constants" that use this naming style. However, I don't think the underscores mean anything special (as far as the language is concerned); i.e. defining your own variable like this won't bestow it any magical properties. It may be part of the previous programmer's naming convention, and if so, it's probably ill-advised.
Setting a property via a function can, in many circumstances, make the "client" code more resilient to changes in the implementation of the class. All implementation details can be hidden inside the method (known as a "setter"). However, there are strong feelings about whether this is a good idea or not (I, for one, am not a big fan).
Two underscores do not make a variable magic.
It's better to use getters/setters than to access class properties directly.
The PHP manual has this to say on naming variables (and other symbols) with underscores:
PHP reserves all symbols starting with __ as magical. It is recommended that you do not create symbols starting with __ in PHP unless you want to use documented magical functionality.
Pay particular attention to the use of the words "reserves" and "documented". They mean double underscores shouldn't be used for user-defined symbols as it may lead to future conflicts, and that unless the symbol is explicitly mentioned in the manual as being magic, it's mundane.
How can I dynamically pass "items" to class function?
For example here it is a piece of some class and its function where I declare an element of object (items) as $b:
//..........
public function __add2SomeObj($b) {
$namespc = $this -> __someObj(); // __someObj() returns object
$namespc -> cats = $b;
}
//...................
Can I pass any other name instead cats dynamically so it won't be declared as a string?
i.e. something like:
//..........
public function __add2SomeObj($a,$b) {
$namespc = $this -> __someObj(); // __someObj() returns object
$namespc -> $a = $b;
}
//...................
} //end of class started above
$t=new aboveClass()
$t->__add2SomeObj("cats", array(1=>"PussyCat",2=>"Scratchy"));
$t->__add2SomeObj("dogs", array(1=>"Waffy",2=>"Sharik")); // once again but dogs...
Should I define a constant or what to make this or should i declare this protected varibale as object like (object) $vaaar?
Sorry I'm a little bit infamiliar with PHP OOP...
Yes you can do this. Read about variable variables:
Class properties may also be accessed using variable property names. The variable property name will be resolved within the scope from which the call is made. For instance, if you have an expression such as $foo->$bar, then the local scope will be examined for $bar and its value will be used as the name of the property of $foo. This is also true if $bar is an array access.
However you must be carful when dealing with arrays:
$namespc->$a[0]
will get the first element from the array that gets returned by $namespc->$a.
Whereas
$namespc->{$a[0]}
will first resolve $a[0], i.e. get the first value of the array $a, and use this as property name.
What you're asking is whether you can decide at runtime which property to change inside __add2SomeObj as you in the second listing. You can, and you did is correct.
However, properties must be strings __add2SomeObj, so you should ensure that the $a parameter is a string (it will be automatically converted to a string, but this may give unexpected results if $a is an object or an array).
Second, you're allowing the caller too change an arbitrary property. This may or may not violate the encapsulation of your class depending on the class __someObj returns and on the class of __add2SomeObj. It will also create a dynamic property on the object $namespce (i.e., one that does not exist in all the objects of that class), which you may not want.
Finally, and has a consequence of the point before, __add2SomeObj may generate a fatal error. So I'd say you'd better validate the $a paramater against a set of permitted property names.
You syntax is correct:
$obj->cats = $b;
and
$a = 'cats';
$obj->$a = $b;
will do the same thing.
As for whether or not to make "cats" a constant, that's up to you. I would suggest putting the error reporting up:
error_reporting(E_ALL | E_STRICT);
That way if you accidentally put in "cast" and that's not a valid member you'll get an error thrown.
Lastly, PHP is a dynamic language. I get the feeling your background might be with more static languages. This is just something you need to get comfortable with and you need to find a balance between readability and verbosity. But whatever you do, don't try and recreate non-PHP idioms in PHP, which is a common mistake for people coming from one language to another.
I've just inherited this code in PHP which seems to do some kind of web service call to googles api. I'm not quite an expert on PHP and there is a few syntax questions I have specifically relating to the following line
$soapClients = &APIlityClients::getClients();
I understand the double "::" as indicating that APIlityClients is a static class but I'm not sure what the "&" in front of APIlityClients means.
When you use an ampersand in front of a variable in PHP, you're creating a reference to that variable.
$foo = 'bar';
$baz = &$foo;
echo $foo //bar
echo $baz //bar
$foo = 'foobazbar';
echo $foo //foobazbar
echo $baz //foobazbar
Prior to PHP5, when you created an object from a class in PHP, that object would be passed into other variables by value. The object was NOT a reference, as is standard in most other object oriented (Java, C#, etc.) languages.
However, by instantiating a class with an ampersand in front of it, you could create a reference to the returned object, and it would behave like an object in other languages. This was a common technique prior to PHP5 to achieve OOP like effects and/or improve performance.
It is PHP's version of getting a reference to something rather than copying its value. So in this case the & would retrieve a reference to the return value of APIlityClients::getClients() rather than a copy of the return value itself.
It means "address of" - and it's referring to the value returned from the getClients() call, not the APllityClients class itself.
Basicly it's saying to assign $soapClients to a reference to whatever is returned from getClients() rather than making a copy of the returned value.
& indicates a pass by reference rather than by value. It doesn't apply much in PHP5 since classes are passed by reference by default in that version, but weren't in previous versions.
the & means it's a reference. References are used to allow multiple variables point to the same object.
this page explains it better than I can though
Also see http://us3.php.net/manual/en/language.references.php for more information on references in php in general