__callStatic(): instantiating objects from static context? - php

I am confused about how "static" and "dynamic" functions and objects in PHP work together especially with regards to __callStatic().
How __callStatic() works:
You can have a normal class MyClass, where within the class you can
put a static function called __callStatic(), which gets called only
when MyClass doesn't have a static function by the name you want.
i.e. I call MyClass::newFunction();
newFunction() is called statically but MyClass does not
have it declared. So, then __callStatic() gets called and
inside you can say
$myObject=new SomeOtherClass();
$myObject->newFunction();
which calls the function you wanted but on some other object.
Short Version:
In other words, __callStatic() does this:
MyClass::newFunction();
which is hiding this:
(new SomeOtherClass())->newFunction();
Say what now? What looks like code calling a static function from a class, turns out to be calling that function from some other class and calling it via instantiation, and not statically.
Explain this, please!
Why was it done? Can you do anything like this elsewhere, like C++ or Java? I am looking for short & concise, but informative explanation on static and dynamic functions in languages, and in this case whether __callStatic() violates or conforms to the big picture of Language constructs. Or is it a new language construct entirely.

__callStatic() provides developers with possibility to react on static method calls even if that methods don't exist or aren't accessible from outside of the class ( being protected). This is useful for dynamic, generic code generation.
Example: You have this class:
class Test {
protected static function myProtected($test) {
var_dump(__METHOD__, $test);
}
public static function __callStatic($method, $args) {
switch($method) {
case 'foo' :
echo 'You have called foo()';
var_dump($args);
break;
case 'helloWorld':
echo 'Hello ' . $args[0];
break;
case 'myProtected':
return call_user_func_array(
array(get_called_class(), 'myProtected'),
$args
);
break;
}
}
}
Try to call:
// these ones does not *really* exist
Test::foo('bar');
Test::helloWorld('hek2mgl');
// this one wouldn't be accessible
Test::myProtected('foo');

Why was it done?
This is an existential question, but I think that the answer is "because you can". PHP is a dynamic language and these constructs __call and __callStatic() show off its power, and this power can be useful in some situations.
Can you do anything like this elsewhere, like C++ or Java?
No. They have no similar magic methods.
I am looking for short & concise, but informative explanation on static and dynamic functions in languages
Static functions encapsulate code. They exist even when no class has been instantiated. You can call them using scope resolution operator.
Dynamic functions are well, dynamic
.. does __callStatic() violate or conform to the big picture of Language constructs. Or is it a new language construct entirely.
It is a construct of a dynamic language. Not sure if this functionality exists in all dynamic languages, but it does in PHP. It does not violate anything, just introduces new paradigm of fall-through catch-all functions when the function you do call does not exist/not accessible in current scope.

I'm not entirely sure why __callStatic() is relevant here?
I don't quite see the difference between:
class Foo {
static function bar() {
$obj = new Foo();
$obj->quux();
}
function quux() {
return "whatever";
}
}
and your example? In both scenarios you're calling a static method which is calling another method on an object of the same class.
Yeah, that's possible. Actually doing it suggests you might want to refactor your code though. In the example you're instantiating an object with its default state, executing a method on it and then throwing the object away. This suggests whatever the method is doing doesn't actually need the objects state. That means it either doesn't belong in this class or could simply be rewritten to be a static method itself.
And are you aware of __call? It does the same thing as __callStatic but for objects rather than classes. E.g. $foo->myMissingMethod(); would go to __call if such a method exists for the class of which $foo is an instance.

Related

Method invocation in PHP

I have TestClass and a public method in it.
I am able to call the same method using :: operator like static method and using an object.
What are the advantages or use of static functions in PHP, if we able to call public functions without creating object of the same class?
<?php
class TestClass {
public function testMethod() {
echo 'Method called';
}
}
TestClass::testMethod();
$classObj = new TestClass();
$classObj->testMethod();
?>
In this case, there is no difference.
However, the point of static functions is to say that some functions don't need an instance of the class in order to be executed. It is possible to call functions statically even if they are not marked as static, but it is technically incorrect to do so. If you have error_reporting(E_ALL) set, it will give you a strict standards error.
This is not because the code won't work, but because it might not.
class TestClass {
private $name = 'Rakesh';
public function doSomething() {
echo "Hi there";
}
public function doSomethingElse() {
echo "Hi there " . $this->name;
}
}
You can call the first function statically and it will work fine. But if you call doSomethingElse statically, it won't work, because it tries to access $this, which is only possible if you have an object.
So we apply the static keyword to doSomething to let (a) PHP and (b) the programmer using the class know that it is possible to call it statically. It's a promise that it will work.
The assumption should be that, if it is not marked as static, you shouldn't call it statically.
PHP's strict standards errors are meant to make your code better, even if it already works. The documentation for the E_STRICT constant says:
Enable to have PHP suggest changes to your code which will ensure the best interoperability and forward compatibility of your code.
In low-level terms, a static function in PHP isn't much different than a member function. The only real difference is that $this isn't provided to a static function.
That means the use of the static keyword is mostly of semantic benefit, as it helps you define the architecture and intended behaviour of your classes.
With that said, you shouldn't abuse the semantics. PHP can (optionally) warn you about those kinds of mistakes, and you should always pay attention to such warnings. The language specification is there for a reason, and it's designed to work in certain ways. If you use static (or any other language feature) incorrectly, then it may not always work as you expect. Future PHP updates or configuration changes could break your code unexpectedly.
Declaring class properties or methods as static makes them accessible without needing an instantiation of the class. A property declared as static can not be accessed with an instantiated class object (though a static method can).
For compatibility with PHP 4, if no visibility declaration is used, then the property or method will be treated as if it was declared as public.
Advantages are ...
1>Hash memory will not create ,hence no wastage of Memory (no memory leak problem)
2>
// This makes little sense
Math m = new Math();
int answer = m.sin(45);
// This would make more sense
int answer = Math.sin(45);
It's like a shortchut, one feature more of php. But, to access to their properties you must declare them like constants. For example:
<?php
class Math{
const pi=3.1416;
}
echo Math::pi;
?>

Difference in Class Calling PHP

With learning fuelPHP, I am introduced on calling classes using scope resolution, or :: in sense. Typically, when we call a method in a class we do this ...
$myclass = new myclass();
$myclass->mymethod();
On fuel, methods are usually called in this manner ...
myclass::mymethod();
I was wondering if there are any difference between the two? Is the scope resolution is something of an update on 5.3 as well ... if not, which one is ideal, or when should I use these.
Thanks.
The scope resolution operator is used to access either class constants like ::const, static variables like ::$var or call static methods like ::method().
See http://php.net/manual/en/language.oop5.static.php
Static methods can be called without having an instance of the class they are defined in. They're defined in that class with the static keyword.
For example, one of CakePHP's static methods is defined like this:
class ClassRegistry {
// ...
public static function &getInstance() {
// ...
}
}
... which you can call like ClassRegistry::getInstance().
Without the static keyword, you'd need an instance of the ClassRegistry class to call that function.
You can read more here, especially about why using static methods in your own code can sometimes be a bad idea: http://kore-nordmann.de/blog/0103_static_considered_harmful.html
I am not sure how would myclass::mymethod(); work, since I use such syntax only when I am calling a STATIC class.
MyClass::DoSomething();
would call a static method named DoSomething()
while
$instance = new MyClass();
$instance->DoSomething();
would call the instance method.
I have not tested it but I believe you will run into an error if you do $instance::DoSomething()
I think the best way to understand why there is a static call and what it does behind the scene is to check this FuelPHP blog's entry: http://fuelphp.com/blog/2011/05/why-did-you-do-that
The obvious difference is that the first solution $myObject->myMethod() it's a dynamic call : you need an instance to execute myMethod().
In the second solution, MyClass::myMethod() is a static call. The class acts as a sort of namespace where a function belong. You don't need an instance for that.

what's the point of declaring static functions in PHP?

So in PHP you can have
Class A{
function B(){}
}
and you can call this as if it were a static function:
A::B();
My question is...if I can do this, then why should I ever declare the function B() as static since doing so makes $this unavailable, so there's less flexibility, so you have everything to lose but nothing to gain...
or is there an advantage of declaring the function as static that I'm not aware of?
also I heard that "static calling of non static methods" are "deprecated"....what does that exactly mean especially in relation to this scenario? is calling A::B() when B() is not declared static something that I shouldn't be doing? if so, why is that the case?
Because PHP tends to be a bit loosy-goosy around strictness (?) these sort of things work. The fact that they are deprecated means that sometime in a future release, it is likely not to work anymore. So if you are calling a non-static function in a static context, your program may break in a future PHP upgrade.
As for using it right now - the advantage to declaring a function as static is that you are deciding right there how that function should be used. If you intend to use a function in a static context, you can't use $this anyway, so you are better of just being clear on what you plan to do. If you want to use the function statically, make it static. If you don't, then don't. If you want to use a function both statically and non-statically, then please recheck your requirements :P
For compatibility mode. Now calling non-static methods statically generates an E_STRICT level warning.
Why static and not instantiate the object? Each programmer will tell you a reason. I particulary preffer instantiate object than use static methods. It's clear, traceable and more reusable.
I did a test bench and the difference was minimal between instantiate and call a method than call it staticaly.
Tip: if you foresee calling methods statically defines them as well;-)
First off, you couldn't do stuff like that in your post in a strict typed language like Java. Java code doesn't compile, if you call non-static stuff in a static context. PHP is not that strict on these things (yet), but still you shouldn't do things just because you can, although it's bad practice and in some languages even 'incorrect' practice.
There sure are advantages using static methods. And it's not quite right that you gain nothing or even lose flexibility. Let's have an example:
class A {
private static $prop_a = 'property_a';
public static function b() {
echo 'called b()';
echo self::$prop_a;
$A = new A();
$A->c();
}
public function c() {
echo 'called c()';
}
}
Now we can call the class this way:
A::b();
which outputs
called_b
property_a
called_c
But you can do the same with:
$a = new A();
$a->b();
$a->c();
c() is executed twice now, but you get the idea. Within your class, you can instanciate the class itself and work with it like with a regular object. But from outside, it's simply one line of code while it's 3 lines using the non-static way. Pretty cool, huh?
And as you see, you can use the static function in a non-static context, which means, you can declare your method static, but if you instanciate your class, you can simply call it like a regular method. Sounds pretty flexible to me ;)
And no, you can't use $this in a static context, but that's what self is for ;)
If it is a static function you don't have to instantiate the class in order to use the method.
Class A {
static function hello($arg)
{
echo 'Hello, ' . $arg;
}
}
A::hello('world');
VS
Class A {
public function hello($arg)
{
echo 'Hello, ' . $arg;
}
}
$a = new A;
$a->hello('world');
The important thing here is the instantiation of the object. After you've instantiated an object, it can be manipulated, and calling your methods may yield unexpected results. If your values and functions are statically declared in the class, they cannot be modified at the time you call the function.
This is not to say they you should always use static methods either. take the following example.
class My_math {
static function pi()
{
return 3.14
}
}
class My_bakery {
private var $pie;
function set_pie($pie)
{
$this->pie = $pie;
}
function pie()
{
echo "I made you a " . $this->pie . "pie";
}
}
I've made My_Math return a constant value, because I know pi doesn't change. But in My_bakery, some days I want blueberry pie and some days I want peach pie.

PHP and Python static methods in objects, two different worlds...?

i'm php coder, trying to get into python world, and it's very hard for me.
Biggest enjoy of static methods in php is automatic builder of instance. No need to declare object, if you needed it once, in every file (or with different constructor params , in one line)
<?php
class Foo {
function __constructor__(){
$this->var = 'blah';
}
public static function aStaticMethod() {
return $this->var;
}
}
echo Foo::aStaticMethod();
?>
we can call constructor from static method don't we? and we can access everything in class as it would be simple method ... we can even have STATIC CONSTRUCTOR in php class and call it like so: Object::construct()->myMethod(); (to pass different params every time)
but not in python???? #staticmethod makes method in class a simple function that doesn't see totally anything ??
class socket(object):
def __init__(self):
self.oclass = otherclass()
print 'test' # does this constructor called at all when calling static method??
#staticmethod
def ping():
return self.oclass.send('PING') # i can't access anything!!!
print Anidb.ping()
I can't access anything from that god damned static method, it's like a standalone function or something like this..??
Maybe I'm using the wrong decorator? Maybe there's something like php offers with static methods in python?
1) Please tell why static methods is isolated
2) Please tell me how to make the same behavior like php static methods have.
3) Please tell me alternative practical use of this, if php static methods behavior is a bad thing
P.s. the goal of all this to write totally less code as much as possible.
P.p.s Heavy commenting of sample code is appreciated
Thank you.
static methods in PHP are not as you believe, they can't access to instance members. No $this! with them.
<?php
class Foo {
public static $var = 'foo ';
function __construct(){
echo 'constructing ';
$this->var = 'blah ';
}
public function aMethod() {
return $this->var;
}
public static function aStaticMethod() {
#return $this->$var; -> you can't do that,
# $this can be accessed only in instance methods, not static
return self::$var;
}
}
$foo = new Foo();
echo $foo->aMethod();
echo Foo::aStaticMethod();
?>
Python has three kind of methods in objects static methods are like functions defined ouside classes, the only use to put them in object is to keep them with the class as helper functions. class methods can access only to variables defined in the class (decorator #classmethod). This is more or less what PHP calls static members or methods. The first parameter of such methods sould be cls, and content of class can be accessed through cls. Normal methods must get self as first parameter and are the only ones to be able to access to instance members.
If you want several objects of the same type you definitely need instances, and the other types are not what you are looking for. If you only have one instance of an object, you could use class methods instead (or PHP static methods).
But in most case you should not bother doing that if you don't know why and just stick with instances of objects and normal methods, doing otherwise is premature optimization and your code is likely to bite you later because of the many restrictions you introduce.
You want classmethod instead. That provides the class as the first argument.
EDIT:
class C(object):
foo = 42
#classmethod
def printfoo(cls):
print cls.foo
C.printfoo()
I see you've already accepted another answer, but I'm not sure that it will work with your code. Specifically, the oclass variable is only created for instances of the class, not for the class itself. You could do it like this:
class socket(object):
oclass = otherclass()
#classmethod
def ping(cls):
return cls.oclass.send('PING')
socket.ping()
However, using your existing code and removing all decorators, you could simply instantiate it and use a method on the same line:
socket().ping()

Static or not static?

What is better to use in this context, static methods, or simple public method and call them always like this: $request = new Request();
if($request->isPostRequest()){ do smth }
ofcourse its easier to use static, but what is more properly to use?
Class Request {
public static function isSecureConnection() {}
public static function isPostRequest() {}
public static function isAjaxRequest() {}
...etc
}
If each Request is a genuine entity, then it would be better to use non-static members. But if it's not and methods are used in general, like Sinus function in math, then they'd be better to be static.
Overall it'd be better to declare static functions in a class that is just consisted of functions and no data members.
You should always create a class like if it was to be used on a non-static environment.
Then you can use that as a Singleton with lazy-instantiation. Or even as a Static class instantiation. Or even as a Standalone instance object. You decide later what to do with it.
If you start by declaring all members as static you are basically just covering a bunch of Global variables inside a glorified namespace known as a Class. You also will statically allocate the memory used by that class even if you don't call it or use it in your code.
So, just write as a Class, then you decide what to do with it. Static/Non-Static. Singleton/Instance. Factory Pattern or not. Memory Allocator X/DLL bound or whatnot.
The only exception is static members used for book-keeping in behalf of the Object Instances; things like reference counting, caches and things like that. That is the good thing about static/non-static, you can mix and match for some clever behaviors.
What if later you wanted another Request? Or what would happen if you can create more than one because you are in a multithreaded environment? Things will get really strange once you go that route with statics.
It looks like you are handling one particular request.
Now this insinuates you should make it a singleton, and/or use static functions.
Reason:
There is only one request, all the state is defined by the environment delivered to the process. The class methods are just helper functions, and you want to be able to use them without class instance.
On the other hand, you would rarely use static functions with classes that represent one of many, for example one user of many, one question of many.
Declaring class properties or methods as static makes them accessible without needing an instantiation of the class. A property declared as static can not be accessed with an instantiated class object (though a static method can).
Example:
<?php
class Foo {
public static function aStaticMethod() {
// ...
}
}
Foo::aStaticMethod();
$classname = 'Foo';
$classname::aStaticMethod(); // As of PHP 5.3.0
?>
See the reference of Static Keyword from php.net.
If you can, use static methods as a default. static methods run quicker than their non-static counterparts.

Categories