10

I have been stepping up my PHP game lately. Coming from JavaScript, I've found the object model to be a little simpler to understand.

I've run into a few quirks that I wanted some clarifying on that I can't seem to find in the documentation.

When defining classes in PHP, you can define properties like so:

class myClass {

    public $myProp = "myProp";
    static $anotherProp = "anotherProp";

}

With the public variable of $myProp we can access it using (assuming myClass is referenced in a variable called $myClass) $myClass->myProp without the use of the dollar sign.

We can only access static variables using ::. So, we can access the static variable like $myClass::$anotherProp with a dollar sign.

Question is, why do we have to use dollar sign with :: and not ->??

EDIT

This is code I would assume would work (and does):

class SethensClass {

    static public $SethensProp = "This is my prop!";

}

$myClass = new SethensClass;
echo $myClass::$SethensProp;
Sethen
  • 11,140
  • 6
  • 34
  • 65
  • 1
    Interesting... One upvote and one close request. – Sethen Mar 12 '13 at 16:35
  • Apologies for commenting here about [your other question](http://stackoverflow.com/q/17681253/20578) (which, if asked as a series of individual questions, I personally thought would have been fine - see e.g. http://stackoverflow.com/questions/15270843/what-does-plus-operator-mean-in-underscore-js), but saying something like "best practice says to do this" is a bit meaningless. If you can't explain *why* you think something is a "best practice", then how do you know it's "best"? Different things are best in different situations. – Paul D. Waite Jul 16 '13 at 16:09
  • @PaulD.Waite It's fine. As a developer trying to move forward with his development, asking questions about whether a particular library follows best practices to help them learn is acceptable in my mind. For the community at large to not support that is very frustrating. I do not believe that particular library was written using best practices and I am trying to make sure it's something I'm not doing wrong so when I contribute code I can be sure it's the best it can be. – Sethen Jul 16 '13 at 16:11
  • cool cool. Just remember, to make your code the best it can be, you're going to need to move beyond "someone said this is best practice", and understand *why* something is considered good or best practice. – Paul D. Waite Jul 16 '13 at 16:14

2 Answers2

18

A class constant is accessed with the :: scope operator, and no dollar sign, so the $ is needed there to differentiate between static class properties and class constants.

class myClass {
  public static $staticProp = "static property";

  const CLASS_CONSTANT = 'a constant';
}

echo myClass::CLASS_CONSTANT;
echo myClass::$staticProp;

So to access a variable, the $ is necessary. But the $ cannot be placed at the beginning of the class name like $myClass::staticProp because then the class name could not be identified by the parser, since it is also possible to use a variable as the class name. It must therefore be attached to the property.

$myClass = "SomeClassName";
// This attempts to access a constant called staticProp
// in a class called "SomeClassName"
echo $myClass::staticProp;

// Really, we need
echo myClass::$staticProp;
Michael Berkowski
  • 267,341
  • 46
  • 444
  • 390
  • `$myClass` is supposed to represent `$myClass = new myClass`. – Sethen Mar 12 '13 at 16:38
  • Then you are making no sense. $staticProp is a class variable, not instance variable, hence it can't be called by a class instance. – Lim H. Mar 12 '13 at 16:40
  • @LimH. So, what you're saying is you can't access a `static` variable with a class instance?? – Sethen Mar 12 '13 at 16:42
  • @SethenMaleno Yes, that's what I'm saying. – Lim H. Mar 12 '13 at 16:44
  • @LimH. Is this just bad practice? Because I have had success accessing `static` variables with class instances. – Sethen Mar 12 '13 at 16:45
  • @SethenMaleno it's not bad practice. It's conceptually incorrect. Please modify your post with codes that successfully call static variables from instances. – Lim H. Mar 12 '13 at 16:46
  • @SethenMaleno Static properties are to be used statically, and if you attempt to access them via `$this->staticProp` it violates strict standards. – Michael Berkowski Mar 12 '13 at 16:47
  • @LimH. I have updated my original answer with code that works. This is how I would assume this would be done. Apparently, this is not right. – Sethen Mar 12 '13 at 16:52
  • @MichaelBerkowski Any thoughts on my edit?? This code works, bit Lim is telling me this is not correct. I am curious as to why. – Sethen Mar 12 '13 at 16:58
  • 1
    @SethenMaleno I'm so so so so so sorry for my ignorance. Apparently, according to the documentation, as of PHP 5.3.0, you can reference the class from the variable. So technically you can't call a class variable on an instance, but because PHP is being PHP, it automatically reference the class for you. So in your case, the $myClass will be interpreted as SethensClass, not an actutal class instance, and therefore the static variable can be called. – Lim H. Mar 12 '13 at 16:58
  • 1
    @SethenMaleno What you have up there will work. It is a behavior I usually avoid unless it is absolutely necessary, but it is legal and sometimes useful – Michael Berkowski Mar 12 '13 at 16:59
  • http://php.net/manual/en/language.oop5.static.php -- last line, before example 1. My bad again. I seriously didn't know this :) – Lim H. Mar 12 '13 at 16:59
0

its Greedy!

Sometimes it is useful to refer to functions and variables in base classes or to refer to functions in classes that have not yet any instances. The :: operator is being used for this.

<?php
class A
{
    function example()
    {
        echo "I am the original function A::example().<br>\n";
    }
}

class B extends A
{
    function example()
    {
        echo "I am the redefined function B::example().<br>\n";
        A::example();
    }
}

// there is no object of class A.
// this will print
//   I am the original function A::example().<br>
A::example();

// create an object of class B.
$b = new B;

// this will print 
//   I am the redefined function B::example().<br>
//   I am the original function A::example().<br>
$b->example();
?> 

The above example calls the function example() in class A, but there is no object of class A, so that we cannot write $a->example() or similar. Instead we call example() as a 'class function', that is, as a function of the class itself, not any object of that class.

There are class functions, but there are no class variables. In fact, there is no object at all at the time of the call. Thus, a class function may not use any object variables (but it can use local and global variables), and it may no use $this at all.

In the above example, class B redefines the function example(). The original definition in class A is shadowed and no longer available, unless you are referring specifically to the implementation of example() in class A using the ::-operator. Write A::example() to do this (in fact, you should be writing parent::example()).

In this context, there is a current object and it may have object variables. Thus, when used from WITHIN an object function, you may use $this and object variables.

internals-in
  • 4,798
  • 2
  • 21
  • 38