I've seen this use of syntax a few times on the Yii framework. I tried searching for an explanation but got no examples. A link will be nice if possible. It goes something like class::model()->function();
My understanding is that model is an object of class therefore it can access the function. So I tried to code it but I get " Call to a member function sound() on a non-object in". Here's my code
class animal
{
private static $obj;
public static function obj($className = __CLASS__)
{
return self::$obj;
}
public static function walk()
{
return "walking";
}
}
include('animal.php');
class cat extends animal
{
public static function obj($className = __CLASS__)
{
return parent::obj($className);
}
public static function sound()
{
return "meow";
}
}
echo cat::obj()->sound();
Also what benefits does it have?
That is called an object operator and this, ->, calls a class method from your created object which is defined in that class.
Here is an explanation and some examples.
$obj = new Class; // Object of the class
$obj->classMethod(); // Calling a method from that class with the object
echo cat::obj()->sound();
This will display the output of the sound() method, called on the object that is returned from cat::obj().
The reason it's failing for you is because cat::obj() is not returning a valid object.
And the reason for that is because the obj() method returns the static obj property, but you're not actually setting that obj property anywhere.
The pattern you're trying to use here is known as a "Singleton" object. In this pattern, you call an obj() method to get the single instance of the class; every call to the method will give you the same object.
However the first call to the method needs to instantiate the object; this is what you're missing.
public static function obj($className = __CLASS__){
if(!static::$obj) {static::$obj = new static;}
return static::$obj;
}
See the new line where the object is created if it doesn't exist.
Also note that I've changed self to static. The way you're using this with class inheritance means that you probably expect to have a different static object for each class type, self will always return the root animal::$obj property, whereas static will return the $obj property for whichever class you're calling it from.
There are a few other bugs you need to watch out for too. For example, you've defined the sound() method as static, but you're calling it with ->, so it shouldn't be static.
Hope that helps.
The cat::obj() returns you a object of the type cat. With ->sound(); you're executing the function sound() from the class cat. All that should return "meow".
cat::obj() returns an object; ->sound(); execute a method of this object. Equivalent is
$o = cat::obj();
$o->sound();
Related
Looking for a clean way to determine the class (in this case, either parent or child class) of the method that calls a method in the parent class.
I thought late static binding could handle this, but seems like that only really works for calling a static method directly, and not from within an instantiated object's method.
Consider the following:
abstract class ParentClass {
public function parentMethod() {
self::_log("parent.non.static");
}
public static function parentStatic() {
self::_log("parent.static");
}
public static function getClassName() {
return __CLASS__;
}
protected static function _log($key) {
$prefix = 'graphite.key.prefix';
$class = static::getClassName(); // gets the object's class, not calling class
$g_key = "{$prefix}.{$class}.{$key}";
echo "{$g_key} \n";
// Graphite::increment($g_key);
}
}
class ChildClass extends ParentClass {
public function childMethod() {
self::_log("child.non.static");
}
public static function childStatic() {
self::_log("child.static");
}
public static function getClassName() {
return __CLASS__;
}
}
$obj = new ChildClass;
$obj->childMethod(); // graphite.key.prefix.ChildClass.child.non.static
$obj->parentMethod(); // graphite.key.prefix.ChildClass.parent.non.static
ParentClass::parentStatic(); // graphite.key.prefix.ParentClass.parent.static
ChildClass::childStatic(); // graphite.key.prefix.ChildClass.child.static
Looking for a clean way to get the class that calls the _log() method without having to pass it in as a parameter. Doesn't have to be static at all, but I was playing around with the late static binding, because I thought that would work, but it just gets the name of the instantiated object, not the child/parent class of the method that calls the _log() method :-/
Edit:
Just to be clear, I'm after getting the class name of the method that called _log() from within the instantiated object (like parentMethod() and childMethod()) Don't care if _log() is static or not. If that makes it easier, fine. But the static ParentClass::parentStatic() and ChildClass::childStatic() were just to show late static bindings and what I figured might work, but not from calling within an instantiated object
http://php.net/manual/en/function.get-called-class.php
class One {
public static function test() {
echo get_called_class() . PHP_EOL;
}
}
class Two extends One {}
One::test();
Two::test();
Output:
One
Two
Also, according to the top comment in the docs static::class also works as of PHP 5.5.
get_class will get the class name of a class instance. This can also be called on $this within a class. If you have a class that extends/implements another, $this will refer the the instantiated class, meaning the child class.
Another option is to use debug_backtrace to get the stack of functions that lead up to where you currently are. You can parse the returned array to get whatever you need including line numbers, classes, functions, methods, whatever.
I understand why there should be no return values in constuctor, because it will not return any.
But still I see exactly this in a lot of scripts on the internet and I haven't managed to find an answer and it's buggin me for a while. If anyone would be kind enough to explain me, I would really apreciate.
Code I am refering to:
function __construct() {
return;
}
Actually, you may (no error will be occurred) use the return keyword in the __construct method but (you don't) that would be useless and won't return anything.
The __construct method doesn't create an object instance
It's not true that, the constructor creates the object instead, it's the new keyword which creates an object instance and returns the object. So, when we use something like this:
$obj = new SomeClass;
Then PHP creates the object returns the object instance. If this class contains any constructor method then this method is called by PHP after creation of that object instance. So, you can imagine, something similar:
class SomeClass {
public $prop = null;
public function init() {
$this->prop = 'SomeValue';
}
}
Now create the object and call the init method manually
$obj = new SomeClass;
$obj->init();
We created an instance of SomeClass and called the init methos manually but in the case of __construct method PHP calls the method automatically just after the creation of that object. So, we don't have to manually set the value to the prop property.
So, before the __construct method is called the object instance is created and without creating the object instance, the __construct method couldn't be called by PHP because $this refers to current object which is already created and if the object is not initialized then how can we call:
public function __construct()
{
$this->prop = 'SomeValue'; // $this refers to current object
}
The new keyword always returns an object instance:
Let's see this example:
class SomeClass {
public $prop = null;
public function __construct() {
$this->prop = 'SomeValue';
return $this->prop; // won't work
}
public function getProp() { ... }
}
Now check this:
$obj = new SomeClass;
If we were able to return a value from the constructor then how could we use the object instance using something like $obj->getProp() because logically it would contain SomeValue instead of the object reference/identifier, so it makes sense that PHP should not allow to return anything from the __construct method because this magic method get called automatically just after the creation of the object and we use new keyword to create the object instance that returned to us (into a variable) by the new keyword and if we return anything from the __construct method, it prevented by PHP and only an instance of the created object is returned if we didn't throw an exception explicitly.
To create an instance of a class, the new keyword must be used. An
object will always be created unless the object has a constructor
defined that throws an exception on error. Reference:PHP Manual
Though it's possible to use the return in the __constructor but it would be meaningless for example, check this:
class SomeClass {
public function __construct() {
return 'SomeValue'; // won't work
// or blank return
return;
}
}
Perhaps, you may do this (only for example):
class SomeClass {
public function __construct() {
if('some condition does not met then ...') return;
$this->prop = 'Prop is set';
}
public function doSomething(){
return $this->prop ? $this->prop : 'Sorry! Prop is set.';
}
}
Now try this:
$obj = new SomeClass;
echo $obj->doSomething();
If we just return before the second line in the constructor then the property won't be set otherwise the property will be set and doSomething method will output Prop is set. This may not a good way but for the example, I think this could be a valid code where return will stop execution of rest of the code. But it's not a good idea and maybe not required but for he sake of the example I can think the use of return, otherwise there is no need to use the return keyword in constructor and if someone uses it then it could be a personal choice of style or I don't know why.
That usually is a sign of poor implementation. A constructor "returns" nothing but an instance of it's own class.
Trying to get some data from one method in side static method(using it inside a other class) but I get the 'Using $this when not in object context in...' error.
Below a basic example
class mClass{
public $someVar = 'Hello world...';
public function passFunc(){
$give = $this->someVar;
return $give;
}
public static function showFunc(){
$show = self::passFunc();
return $show;
}
}
mClass::showFunc();// show error: Using $this when not in object context in...
You can't use $this, when you are working with static variables. $this is a pointer to the current object, but static variables belongs to class.
A class method (or static function) isn't tied to a particular instance of your class, i.e. it doesn't have $this although self is available.
A class method can access static properties or methods, but accessing anything else within the class will raise an error. It's best to look at static methods as a means to organize functions; as such, they operate in between external functions and instance methods.
In your case, you'd have to create an instance inside your static method:
public static function showFunc()
{
$o = new self;
$show = $o->passFunc();
return $show;
}
I have a class and it has some static, some not static methods. It has a static property. I'm trying to access that property inside all of it's methods, I can't figure out the right syntax.
What I have is this:
class myClass {
static public $mode = 'write';
static public function getMode() {
return myClass::$mode;
}
public function getThisMode() {
return $this->mode;
}
}
Can anyone tell me the actual syntax for this one?
For static properties use the following even inside a non static function
return self::$mode;
The reason for this is because the static propery exists whether an object has been instantiated or not. Therefore we are just using that same pre-existing property.
If you are outside of the class, make sure not to forget the $ or you will see this error as well. For example, make sure to call it like this:
$myClass = new myClass();
echo $myClass::$mode;
Not like this:
echo $myClass::mode;
I have a question regarding static function in php.
let's assume that I have a class
class test {
public function sayHi() {
echo 'hi';
}
}
if I do test::sayHi(); it works without a problem.
class test {
public static function sayHi() {
echo 'hi';
}
}
test::sayHi(); works as well.
What are the differences between first class and second class?
What is special about a static function?
In the first class, sayHi() is actually an instance method which you are calling as a static method and you get away with it because sayHi() never refers to $this.
Static functions are associated with the class, not an instance of the class. As such, $this is not available from a static context ($this isn't pointing to any object).
Simply, static functions function independently of the class where they belong.
$this means, this is an object of this class. It does not apply to static functions.
class test {
public function sayHi($hi = "Hi") {
$this->hi = $hi;
return $this->hi;
}
}
class test1 {
public static function sayHi($hi) {
$hi = "Hi";
return $hi;
}
}
// Test
$mytest = new test();
print $mytest->sayHi('hello'); // returns 'hello'
print test1::sayHi('hello'); // returns 'Hi'
Entire difference is, you don't get $this supplied inside the static function. If you try to use $this, you'll get a Fatal error: Using $this when not in object context.
Well, okay, one other difference: an E_STRICT warning is generated by your first example.
Calling non-static methods statically generates an E_STRICT level warning.
In a nutshell, you don't have the object as $this in the second case, as
the static method is a function/method of the class not the object instance.
After trying examples (PHP 5.3.5), I found that in both cases of defining functions you can't use $this operator to work on class functions. So I couldn't find a difference in them yet. :(