Using the :: operator on an object - php

Recently I've found interesting usage of code and I didn't know that it's possible. Can someone explain or give me manual page with explanation why the code below works? I understand :: can be used to reflect methods from parent, static etc. or to access static fields/methods but with reference $this it seems weird mostly because method a() is not static
class Test
{
private function a()
{
echo 'a works';
}
public static function c()
{
echo 'c works';
}
public function b()
{
$this::a(); // this is weird
$this::c(); // also this
$this->a(); // normal usage
self::a(); // as expected
static::a(); // same as above
Test::c(); // as expected
}
}
(new Test)->b();
I've tried to find some information on my own but with no luck.
Edit:
I'm aware what :: is also I know it will throw warning if E_STRICT is enabled.

As of PHP 5.3, you can use a variable to reference the class with the :: operator. The manual only shows usages in which the variable is a string, however it is in fact possible to also use an object in its place; the class referenced is then the class the object is an instance of. There's an example buried in the manual for static: http://php.net/manual/en/language.oop5.static.php#language.oop5.static.properties.
So, all these resolve to the same thing:
$foo = new Foo;
$foo::bar();
$foo = 'Foo';
$foo::bar();
Foo::bar();
The methods will always be called statically; for methods which are already static this works as expected, while for non-static methods an E_STRICT notice will be raised.
This is mostly for convenience as far as I gather; you already have an object of a specific class, now you want to reference some static item of that class – just use the object you already have. This also allows for some more dynamic behaviour with subclassing. E.g.:
$foo = new SomeClassWithAVeryLongName;
$foo->bar($foo::BAZ); // much more concise than repeating SomeClassWithAVeryLongName::

Related

Purpose of Static Class Functions in PHP

I thought that the use of the static keyword in the declaration of a class function meant that you could call the function without an instance of the class using the scope resolution operator (::).
For example:
class Foo
{
public static function static_function() {
return 'x';
}
public function non_static_function() {
return 'y';
}
}
// to call static_function:
echo Foo::static_function();
// to call non_static_function:
$foo = new Foo();
echo $foo->non_static_function();
The PHP.net documentation on static seems to support this idea.
I came across some code yesterday that someone had wrote accessing class functions using the scope resolution operator that had NOT been defined with the static keyword. I was surprised and confused to see this worked.
Given my class defined above, Foo, it turns out you can actually do:
echo Foo::static_function();
echo Foo::non_static_function();
Resulting in output xy without generating any errors or warnings.
If you can access non-static class functions without the static keyword, what is the point in it?
Resulting in output xy without generating any errors or warnings.
No way. The error reporting must have been turned off on that environment. That would have definitely produced a Strict Standards warning notice.

When is necessary to use static methods?

I thought usually we use static method because we do not need to instantiate objects. and we can use className::staticFunction to call static method, bub today found:
test1.php
<?php
class Foo {
static public function helloWorld() {
print "Hello world " ;
}
}
Foo::helloWorld();
test2.php
<?php
class Foo {
public function helloWorld() {
print "Hello world " ;
}
}
Foo::helloWorld();
Question:
Both of above scripts work. We did not declare function as static, we can still use className::staticFunction to call the function. Why do we need use static methods?
We did not declare function as static, we can still use className::staticFunction
What you probably didn't notice is that PHP complains about the second type of invocation:
PHP Strict Standards: Non-static method Foo::helloWorld() should not be called statically in php shell code on line 1
Strict Standards: Non-static method Foo::helloWorld() should not be called statically in php shell code on line 1
To make these notices visible you need to set the value of error_reporting to -1, either using ini_set() or via the php.ini configuration file; btw, this is recommended during development.
Conclusion
A function that's called statically should be declared as static function xyz().
Update
Btw, using the scope resolution operator :: doesn't necessarily mean you're making a static call; consider this example:
class Foo
{
public function helloWorld()
{
print "Hello world ";
}
public function doSomething()
{
self::helloWorld();
}
}
$f = new Foo;
$f->doSomething();
This works because using self:: as opposed to Foo:: doesn't change the invocation "mode" (unless the method you're calling is defined as static).
The "problem" with static methods is the way they're called:
Foo::bar();
Any call to a static method is by necessity hardcoded and cannot easily be substituted. Compare with:
$foo->bar();
$foo is a variable here, meaning the exact object and implementation of bar() can be substituted. This is important for and the basis of dependency injection.
You'd use a static method for:
first and foremost cases where you don't need individual object instances
anything you need to do before an object can be instantiated
alternative object constructors, for instance DateTime::createFromFormat() instead of new DateTime
idempotent utility functions which you are 100% sure never need to be substituted or mocked
You may use static functions in other scenarios here and there, but these are the main points. You need to be aware that declaring a method static means you need to call it statically, which means its call-time use cannot really be altered. For a long treaty on this subject, read How Not To Kill Your Testability Using Statics.
Well a simply hello world program might not be able to show a big difference is the usage of static vs not but take a look at this class
class foo {
private $a = 1;
private static $b = 2;
public function foobar()
{
echo $this->a;
}
}
in this above class if you call foobar statically then $this->a will not resolve.
PHP is funny like that, but I'll usually have a utilities class which takes arguments of things to perform logic on and return. Stuff like this doesn't need an instantiated class. It's up to the user/developer to correctly call methods (read: use the correct method accessors).
When you are working on a large OOP based project, you’ll no doubt be working with many classes (both parent and child classes). An unfortunate consequence of this is that in order to access elements from different classes, they must manually be passed through each class (or worse, storing an instance in a global variable). This can be painstakingly frustrating and can lead to messy code and overall bad project design. Thankfully, static elements are accessible from any context (i.e. anywhere in your script), so you can access these methods without needing to pass an instance of the class from object to object.
As you don’t need to declare an object instance to access static elements, you can be saved from unnecessary declarations to access seemingly simple functions.
Static elements are available in every instance of a class, so you can set values that you want to be available to all members of a type.
From the above example test1.php
helloworld() function cannot be overriden or overloaded since you have added a static keyword.
However in the second example, test2.php
helloworld() function can be overloaded and overriden
Illustration:1 (Works)
<?php
class Foo {
function helloWorld() {
print "Hello world " ;
}
}
class Foo1 extends Foo
{
function helloWorld()
{
echo "Foo's World";
}
}
$Foo1 = new Foo1();
$Foo1->helloWorld(); //Foo's World
Illustration:2 (Fails)
Cannot make static method Foo::helloWorld() non static
<?php
class Foo {
static function helloWorld() {
print "Hello world " ;
}
}
class Foo1 extends Foo
{
function helloWorld()
{
echo "Foo's World";
}
}
$Foo1 = new Foo1();
$Foo1->helloWorld();

PHP: Why am I getting errors about static properties?

http://codepad.viper-7.com/I0Zqoi
I don't understand what's wrong with this or how to fix it or why. Can someone who knows a little about programming please explain what's happening behind the scenes, like on the interpreter level? Also, how can I fix my problem, and why do I need to write my code in the way of the correction? Can you tell me, in human language, what is wrong with this and how to make it better? I guess my book isn't explaining well, and the code inside of it doesn't work. :/ Thank you.
class A
{
private $foo = 'bar';
function read()
{
echo self::$foo;
}
}
$a = new A();
a::read();
Strict Standards: Non-static method A::read() should not be called statically in /code/I0Zqoi on line 13
Fatal error: Access to undeclared static property: A::$foo in /code/I0Zqoi on line 8
The only workaround seems to be to add "static" in front of the method. Apparently, non-static methods cannot be accessed by static means (e.g., class A{function read(){echo "whatever"};} cannot be accessed by a::read() because the -> operator is necessary). Also, static properties cannot be accessed by object code, even if they exist within a function (e.g., class A{static $variable; function read(){echo $this->variable};} a->read(); won't work because the -> operator is being used to access a function that calls a static property.). By changing both the method and the property to static, the method can be accessed by static means. By changing both the method and property to non-static makes it so that either can be accessed with object instanciation. It doesn't make sense to me that the debugger is throwing errors because my book says that static properties can be called from non-static methods via object code calls to the non-static methods. So, is the debugger broken? Because I've tried every combination, and the code only seems to work if both the method and property are either static or non-static. :(((
The Strict Standards part is because a::read() is being called in a static context with ::. After declaring $a as a class instance of A, you should call the read() method on the variable using the -> operator:
// Proper non-static method call
$a = new A();
$a->read();
In the class definition, $foo is declared as a private property, but without the static keyword. It is then referred to in static context using the :: operator instead of the ->. The proper way to access it would beL
// Proper reference to non-static $foo
function read() {
echo $this->foo;
}
Now what does static mean anyway? Static methods and properties refer to class methods and properties that are shared by all current and future class instances. If A::$foo had been declared as:
private static $foo;
then there would be only the one $foo for all of class A in your code. Changing $foo would affect all instances of class A, and $foo can be accessed without even creating an instance of the class (like new A();)
Likewise, static methods can be called without creating an instance of the class because they do not modify class properties that are not also static.
// Static method call:
A::read();
To declare properties and methods as static, just add the static keyword:
// Property
private static $foo;
// Method
public static function foo() {}
EDIT for more examples:
class A
{
// Private property (non-static)
private $foo;
// Public property (static)
public static $bar = 12345;
// Public (non-static) function to access private $foo
public function getFoo() { return $this->foo; }
// Public (non-static) function to set private $foo
public function setFoo($newfoo) { $this->foo = $newfoo; }
// Static function
public static function incrementBar() { self::$bar++; }
}
Now see it in action:
// We haven't created any class instances yet (with the 'new' operator)
// But we can access the static properties & functions:
echo A::$bar . " ";
// prints 12345
A::incrementBar();
echo A::$bar . "\n";
// prints 12346
// Now we'll start working with class instances.
// Create 2 instances of class A
$a = new A();
$a->setFoo(8888);
$b = new A();
$b->setFoo(9999);
// It's a violation of strict standards to call getFoo() statically
// And it's meaningless to do so, because $foo only exists inside a class instance!
// Can't do this... Issues a strict warning since we're calling non-static getFoo() statically
//echo A::getFoo();
// But we can call getFoo() on the class instances:
echo $a->getFoo() . " " . $b->getFoo() . "\n";
// Prints 8888 9999
// Remember $bar was 12346...
echo $a::$bar . " " . $b::$bar . "\n";
// Prints 12346 12346
// Now modify the static property $bar again
// This affects all class instances.
A::incrementBar();
echo $a::$bar . " " . $b::$bar . "\n";
// Prints 12347 12347
I stuffed this whole thing into the codepad as well: http://codepad.viper-7.com/tV6omK
The book you're reading must not be paying attention to strict standards. If a non-static function does not attempt to access/modify a non-static property, you can call it statically successfully, but it WILL issue a strict warning. If the non-static function does modify or access a non-static property with $this->property, it will be a fatal error. You can't do that.
In PHP's error_reporting, the setting of E_ALL for show all errors actually does not include strict warnings. That has to be done with E_ALL & E_STRICT.
:: is used to access a static attribute. If you want to access an object attribute then use ->.
$a->read();
...
echo $this->$foo;
Although the other answers are definitely correct, here's an answer to your concrete question:
It doesn't make sense to me that the debugger is throwing errors because my book says that static properties can be called from non-static methods via object code calls to the non-static methods. So, is the debugger broken? Because I've tried every combination, and the code only seems to work if both the method and property are either static or non-static. :(((
The author of your book was under the impression that not getting an error message is considered clean code. It's not. You shouldn't have a method that can be called both statically as well as dynamically, as the two simply differ too much. Dynamic calls are for objects, where static calls are for classes. If you have the opportunity, I would always try to go the dynamic way, as that yields less coupling in the application.
As to why "the debugger is throwing errors" (it's the interpreter throwing E_STRICT warnings, but hey ;)): this behaviour has been changed in PHP five dot something. In PHP 4 you could call every method statically, even if it was a dynamic method. Possibly, your book is running behind on the facts.

php static methods question

What is the difference between these two pieces of code?
class something {
static function doit() {
echo 'hello world';
}
}
something::doit();
and the same but without the static keyword
class something {
function doit() {
echo 'hello world';
}
}
something::doit();
They both work the same is it better to use the static keywords? Am i right in understanding that it doesn't instantiate the class if you use the static method?
The second example is technically incorrect - if you turn on E_STRICT error reporting you'll see that PHP is actually throwing an error.
PHP Strict Standards: Non-static
method something::doit() should not be
called statically in...
In other words, it's being nice and letting you call the function anyway.
In addition to the other valid answers, the reason for the 2nd example working is also due to a quirk in how PHP handles objects and calls (Besides PHP 4 compatibility). Calling a non-static declared method statically from within another instance will let you access class methods on other classes as if they were local. To understand, let's take an example:
class A {
public function foo() {
echo get_class($this) . "\n";
}
}
class B {
public function bar() {
A::foo();
}
}
$a = new a();
$a->foo(); // "A"
$b = new B();
$b->bar(); // "B"
Did you see what happened there? Because you called the A::foo() method from within another class's instance, PHP treated the call as if it was on the same instance. Note that there is no relationship between A and B other than the fact that B calls A. Within A->foo(), if we did $this instanceof A (or $this instanceof self), it would fail and return false! Quite unusual...
Now, I first thought it was a bug, but after reporting it, it's apparently as designed. It's even in the docs.
Note that this will not work with E_STRICT mode enabled. It also will not work if you declare a method as static.
The difference is that static functions can be used without having to create an instance of the class.
Have a look at this great PHP OOP beginner tutorial here. It explains in more detail with an example under the Static Properties and Methods section.
Second bit shouldn't work as you should call it by
$something = new something();
$something->doit();
Static functions allows you to call a function within a class without consturcting it.
So basically if you have a class to handle users, so a function that logs the user in should be a static function, as in the constructor of that class you will probably gather the user information and you cannot do so without logging him in.
Your second example is wrong. Using a static method does not create an instance of the class. Your second example should look like this:
$x = new something();
$x->doit();
Static methods should be declared static for minimum two reasons:
a) when using E_STRICT error_reporting, calling non static method as static will generate error:
Strict standards: Non-static method something::doit() should not be called statically
b) based on keyword static some IDE's filter method possible to run at auto-complete.

Difference between :: and -> in PHP

I always see people in serious projects use :: everywhere, and -> only occasionally in local environment.
I only use -> myself and never end up in situations when I need a static value outside of a class. Am I a bad person?
As I understand, the only situation when -> won't work is when I try following:
class StaticDemo {
private static $static
}
$staticDemo = new StaticDemo( );
$staticDemo->static; // wrong
$staticDemo::static; // right
But am I missing out on some programming correctness when I don't call simple public methods by :: ?
Or is it just so that I can call a method without creating an instance?
The double colon is used when you don't instantiate a class
class StaticDemo {...};
StaticDemo::static
if you do instantiate, use -->
class StaticDemo {...};
$s = new StaticDemo();
$s->static;
This is explained further at http://php.net/manual/en/language.oop5.patterns.php
:: is for referencing static properties or methods of a class. -> is for referencing instance properties and methods. You aren't missing out on any programming correctness, and if you are a bad person then it isn't because of this. Which one you use depends on the purpose of your class and how its written. But also, PHP didn't have namespaces until very recently so many people encapsulated their code in static classes to emulate namespaces to avoid naming collisions. It is possible you are seeing code that does that.
You caused a strict standards warning in E_STRICT mode. You are a bad person.
<?php
error_reporting(E_ALL | E_STRICT);
header('Content-type: text/plain');
class Foo {
public $msg = "Hello, public.\n";
public static $msgStatic = "Hello, static.\n";
public function write() {
echo "Hello, write.\n";
}
public static function writeStatic() {
echo "Hello, writeStatic.\n";
}
}
//echo Foo::$msg; // Fatal error: Access to undeclared static property: Foo::$msg
echo Foo::$msgStatic;
echo Foo::write(); // Strict Standards: Non-static method Foo::write() should not be called statically
echo Foo::writeStatic();
echo "------------------------\n";
$f = new Foo;
echo $f->msg;
echo $f->msgStatic; // Strict Standards: Accessing static property Foo::$msgStatic as non static
// Notice: Undefined property: Foo::$msgStatic
echo $f->write();
echo $f->writeStatic();
Output:
Hello, static.
Strict Standards: Non-static method Foo::write() should not be called statically in /home/adam/public_html/2010/05/10/bad.php on line 22
Hello, write.
Hello, writeStatic.
------------------------
Hello, public.
Strict Standards: Accessing static property Foo::$msgStatic as non static in /home/adam/public_html/2010/05/10/bad.php on line 29
Notice: Undefined property: Foo::$msgStatic in /home/adam/public_html/2010/05/10/bad.php on line 29
Hello, write.
Hello, writeStatic.
-> is for an instanciated class.
:: is a static call.
:: is used in inheritance constructors (a child accessing a parent constructor) and when referring to a static method inside another method.
I wouldn't say not using static calls makes you a bad person either!
Yes, you can call a method or access a value without creating an instance.
It would be useful, for example, if you have a value that all instances of a class use. Say this value, however, needs to be initialized at the beginning of your app. You could use something like StaticDemo::static = 42; to initialize it, and then all instances of your class would be able to access it.
As I understand it the static is shared between objects of the same type:
class test{
static function print_test(){
print "hello!";
}
}
$objectA = new test();
$objectB = new test();
The function print_test will be "shared" between the two objects. But the catch is the function print_test() should not reference anything inside the class! even thou PHP 5 accepts it.
Since the function print_test in the example just prints out "hello!" and doesn't reference anything inside the class why allocate memory for it in $objectA and $objectB? Just make one static function and $objectA and $objectB should point to it automatically.
Well that's the theory behind it in other languages, but since php5 allows you to reference $this in a static function I don't believe its a true static function since it would have to be dynamic to get any properties for ($this->variable) that unique object.
:: is used for static methods, which you call if you have no object instance.
Use "->" when in object context and "::" when accessing the class directly. In your example that would be:
class StaticDemo {
public static $staticVar = 'blabla';
public $normalVar = 'foobar';
}
$foo = new StaticDemo();
echo $foo->normalVar; //object context, echoes "foobar"
echo StaticDemo::staticVar; //class or "static" context, echoes "blabla"
Read this for detailed intel.
Or is it just so that I can call a method without creating an instance?
Correct.
The :: (scope resolution operators) are used when calling static methods/members. You don't have to create an instance to do this (like you did in your example).
Using -> and :: in the right context is the key to object-orientated programming correctness. You should only create static variables/methods when they apply to the class as a whole, and not only to a specific instance (object) of the class.
Static methods and properties are independent of a particular instantiation of a class. These must be accessed using double colons (::). Non-static methods and properties should be accessed using ->
This allows you do to some pretty cool things. A trivial example is a counter that keeps track of the number of instances of the class exists:
class foo {
public static $i = 0;
public function __construct() {
self::$i++;
}
}
$a = new foo();
$b = new foo();
echo foo::$i;
// outputs 2
As others have said,
:: 'double colon' is for referencing a static property or method.
-> 'dash arrow' is for referencing a property or method of a class instance.
But also its worth noting that
:: is often used in texts as shorthand to refer to a property or method that belongs to a certain class (whether it's static or instance).
See the 'Note...in documentation...' : http://books.google.co.uk/books?id=qVLjFk_4zVYC&lpg=PA66&dq=php%205%20objects&pg=PA46#v=onepage&q=php%205%20objects&f=false
Well you're right about how to use -> and ::. But sometimes it just doesn't make much sense to create objects of a class. Here's an example
Compare
class Settings
{
public static $setting1;
public static $setting2;
... // lots of other vars and functions
}
if(Setting::$setting1)
//do something
vs
class Settings
{
public $setting1;
public $setting2;
... // lots of other vars and functions
}
$set = new Settings()
if($set->setting1)
//do something
As I said It doesn't make sense to create instances as there's always only required one. in this case static fits better. It turns out in web we mostly deal with this kind of case unless you're dealing with real Objects e.g. users etc hence the prevalence of the former

Categories