calling static method with static class variable as class name in php - php

I know you can call static methods using variable as class name like so:
$className = "Foo";
$className::Bar(); //works
But when i'm trying to use static property as variable like this:
self::$className = "Foo";
self::$className::Bar(); //doesn't
it gives me the following parse error on line where i'm trying to call the method:
Parse error: syntax error, unexpected '::' (T_PAAMAYIM_NEKUDOTAYIM)
So how can i call that method using static property and is that even possible with syntax somewhat similar to what i described(w/o call_user_func and creating local variable that stores self::$className)?

You could do that:
$tmp = self::$className;
$tmp::Bar();
Edit
Based on your comments it seems your problem is more about OOP design than it is about syntax. Furthermore, you keep adding new restrictions every time a solution is given, which makes it difficult to provide a relevant answer.
Anyway, I'll try to summarize your options. The syntax you want does not exist (at the moment, anyway), so you have to work around it one way or another. Yes, this is annoying, and yes this means that you will have to make concessions. But that's how it is.
Here are your options so far:
Use call_user_func or forward_static_call or similar.
Use a temporary local variable. Possibly wrap that into a method if it's really bothering you (e.g. static function call($method) { $tmp = self::$classname; return $tmp::$method(); } and then use self::call('bar');)
Refactor your object design using instances instead of static methods so that you don't need to do that anymore.
Use some other terribly ugly and dangerous hack (e.g. eval(self::$classname.'::bar();'); and hope it won't come bite you in the butt.

Related

Using Classes / OOP in PHP

I'm pretty proficient with PHP, outside of OOP - which I am just now starting to jump in to.
I've been watching videos and reading tutorials, but they are all still pretty confusing...
If I have
FILE 1 (class.time.php)
class Time {
function GetTime(){
$time = date('H:i:s');
printf($time);
}
}
and then in a nother php page I've got
FILE 2 (page.php)
I can do
include('class.time.php');
and then anywhere in this page I can then do
$time = new Time; //Calling the class and setting the class to a variable
$time->GetTime(); //This is BASICALLY saying (run the 'GetTime' function in the 'Time Class'
My main question is, is the comment above (This is BASICALLY saying.....) correct? or is there a better way to think of it?
regarding method calls
I would make one correction to your statement, hinting a little more accurately at what Object Orientation is all about. Your comment reads:
run the 'GetTime' function in the 'Time Class'
Which is only kinda accurate, and expounding on it may clarify OOP for you. For the purposes of this post, I might rephrase it this way:
run the 'GetTime' method (which is defined in the Time class) bound to the object stored in $time
See the difference? You aren't just calling a function from a class, you are saying "get the processing instructions from the class, but bind those instructions to this specific object and then execute.
It may sound like mincing words, but it's critical to understanding encapsulation. Objects of a class share their method definitions, but they do not share data.
You can think of an object as essentially a set of two things:
A block of memory holding it's own, personal data
A pointer to a set of methods with special access to that data
(the "special" nature of the methods' relationship to the data is either implicit or explicit, it's up to you)
The distinction is readily evident when you start using "member variables" (sometimes called "object properties", "instance variables (aka ivars)", or similar names). Consider this sample code:
class Person {
public $name;
public printName() {
echo $this->name;
}
}
$me = new Person();
$you = new Person();
$me->name = "Chris";
$you->name = "Alex";
$me->printName(); // "Chris"
$you->printName(); // "Alex"
This highlights the fact that each object has it's own memory for instance variables. They share the definition of those variables, as well as the blocks of code written to process those variables.
The special variable $this is of particular interest to my overall intention with this answer: the same variable in the same method definition actually points to a different object depending on which object you call the method on.
regarding new
Now to the previous line, where your comment reads (in regard to $time = new Time):
Calling the class and setting the class to a variable
The way I would phrase it is:
Make an instance of this class, and allow me to access the instance through $time
That word, instance will be a big concept to get solid before moving on. You don't call a class, you call a method, and you don't (in PHP at least) set the value of variables to be a class, you set them to point to instances of the class. Sometimes people use the words instance and object interchangeably, which is fine. But you should not use them interchangeably with the word class.
Let's get technical:
When you use the new operator, technically you are telling PHP to do two things:
grab some fresh memory, exactly enough to store all the member variables defined in the class
call a special method on that new object to allow me to initialize my object
So if you call new twice, you grab enough memory for 2 objects, and so on. PHP uses your class definition to figure out how much memory to allocate for you, and find the special method to call.
That special method is called __construct, and is guaranteed to be called when your objects are created, with that special $this variable pointing to your shiny new memory. Here's a sample of how you might use it:
class Foo {
private $createdTime;
public function __construct() {
$this->createdTime = time();
}
}
$myFoo = new Foo;
Even though you don't see it, __construct() was called and the value of $createdTime was initialized.
Yes, basically your assumption is correct (apart from syntax errors).
However thats not a very good OO design.
Have a look at this, it give some good examples of OO design: http://www.math-cs.gordon.edu/courses/cs211/ATMExample/
That is correct, but the syntax should be:
$time = new Time();
$time->GetTime();
(don't forget the parentheses, otherwise you are referring to class properties)
Also, it is a good idea to declare your methods as public, protected, or private. If you are going to call the GetTime method from outside the class, it would need to be public.
Since in this case "get time" will never change and accepts no parameters, you would do best to put this into a static method, since it's a waste to instantiate a class in this situation
eg:
class Time {
static public function GetTime(){
$time = date('H:i:s');
printf($time);
}
}
Time::GetTime(); // gets the time, no need to do $time = new Time();
In my opinion you are doing it correct, but for using a simple built-in date function, using it via class would probably just over complicate it.
Following is an excellent article for learning OOP in PHP
PHP OOP for beginners

How to use a variable in a namespace?

I'm trying to dig up my long-lost PHP skills and have therefore stumbled on a problem. I have a function that initializes (not sure if it's a correct word for it) a class in the following fashion:
$foo = new \Master\Slave\$bar();
$bar is a defined class, obviously. But the entire thing doesn't work. This only seems to work when I do the following:
$foo = new $bar();
But with my first example, it outputs the following error:
unexpected T_VARIABLE, expecting T_STRING
Which means that I have to manually enter the class name, correct? But, what if I'm a stubborn nerd who doesn't want to and doesn't see the efficiency in it? Hence my question; how to pull this off without getting a bloody error?
UPDATE: Got the thing working with wrapping the \Master\Slave\$bar in a $variable. Not sure if it's the correct way of doing this, but it works and props go to Visual Idiot
Variables never bound to any namespace they will be always in the global scope.
AFAIK, the namespacing does not work the way you are trying to.
This is how you should do it
namespace Master\Slave;
$bar = "theclassname";
class $bar() {
}
Docs

Dynamically Load Class and Access Static Variable in PHP <= 5.2

Edit:
I solved it by getting all of the class variables using get_class_vars(), and then just acquired the correct property from that array, if it existed. Seems simple enough to me; if anyone has a different solution, I'd love to hear it (or read it, I guess..) :)
I'm trying to access a static variable in a dynamically-loaded class as follows:
$file::$disabled
(In the above statement, $file obviously references the name of a class, and $disabled is the static variable I want to access within the class.)
On PHP 5.3, this works fine; as a result of running the above code on lower versions, I get the infamous T_PAAMAYIM_NEKUDOTAYIM error.
How I've usually gotten around this error when working with older versions of PHP is to create a getter function for that variable and get that return value with call_user_func(). However, for ease of use of developers who will be adopting this code, I would like to keep $disabled as a simple variable rather than a function.
I've tried eval() on the statement, only to reach another dead end.
Does anybody know how I can make this happen?
One option would be to use reflection:
$rp = new ReflectionProperty($file, $disabled);
$value = $rp->getValue();
or
$rc = new ReflectionClass($file);
$value $rc->getStaticPropertyValue($disabled);

Getting the variable name of an instantiated class in PHP

Is it possible to get the variable name used to reference an instantiated class from within the class? here's an example of what i mean:
class Test {
function getName(){
//some code here to get the name '$test1' in this example
}
}
$test1 = new Test
It's not a must for this to be possible, but it'd help for a project i'm working on.
You can use the variable $this to reference the object from within itself.
If you want to find the actual name of the variable $test1, it's going to be more difficult (maybe impossible, since the class has no way to know how it is being used in the global scope). But probably not worth it. Most of the time I've seen questions like that asked, people suggest that there's a design flaw and the application should depend on something other than variable names.
You could most likely do it using debug_backtrace(), however this sort of hack is extremely bad practice.

Is it important to explicitly declare properties in PHP?

I have followed a tutorial to create a simple blog writing application in PHP and have modified the classes in this tutorial so that they have additional capabilities. Modifying this very bare bones app has given me a better understanding of how PHP works, however I have run across an interesting situation.
One of the classes in my project has about a half dozen class properties such as public $id, public $author, public $post. These properties are declared at the beginning of this class however I find that if I remove all but one of these properties the app still functions correctly.
Is it wrong to remove a property declaration such as public $datePosted from the beginning of a class if this class still assigns variables to this property like this: $this->datePosted = $someVariableName;
If you try to access a class property which hasn't been declared, PHP will issue a notice:
class Foo { }
var $fu = new Foo();
echo $fu->baz;
Notice: Undefined property: Foo::$baz in blah.php on line 4
If you set a value first ($fu->baz = 'blah') then it won't complain, but that's not a great situation.
You should definitely declare all your class variables (unless of course you want to have some fun with the magic methods)...
it's clearer for anyone reading your code that the members have been explicitly defined as public rather than just defaulting to it because you haven't assigned them as being public members.
Also, $this->$datePosted is wrong, it should be like this:
$this->datePosted = $someVariable;
which may be why you are experiencing an error.
PHP is really loose about how it handles class member definitions. You technically don't have to declare them. But you should, for two big reasons:
People with smart IDE's (Eclipse, Aptana, Zend Studio) will love if they can take advantage of their editor's code intellisense (auto-complete) while working with your classes. This feature really helps prevent against bugs involving typos. If you don't declare your fields, the IDE has no real way of determining the class' fields.
Someone just getting done working with a compiled language (C++) will likely send a hitman after you if they see a lack of properly-defined fields. It's just good practice to declare them. There's no reason not to.
Also, if you remove declaration and the code reads this variable prior to writting to it, you will have an error like
PHP Notice: Undefined property:
A::$unexistent in C:\temp\test.php on
line 8
Notice: Undefined property:
A::$unexistent in C:\temp\test.php on
line 8

Categories