tags:

views:

243

answers:

6

I understand that there are two ways to access a PHP class - "::" and "->". Sometime one seems to work for me, while the other doesn't, and I don't understand why.

What are the benefits of each, and what is the right situation to use either?

+8  A: 

The "::" symbol is for accessing methods / properties of an object that have been declared with the static keyword, "->" is for accessing the methods / properties of an object that represent instance methods / properties.

Cody Caughlan
It's a bit incorrect to say 'with the static keyword'. That's not the only case - accessing parent methods and constants both require the `::` operator, neither of which have to be declared static.
Peter Bailey
+16  A: 

Simply put, :: is for class-level properties, and -> is for object-level properties.

If the property belongs to the class, use ::

If the property belongs to an instance of the class, use ->

class Tester
{
  public $foo;
  const BLAH;

  public static function bar(){}
}

$t = new Tester;
$t->foo;
Tester::bar();
Tester::BLAH;
Peter Bailey
$t->foo - not $t->$foo...
gnarf
thanks - i was apparently typing too fast ;)
Peter Bailey
so, for example...if i have a library class and in it, a function that will return a connect to my MySQL (basically as a singleton), i can and should refer to it by doing something like library::connect(); rather than $libraryObject->connect(); ?
johnnietheblack
also, if i use the object, i have to pass it into other functions, but if i use the static operator, i can avoid scope issues? thanks in advance!
johnnietheblack
@jonnietheblack: There's no *should*, it's a matter of what you want to do. If you want to use an Object that you can pass around, copy, clone etc, you instantiate the Object from the Class (using `new Class`) and from then on use things inside the Object with `->`. If you're not instantiating an Object, but just want to call the Class functions "as they are", you use `::`. It really depends on your usage of the Class, one method isn't better than the other.
deceze
To put it another way: `$object->func()` is okay, notice that `$object` is a variable, i.e. it's instantiated. `ClassName::func()` is also okay, notice that `ClassName` is not a variable, it's just the class name. `$object::func()` is not good, you're trying to call a method statically on an instantiated object. `ClassName->func()` is also no good for the reverse reason.
deceze
+2  A: 

When you declare a class, it is by default 'static'. You can access any method in that class using the :: operator, and in any scope. This means if I create a lib class, I can access it wherever I want and it doesn't need to be globaled:

class lib
{
    static function foo()
    {
       echo "hi";
    }
}
lib::foo(); // prints hi

Now, when you create an instance of this class by using the new keyword, you use -> to access methods and values, because you are referring to that specific instance of the class. You can think of -> as inside of. (Note, you must remove the static keyword) IE:

class lib
    {
        function foo()
        {
           echo "hi";
        }
    }
$class = new lib;
$class->foo(); // I am accessing the foo() method INSIDE of the $class instance of lib.
Chacha102
Your first example will throw errors in E_STRICT: Non-static method lib::foo() should not be called statically.
gnarf
Updated, although I've never had an error, even though documentation says it should.
Chacha102
A: 

It should also be noted that every static function can also be called using an instance of the class but not the other way around.

So this works:

class Foo
{
  public static function bar(){}
}

$f = new Foo();
$f->bar(); //works
Foo::bar(); //works

And this doesn't:

class Foo
{
  protected $test="fddf";
  public function bar(){ echo $this->test; }
}

$f = new Foo();
$f->bar(); //works
Foo::bar(); //fails because $this->test can't be accessed from a static call

Of course you should restrict yourself to calling static methods in a static way, because instantiating an instance not only costs memory but also doesn't make much sense.

This explanation was mainly to illustrate why it worked for you some of the times.

André Hoffmann
It should be noted - in the sense that it shouldn't be allowed. Bad design principle to get into the habit of.
gnarf
I was just telling this because he was asking why it sometimes works and the other time doesn't.Of course it's not a great design principle, but sometimes you need to know stuff to things the right way.
André Hoffmann
integrate this in to your answer and it will be a good one.
tharkun
Ok. I'll do that.
André Hoffmann
Foo::bar(); in second example will work actually
MrHus
That wouldn't make any sense, since without an instance there are no non-static variables that this method could access. Did you try that? If so what version did you use?Besides if it would work, the static keyword wouldn't bring any changes to a method either.
André Hoffmann
Just gave that a try and figured out that it only dies when you are calling a dynamic method which is using dynamic variables in a static context. PHP seriously lacks a clear coding style in some aspects :-/
André Hoffmann
The only difference is that you don't have $this when you call with :: symbol. I've run you're code and it works just fine. The only change I made was adding missing parenthesis on the $f->bar;. I'm running 5.3.
MrHus
Yea..just figured that out too :-(I updated the example.
André Hoffmann
A: 

Sourcing WikiPedia - Class

In object-oriented programming, a class is a programming language construct that is used as a blueprint to create objects. This blueprint describes the state and behavior that the created objects all share. An object created by a class is an instance of the class, and the class that created that instance can be considered as the type of that object, e.g. a type of an object created by a "Fruit" class would be "Fruit".

The :: operator accesses class methods and properties which are defined in php using the static keyword. Class const are also accessed using ::

The -> operator accesses methods and properties of an Instance of the class.

If the function operates on an instance, you'll be using ->. If it operates on the class itself, you'll be using ::

Another use of :: would be when you want to call your parent functions. If one class inherits another - it can override methods from the parent class, then call them using parent::function()

gnarf
A: 

Php can be confusing in this regard you should read this.

What's also confusing is that you can call non static functions with the :: symbol. This is very strange when you come from Java. And it certainly surprised me when I first saw it.

For example:

class Car
{
    public $name = "Herbie <br/>";

    public function drive()
    {
        echo "driving <br/>";
    }

    public static function gas()
    {
        echo "pedal to the metal<br/>";
    }
} 

Car::drive(); //will work
Car::gas(); //will work

$car = new Car();
$car->drive(); // will work
$car->gas(); //will work

echo $car->name; // will work
echo Car::$name; // wont work error

As you can see static is very loose in php. And you can call any function with both the -> and the :: symbols. But there is a difference when you call with :: there is no $this reference to an instance. See example #1 in the manual.

MrHus