This is with reference to Get a static property of an instance, I am a newbie and have the following code :
class Foo
{
public static $my_static = 1;
}
class Bar extends Foo
{
}
$foo = new Foo();
$boo = new Bar();
echo Foo::$my_static; // ok
echo Bar::$my_static; // ok
echo $foo::$my_static; // ok
echo $boo::$my_static; // ok
Static variables/properties are accessed only as ClassName::static_property as in C++, but it is not the case in PHP... but PHP books mostly mention the className::static_property pattern, not the object::static_property construct. Need more light on this..
Static properties may be accessed on various ways.
Class::$aStaticProp; //by class name
$classname::$aStaticProp; // As of PHP 5.3.0 by object instance
Static properties cannot be accessed through the object using the arrow operator ->.
As of PHP 5.3.0, it's possible to reference the class using a variable. The variable's value can not be a keyword (e.g. self, parent and static).
More you can read in manual
$instance::$staticProperty is simply a convenience shorthand for Class::$staticProperty. Since you already have an instance of a class and the syntax is unambiguous, PHP saves you from writing a potentially long class name. There's no functional difference.
within the class you have to use like self::$staticPropery
if the function accessing to the variable is also static.
Related
I am having trouble understanding how to work with objects.
The specific code:
class first{
class second{
public function widgets(){
$a_variable = $a_value;
}
#1
}
$second = new second;
#2
}
#3
$first = new first;
If I initialize $a_variable as $a_variable it is only available inside the function, correct?
If I initialize $a_varialbe as $this->a_variable it is only available inside class second, correct?
Can I initialize $a_variable as $first->second->a_variable? If so, How would I call it at #1, #2, and #3?
Can I initialize $a_varialbe as $this->second->a_variable? If so, How would I call it at #1, #2, and #3?
As you can see I am simply confused as to how OOP works.
First of all, I want to express how much I appreciate all of the help. I have already learned more than enough to consider this question a smashing success.
That said, even if it is poorly formulated, psuedo-code and invalid syntax, this code DOES run.
class class_1{
public function function_1(){
require('class_2.php');
public function function_2_callback(){
//%%%%%% How do I set a variable here and get the DATA...
}
$this->class_2 = new class_2("function_2_callback");
}
}
$class_1 = new class_1;
//&&&&&&&&&& Get the DATA here?
/* CONTENTS OF class_2.php */
class class_2($callback){
call_user_function($callback);
}
Even if we have to look at this as an exercise. Can someone tell me how I would first set (# %%%%%%%)and then call a variable (# &&&&&&&&) as shown?
First off: What you have there doesn't work, you cannot declare a class inside a class the way you are doing (notwithstanding conditionally declaring a class inside a function, which you should not do).
Scope in PHP (including OOP) is very simple:
variables have function scope
object properties are accessible if you have a reference to the object
the visibility of object properties can be restricted
The only real scope you have is function scope for variables:
$a = 'foo';
function bar() {
$a = 'bar';
}
The two $as are entirely unrelated, in different scopes. As simple as that.
class Foo {
public $a = 'foo';
public function bar() {
$this->a; // foo
$a = 'bar';
}
}
$foo = new Foo;
$foo->a; // foo
An object property has no scope, it has visibility. You can access it if you have the object in scope. Above, $foo is the object. It's in scope, its property a is public, therefore it can be accessed using $foo->a. Inside the class, the property is accessible via $this->a.
The $a = 'bar' is a local variable in the function and has nothing to do with $this->a. It is not accessible anywhere except inside the function. Refer to rule #1, function scope.
class Bar {
protected $b = 'bar';
public function baz() {
$this->b; // bar
}
}
$bar = new Bar;
$bar->b; // doesn't work
If the visibility is not public, the property (here b) is not accessible from outside the class itself. Inside the class you can access it using $this->b, but not from outside using $bar->b. It's not about scope, but visibility.
And that's pretty much the scope rules in PHP.
First of all your example is invalid code
PHP does not support nested classes, meaning a class within a class.
if you define a class, a variable initialized within a method is local to that method, while you can "initialize" an attribute with $this->newattribute, you should have declared it and its visibility before (before you write a method public / private / protected $varname = "initial value";).
Your questions 3 and 4 would make sense in another context, this is when an object is passed as member of another object, see example below.
If you build it like
<?php
class First {
public $second;
}
class Second {
public $a_variable;
}
$foo = new First();
$foo->second = new Second();
you can access it:
$foo->second->a_variable = "foo";
or within a method in second with
$this->a_variable;
or within a method in first with
$this->second->a_variable;
You should NOT be nesting classes like that. That shouldn't even run. I would suggest running the code first. There are some tools online for testing small snippets of PHP code, such as this.
For the code to run as you might expected it to, it should look like this:
class second{
public function widgets(){
$a_variable = $a_value;
}
}
class first{
public $second;
public function __construct() {
$this->second = new second;
}
}
$first = new first;
A variable that begins with $[a-z]+ is local to the function. A property beginning with $this->[a-z]+ (where [a-z] is 1 or more letters) is part of the object.
There's some documentation on php.net that goes over the specifics of objects in php here.
If I initialize $a_variable as $a_variable it is only available inside
the function, correct?
Yes, correct. It begins with $[a-z]. Not quite true if you use the global keyword, but that's discouraged.
If I initialize $a_varialbe as
$this->a_variable it is only available inside class second, correct?
Yes, but you should declare it first. You can do this with public $variable, protected $variable or private $variable. public means a property can be accesses from the outside, whereas private means only the class itself can access it. protected is private to the outside, but public to classes that extend from your class.
(public/private/public became available in PHP 5. In PHP 4 you would use var $variable, which defaults to public in PHP 5)
Can I initialize $a_variable as $first->second->a_variable?
You can arbitrarily initialize class variables without declaring them, but that's not something you should be doing.
If so, How would I call it at #1, #2, and #3?
You can't call code there (in your example). Code must be inside a function or in the global context (outside of the class definition).
A Brief Explanation of Classes
class foo{
// This can be accessed anywhere
public $i_am_public;
// This can be accessed within this class and any sub classes
protected $i_am_protected;
// Thi can only be accessed within this class
private $i_am_private;
// This function can be accessed anywhere
public function foo_function(){
// This variable is only available in this function
// it cannot be accessed anywhere else
$variable = 'Hello World';
// However, you can access any of the other variables listed above
// like so
$this->i_am_public = 'public';
$this->i_am_protected = 'protected';
$this->i_am_private = 'private';
// Write these variables
echo $this->i_am_public;
echo $this->i_am_protected;
echo $this->i_am_private;
}
}
$foo = new foo;
$foo->foo_function();
// You can change any publicly defined variables outside
// of the class instance like so
$foo->i_am_public = 'testing';
Specific Answers to Questions
Before I go any further, I would hugely urge you not to define a class within a class! Instead, use class extensions which I will explain later. In fact, I am surprised your code even works!
If I initialize $a_variable as $a_variable it is only available inside
the function, correct?
Yes, this will only be available inside the function. If you want to access it outside of the function then you need to define it outside the function using one of the scope definitions public, protected, private.
If I initialize $a_varialbe as $this->a_variable it is only available
inside class second, correct?
This depends on what scope you give it, but you shouldn't be defining a class within a class anyway.
Can I initialize $a_variable as $first->second->a_variable? If so, How
would I call it at #1, #2, and #3?
I cannot answer this as I have never nested a class within a class, once again I would urge you to change this structure.
Can I initialize $a_varialbe as $this->second->a_variable? If so, How
would I call it at #1, #2, and #3?
Please see above answer :-)
Nesting Classes
As mentioned, I have never seen this before, and I am surprised it even works. You should definitely change this structure.
One suggestions would be to use extensions like so:
class foo{
// This can be accessed anywhere
public $i_am_public;
// This can be accessed within this class and any sub classes
protected $i_am_protected;
// Thi can only be accessed within this class
private $i_am_private;
public function foo_function(){
echo 'Hello World';
}
}
class bar extends foo {
// This is a public function
public function baz(){
// These will work
$this->i_am_public = 'public';
$this->i_am_protected = 'protected';
// This will not work as it is only available to
// the parent class
$this->i_am_private = 'private';
}
}
// This will create a new instance of bar which is an
// extension of foo. All public variables and functions
// in both classes will work
$bar = new bar;
// This will work because it is public and it is inherited
// from the parent class
$bar->foo_function();
// This will work because it is public
$bar->baz();
Why in PHP you can access static method via instance of some class but not only via type name?
UPDATE: I'm .net developer but i work with php developers too. Recently i've found this moment about static methods called from instance and can't understand why it can be usefull.
EXAMPLE:
class Foo
{
public static Bar()
{
}
}
We can accept method like this:
var $foo = new Foo();
$foo.Bar(); // ??????
In PHP
the class is instantiated using the new keyword for example;
$MyClass = new MyClass();
and the static method or properties can be accessed by using either scope resolution operator or object reference operator. For example, if the class MyClass contains the static method Foo() then you can access it by either way.
$MyClass->Foo();
Or
MyClass::Foo()
The only rule is that static methods or properties are out of object context. For example, you cannot use $this inside of a static method.
Class Do {
static public function test() {
return 0;
}
}
use like this :
echo Do::test();
Why in PHP you can access static method via instance of some class but not only via type name?
Unlike what you are probably used to with .NET, PHP has dynamic types. Consider:
class Foo
{
static public function staticMethod() { }
}
class Bar
{
static public function staticMethod() { }
}
function doSomething($obj)
{
// What type is $obj? We don't care.
$obj->staticMethod();
}
doSomething(new Foo());
doSomething(new Bar());
So by allowing access to static methods via the object instance, you can more easily call a static function of the same name across different types.
Now I don't know if there is a good reason why accessing the static method via -> is allowed. PHP (5.3?) also supports:
$obj::staticMethod();
which is perhaps less confusing. When using ::, it must be a static function to avoid warnings (unlike ->, which permits either).
In PHP, while you're allowed to access the static method by referencing an instance of the class, you don't necessarily need to do so.
For example, here is a class with a static function:
class MyClass{
public static function MyFunction($param){
$mynumber=param*2;
return $mynumber;
}
You can access the static method just by the type name like this, but in this case you have to use the double colon (::), instead of "->".
$result= MyClass::MyFunction(2);
(Please note you can also access the static method via an instance of the class as well using "-->"). For more information: http://php.net/manual/en/language.oop5.static.php
In PHP 7 it seems to be absolutely necessary for you to be able to do $this->staticFunction(). Because, if this code is written within an abstract class and staticFunction() is also abstract in your abstract class, $this-> and self:: deliver different results!
When executing $this->staticFunction() from a (non-abstract) child of the abstract class, you end up in child::staticFunction(). All is well.
However, executing self::staticFunction() from a (non-abstract) child of the abstract class, you end up in parent::staticFunction(), which is abstract, and thusly throws an exception.
I guess this is just another example of badly designed PHP.
Or myself needing more coffee...
In JS you can access methods in this fashion: ParentObject.ChildObject.ChildObjMethod() -- can same be done in PHP?
Not exactly. The :: operator is for invoking static methods on a class. So, you could store a reference to an object statically, but then you'd need to invoke the method with a -> operator.
<?php
class Foo
{
static public $bar;
static public function initStaticMembers()
{
self::$bar = new Bar();
}
}
class Bar
{
public function method()
{
echo "Hello World\n";
}
}
Foo::initStaticMembers();
Foo::$bar->method();
There's no way to do
Object::ChildObject::method();
Method chaining is essentially a shortcut for something like
$o = Object::ChildObject;
$o::method();
The first call is made, and returns or assigns something. The next method is then called on the thing that's returned. You can't store a class in a variable with PHP, or return a class from a function. Therefore, the exact syntax for what you're asking to do is impossible.
That said, method chaining is becoming more popular in PHP. Syntax like the following
$o = new Baz();
$o->method()->anotherMethod()->yetAnotherMethod();
$o->someObjectReference->methodCall()->etc();
is becoming common place. This works because each call or variable reference
$o->method();
$o->someObjectReference;
returns another Object instance, which can then have a method called on it.
The :: can be used for accessing static class members. But you can also access instantiated childobjects in PHP, using the normal -> arrow thingy:
$parent->child->child_method();
See also Reference - What does this symbol mean in PHP?
I have seen function called from php classes with :: or ->.
eg:
$classinstance::function
or
$classinstance->function
whats the difference?
:: is used for scope resolution, accessing (typically) static methods, variables, or constants, whereas -> is used for invoking object methods or accessing object properties on a particular object instance.
In other words, the typical syntax is...
ClassName::MemberName
versus...
$Instance->MemberName
In the rare cases where you see $variable::MemberName, what's actually going on there is that the contents of $variable are treated as a class name, so $var='Foo'; $var::Bar is equivalent to Foo::Bar.
http://www.php.net/manual/en/language.oop5.basic.php
http://www.php.net/manual/language.oop5.paamayim-nekudotayim.php
The :: syntax means that you are calling a static method. Whereas the -> is non-static.
MyClass{
public function myFun(){
}
public static function myStaticFun(){
}
}
$obj = new MyClass();
// Notice how the two methods must be called using different syntax
$obj->myFun();
MyClass::myStaticFun();
Example:
class FooBar {
public function sayHi() { echo 'Hi!'; }
public /* --> */ static /* <-- */ function sayHallo() { echo 'Hallo!'; }
}
// object call (needs an instance, $foobar here)
$foobar = new FooBar;
$foobar->sayHi();
// static class call, no instance required
FooBar::sayHallo(); // notice I use the plain classname here, not $foobar!
// As of PHP 5.3 you can write:
$nameOfClass = 'FooBar'; // now I store the classname in a variable
$nameOfClass::sayHallo(); // and call it statically
$foobar::sayHallo(); // This will not work, because $foobar is an class *instance*, not a class *name*
::function is for static functions, and should actually be used as:
class::function() rather than $instance::function() as you suggest.
You can also use
class::function()
in a subclass to refer to parent's methods.
:: is normally used for calling static methods or Class Constants. (in other words, you don't need to instantiate the object with new) in order to use the method. And -> is when you've already instantiated a object.
For example:
Validation::CompareValues($val1, $val2);
$validation = new Validation;
$validation->CompareValues($val1, $val2);
As a note, any method you try to use as static (or with ::) must have the static keyword used when defining it. Read the various PHP.net documentation pages I've linked to in this post.
With :: you can access constants, attributes or methods of a class; the variables and methods need to be declared as static, otherwise they do belong to an instance and not to the class.
And with -> you can access attributes or methods of an instance of a class.
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