I was wondering if there is a shorter, better or cleaner way to assign and use class variables in PHP, then through $this->instance_variable ?
class Bar {
# internal variables
var $foo = "Hello World";
public function foo() {
return $this->foo;
}
}
I am not very familiar with all PHP's variable scoping, but from what I understood at the official docs, you can either define them global, or access them trough $this->?
Is there a keyword to define them as instance variable, so they are accessible like Rubys #variable?
There's a few key assumptions your'e bringing from ruby that don't translate well into PHP.
The correct way to declare and use object properties (equivalent to Ruby's instance variables) in PHP is
class Foo
{
//accesible from inside this objects of this class,
//objects that have this class as an ancestor, and from
//outside the object
//var $bar; is equivalent. "var" is PHP 4 syntax,
//when everything was public
public $bar;
//accesible from inside this objects of this class,
//objects that have this class as an ancestor
protected $baz;
//accesible from inside this objects only
private $fiz;
protected function example()
{
echo $this->bar . "\n";
echo $this->baz . "\n";
echo $this->fiz . "\n";
}
}
PHP's OO syntax is based on the Java/C# view of the world. However, because every PHP page/script/program starts off in the global score, the $this pseudo reference to the local object is needed. Without it, you'd create a large degree of ambiguity around situations like this
//In main.php
$foo = "bar";
include('example.php');
//in example.php
class Example
{
public $foo="baz";
public function scopeIsHardLetsGoShopping()
{
global $foo;
echo $foo;
}
}
So, in the method should the $foo referenced be the object variable, or the global variable? If you say it should be the object variable, how do you access the global foo from a method? If you say it should be the global variable how do you access the local property after declaring a variable with the same name global?
Ruby and python gave scoping some thoughts at the onset of the language, so these problems can be avoided. PHP started as a quick way to hack in some c-code to process forms and output HTML. Because PHP makes reasonable efforts to be backwards compatible, you end up with quirky work arounds like $this.
Coming form Ruby it seems a little verbose, but it's a fundamental part of PHP.
PHP instance properties are accessed via the $this->variable operator internally, and public properties as $object->property.
You can access a class variable internally via self::$variable, which is similar to Ruby's class variables. Discussion of self:: vs. $this-> in PHP
In general, you will find PHP much more verbose than Ruby, not least in terms of characters required to reference a variable.
If you have an instance variable (like your $foo) the only way to access it is through $this->foo.
You could, if desperate, write something like $foo =& $this->foo; so you have a local reference to the same variable, but the only benefit is saving a few characters at the cost of added confusion.
Related
I've been looking at some code and am having a hard time working out variable declaration in php classes. Specifically it appears that the code i'm looking at doesn't declare the class variables before it uses them. Now this may be expected but I can't find any info that states that it is possible. So would you expect this:
class Example
{
public function __construct()
{
$this->data = array();
$this->var = 'something';
}
}
to work? and does this create these variables on the class instance to be used hereafter?
This works the same as a normal variable declaration would work:
$foo = 'bar'; // Created a new variable
class Foo {
function __construct() {
$this->foo = 'bar'; // Created a new variable
}
}
PHP classes are not quite the same as in other languages, where member variables need to be specified as part of the class declaration. PHP class members can be created at any time.
Having said that, you should declare the variable like public $foo = null; in the class declaration, if it's supposed to be a permanent member of the class, to clearly express the intent.
So would you expect this: (code sample) to work?
Yes. It's pretty bad practice (at least it makes my C++ skin crawl), but it wouldn't surprise me in the slightest. See example 2 in the following page for an example of using another class without declaring it beforehand. http://www.php.net/manual/en/language.oop5.basic.php It will throw an error if E_STRICT is enabled.
And does this create these variables on the class instance to be used hereafter?
Yep. Ain't PHP Fun? Coming from a C++/C# background, PHP took a while to grow on me with its very loose typing, but it has its advantages.
That's completely functional, though opinions will differ. Since the creation of the class member variables are in the constructor, they will exist in every instance of the object unless deleted.
It's conventional to declare class member variables with informative comments:
class Example
{
private $data; // array of example data
private $var; // main state variable
public function __construct()
{
$this->data = array();
$this->var = 'something';
}
}
Pleace consider the following example:
class A {
public method() {
$foo = 'bar';
}
}
class B extends A {
public method {
parent::method();
echo $foo; // $foo == null
}
}
I run to situations like this quite frequently when I need to extend the functionality of a class coded by somebody else. Is there a way to have the $foo of the aforementioned example to be not null but bar?
I know perfectly well, that what I'm suggesting is not a problem at all if the variable $foo were a property of the class. However, this example applies to a situation where the class I want to extend is poorly designed and modifying the original class and changing the rogue variables into class properties is out of the question for reasons such as the class being a part of a CMS and update compatibility etc.
Unfortunately not. Once method() is called, the $foo variable is contained only within method(). You would have to change method() to either return $foo, or echo it itself. Once method() completes its run (which is quick, as all it does is create a variable), that local variable is then destroyed.
Assuming that B is supposed to extend A (it's not in your example although it does not matter much in this case...) there is nothing you can do without modifying class A: The $foo variable is only defined in the local scope of the method in class A.
You can:
Return it;
Make it a class property;
Output it (perhaps that is done already...) and use output buffering to capture it but that's kind of a hack.
But that is about it, without modifying class A you cannot retain or access $foo inside that method.
No. $foo in this case is a local variable, existing only while the method() call is actually running. When the method returns, the local variables are cleaned up/destroyed. And even if you did something like make it a static variable, it still would exist only in the scope of method() and not be accessible from the outside world.
You'd need to do something like:
class A {
public $foo;
function method() {
$this->foo = 'bar';
}
}
But even then, class A would not be aware of class B and couldn't inject foo's value into your B method's scope.
Up until today, I thought I had a fairly good grasp of how the static modifier worked. I know that (in laymans terms) a static variable in a function does not 'reset' across calls to that function, and I know that static variables and functions on a class are accessible by calling upon them through the class itself (not an instantiation of the class).
My problem is this: today I found that if I declare a static variable inside of a non-static function on a class, all instantiations of that class share that static variable in separate calls to the member function.
For example:
class A {
public function GetValue() {
static $value = 0;
$value++;
return $value;
}
}
$instance_1 = new A();
$instance_2 = new A();
echo $instance_1->GetValue();
echo $instance_1->GetValue();
echo $instance_2->GetValue();
echo $instance_2->GetValue();
echo $instance_1->GetValue();
echo $instance_1->GetValue();
Notice that the GetValue function is neither declared as static or used in a static way (as in, called on the class itself).
Now, I always assumed that this would output: 121234
Instead, I find that it will output: 123456
Like I say, I would understand this if the static variable $value was inside of a static function. However, with it being inside a non-static function I just assumed that it would only be 'tied' to the function 'within' each individual instantiation.
I guess my question is twofold, then... 1) is this a bug or expected behaviour? 2) do other languages treat these 'static inside non-static' variables the same way, or is this unique to PHP?
This is expected.
This is also the case in C++ (and probably others as well).
You should think of non-static class member functions as if they were just like ordinary functions, but with an implicit $this argument that is automatically provided by the interpreter. (That's exactly how they're implemented in most languages.)
I've copied the following information from this article by Josh Duck: http://joshduck.com/blog/2010/03/19/exploring-phps-static-scoping/
Static variables have been available since PHP 4 and allow you to define a persistent variable that is only accessible from the current function. This allows you to encapsulate state into a function or method and can eliminate the need for classes where a single function will suffice.
When a static variable is defined inside a class method they will always refer to the class on which the method was called. In doing this they act almost like properties referenced through static, though there are subtle differences.
Static variables can’t preserve the calling class scope. This can be potentially problematic if you have an inherited method containing a static variable that is called from both inside and outside its class.
As far as I know, all languages with static variables treat them this way. Think of static variables as global variables that can only be accessed from a certain scope.
I've been looking at some code and am having a hard time working out variable declaration in php classes. Specifically it appears that the code i'm looking at doesn't declare the class variables before it uses them. Now this may be expected but I can't find any info that states that it is possible. So would you expect this:
class Example
{
public function __construct()
{
$this->data = array();
$this->var = 'something';
}
}
to work? and does this create these variables on the class instance to be used hereafter?
This works the same as a normal variable declaration would work:
$foo = 'bar'; // Created a new variable
class Foo {
function __construct() {
$this->foo = 'bar'; // Created a new variable
}
}
PHP classes are not quite the same as in other languages, where member variables need to be specified as part of the class declaration. PHP class members can be created at any time.
Having said that, you should declare the variable like public $foo = null; in the class declaration, if it's supposed to be a permanent member of the class, to clearly express the intent.
So would you expect this: (code sample) to work?
Yes. It's pretty bad practice (at least it makes my C++ skin crawl), but it wouldn't surprise me in the slightest. See example 2 in the following page for an example of using another class without declaring it beforehand. http://www.php.net/manual/en/language.oop5.basic.php It will throw an error if E_STRICT is enabled.
And does this create these variables on the class instance to be used hereafter?
Yep. Ain't PHP Fun? Coming from a C++/C# background, PHP took a while to grow on me with its very loose typing, but it has its advantages.
That's completely functional, though opinions will differ. Since the creation of the class member variables are in the constructor, they will exist in every instance of the object unless deleted.
It's conventional to declare class member variables with informative comments:
class Example
{
private $data; // array of example data
private $var; // main state variable
public function __construct()
{
$this->data = array();
$this->var = 'something';
}
}
I was explaining to a Java developer why his method call wasn't working. He just needed to add $this->method_name();
He then asked me, "Why do I need to add $this to the method when it's declared in the same class?"
I didn't really know how to answer. Maybe it's because PHP has a global namespace and it you need to explicitly tell it that the method you are looking for belongs to the current class? But then why doesn't PHP check the current class for the method BEFORE looking at the global namespace?
The problem would also be that if you declared a function foo() and a method foo(), php would have a hard time figuring out which you meant - consider this example:
<?php
function foo()
{
echo 'blah';
}
class bar
{
function foo()
{
echo 'bleh';
}
function bar()
{
// Here, foo() would be ambigious if $this-> wasn't needed.
}
}
?>
So basically you can say that PHP - because of its "non-100%-object-orientedness" (meaning that you can also have functions outside classes) - has this "feature" :)
If I have to guess: Because it was easier than the alternatives. Object oriented support in PHP has always been very much of a hack. I vaguely remember reading a discussion about the upcoming closure support that will appear in PHP 5.3. Appearently it was really, really hard to implement lexical closures in PHP due to it's scoping rules. Probably because you can nest a class in a function in another class and stuff like that. All that freedom possibly makes stuff like this incredibly hard.
This is not unusual. Python, Javascript, Perl (and others) all make you refer to a this or self when dealing with objects.
That's just how scope works in PHP. $obj->f() refers to $foo in the function scope. If you want to get the class property $obj->foo within f(), it's $this->foo.
global $foo;
$foo = 99;
class myclass
{
public $foo;
function f()
{
$this->foo = 12;
$foo = 7;
// $this->foo != $foo != $GLOBALS['foo']
}
}
$this refers to the calling object. The PHP docs have good examples and further details.
Seems PHP hasn't been properly OOPed. In Java and C++, references to the current object ('this') are implicit, ie no explicit mention is needed, leaving the code much cleaner.
Perhaps there is some reason this is difficult with PHP implementation ?