PHP static initializer - php

I'd like to access a static field of a class in a static function, but the field is still <Uninitialized>. How can I initialize this field?
<?php
final class StaticTest {
private static $lookup = array(123, 456, 789);
public static function compute() {
return StaticTest::$lookup[0];
}
}
echo 'result: ' . StaticTest::compute();
?>
As you can see in the following picture taken from the Eclipse PDT debugging the static field $lookup is <Unitialized>.

The error is happening because you are trying to call a private variable while not calling self to access it.
I have given the below code a test and it seems to work. Oddly, I have also given your code a test, and that seems to work fine also.
To get around this, in your compute function, you should use this return self::$lookup[0]; instead of return StaticTest::$lookup[0];.
Another way around this would be to change the private static $lookup = array(123, 456, 789); to public static $lookup = array(123, 456, 789);. Doing this, your code would work fine, but is not the recommended way.
Doing this, it should return the result you want. Think of it similar to non static classes, to access parameters (private or public) inside of a non-static class you can use $this->, where as in a static class, you should use self:: instead. Also, not that using self:: to access a variable requires the $ to be present, where as using $this-> does not.
The answer provided by Dejv would also work, but involves using a singleton type class, which is definitely not needed for this procedure as it is instancing a new class each time, completely ignoring how static variables and functions can work.
Hope this answers your question.

Edit your code to this and it should work as you desire:
<?php
final class StaticTest{
protected static $instance;
private $lookup = array(123, 456, 789);
public function compute() {
return $this->lookup[0];
}
public static function get(){
if (!isset(self::$instance))
self::$instance = new self();
return self::$instance;
}
}
echo 'result: ' . StaticTest::get()->compute();
To explain myself here, it's always better to use the concept where you only specify that you want to use the property of object and don't care about creating the object.
It is done automatically (it object doesn't exist in memory it is created, if it exists it is called).
I can't really explain this better. I'm no braniac. I only use this concept as a substitution for application global variables.
Hope it helps!

Related

Testing setting a private property: can we use the mock to set the value and reflect the property to check if value was set?

I have both a "way of doing this" and "how is it done" question(s).
Class realClass {
private $privateProperty;
public function __construct($someArray, $someString) {
// stuff
}
public function setProperty($someArray) {
$this->privateProperty = $someArray;
}
}
class testRealClass extends TestCase {
// creating a mock because don't want to have tests depending on arguments passed to the constructor
public function setUp(): void
{
$this->classToTest = $this->getMockBuilder(realClass::class)
->disableOriginalConstructor()
->setMethods(null)
->getMock();
}
// testing the set of the variable. In order to know if it was set, without using a getter,
// we probably need to use reflection
public function testSetPrivateProperty() {
$this->classToTest->setProperty([1,2,3]);
// This will not work as the property is private
// echo $this->classToTest->privateProperty;
// Reflecting the mock, makes sense? How does this work?
$reflect = new \ReflectionClass($this->classToTest);
$property = $reflect->getProperty('privateProperty');
$property->setAccessible(true);
var_dump($property->getValue($this->classToTest));
}
}
When executing this I get a ReflectionException: Property privateProperty does not exist.
If I do a print_r of the reflections->getProperties I can see the property there.
I understand this would be easily achievable with just a getter in the realClass but take this as an exercise.
Doest this make sense at all or this will not work because it is just wrong?
Thank you everyone
(Wrote the code here so if I'm missing ";", "(", etc, do ignore it :)
Using Reflection API for testing is seldom a good idea. However, the real question is - why have a private property if nothing can access it? Obviously, the property is used in another method of the class. So, the clean solution here is remove all reflection code, then create a getter in the class itself, and replace all calls to $this->property to $this->getProperty(), then you can easily test this.
For a more generalized take on this question, private properties and methods are not meant to be tested, they are private because they conceal their data from everyone, including the tester classes. The more private fields and properties your class has, the less testable it gets, so when this becomes a hindrance, it is better to split the class into two, making one of the private methods public.

Reasoning behind functions like this?

Learning PHP in a OOP way and i often come across people who makes functions like this.
public function getUsername() {
return $this->username;
}
Is there some security reasoning behind this? Instead of just calling the username property of the class directly? Why wrap getting a property around a function.
This type of functions are used for accessing private or protected members of class. You can not access them them directly outside of the class as they can be accessible only inside the class. So what would you do if you want to access a private member? The answer is this.
Lets take an example -
class A {
private $x;
public $y;
public function test() {
echo $this->x;
}
}
$obj = new A();
$obj->x; // Error : You can not access private data outside the class
$obj->y; // Its fine
$obj->test(); // it will print the value of $x
Hope this will help.
In OOP, class should hide its implementation details, and just provide necessary public functions. Users are more concerned with function rather than details.
For example you have class Test. You are using direct access to property and you have hundred place like $obj->date = 'now' etc.
class Test {
public $date;
}
But what if you need to insert some code before updating value or modificate input value? In this case you have to find all usage of the property and update it. But if you will use getters/setters you can insert some code into them.
class Test {
private $date;
public getDate() { return $this->date; }
public setDate($date) {
// here some modification value or something else
$this->date = $date;
}
}
A quick reason is that you be writing a piece of code and want to prevent a user from overwriting a value in an object instance (a good example is configuration data).
Writing functions in the way you have stated also provides a standard interface which is essential when developing complex programs. It would be crazy to have a team of developers working with the one class and not defining access to variables!
Here is a good explanation of the PHP OOP basics and explains private, public and protected
http://php.net/manual/en/language.oop5.basic.php

How can protected property of a class be visible from a static method in PHP?

I understand OOP. What I understand so far is that private and protected cannot be referenced from outside the class using $this->blah notation. If that is correct, how can the following code work?
<?php
class test {
protected $a = "b";
public static function oo(){
$instance = new static();
echo $instance->a;
}
}
test::oo();
Gives me an output of b! Now, how in Lord's name can that happen?
In PHP 5.3, a new feature called late static bindings was added – and this can help us get the polymorphic behavior that may be preferable in this situation. In simplest terms, late static bindings means that a call to a static function that is inherited will “bind” to the calling class at runtime. So, if we use late static binding it would mean that when we make a call to “test::oo();”, then the oo() function in the test class will be called.after that you return $instance->a; static keyword allows the function to bind to the calling class at runtime.so if you use static then whatever access modifier(private,public,protected) you use it's just meaning less...
please read this link,another
That happens because you're "presenting it" by echo'ing it. You can't reference it like this for example:
class test {
private $a = 'b';
function __construct() {
echo 'instantiated';
}
}
$test = new test();
echo $test->a; // This line won't work, since it's a private var.
It would give you an error message that looks like this:
Fatal error: Cannot access private property test::$a
Example (https://eval.in/226435)
As I said before, you're accessing it from within the class itself, so you CAN view it. (That's the $instance you have there.) If you modify your code to use it like this:
class test {
protected $a = "b";
public static function oo(){
$instance = new static();
return $instance;
}
}
echo test::oo()->a;
Example of the above (https://eval.in/226439)
You'll get that "private acess blah blah" error.
You're understanding the statement wrong. "private and protected cannot be referenced from outside the class" means that as the examples above show, you CAN NOT access the variables outside the class, but with your example, you're accessing it from INSIDE the class, which means they'll do as you require (echo'ing out as you did)
What I understand so far is that private and protected cannot be referenced from outside the class
As follows, since oo is defined in the same type as a, oo has access to a.
This is actually a very good question, and shouldn't be down-voted.
From what I understand, the reason why you can access a protected/private property from within a static method of the same class, is because "the implementation specific details are already known when inside this class". I rephrased this a little from what is documented on the official page on Visibility:
Objects of the same type will have access to each others private and protected members even though they are not the same instances. This is because the implementation specific details are already known when inside those objects.
This makes sense. Visibility access is meant to only expose things that are safe for the public to use. But if you already have access to the code of the Class you're using, then there is no point of preventing you to use what you already see. Hope that makes sense..

How do I access a private variable from a class?

Why does my function return null?
class TestClass2
{
private $test_var="value";
public function getVar(){
global $test_var;
return $test_var;
}
}
$myclass = new TestClass2();
var_dump($myclass::getVar());
Is there an other way to access variables, which are outside the function, other than passing it in as a parameter, or declaring it as global?
You do not need "global", you just need "$this->test_var" to access your private variable inside a method of your class (in your case, the "getVar" method).
As for calling the function, since it is not static, use "->".
class TestClass2
{
private $test_var="value";
public function getVar(){
return $this->test_var;
}
}
$myclass = new TestClass2();
var_dump($myclass->getVar());
Now that I'm pretty certain what you're asking, I'll go ahead and give you a full answer.
When you call a method, an invisible argument, called $this is passed to it. It is a pointer to your class. I'm not certain this is how it works in PHP, but it's how C++ does it so the behaviors should be similar.
So if you're inside a class's method and you want to access one of its properties, you could tell PHP to use the global scope to break outside of your method and into the class, but that's bulky, obnoxious, and can lead to some complications as your class gets more complex.
The solution is to use the reference to our class that PHP magically gives us. If you want to access $foo->bar inside $foo->getBar(), you can get $this->bar. A good way to think of it is that this is a variable that holds the name of your class.
An additional advantage of this is that, because we're in our class, private properties are visible. This means that $this->bar is valid, whereas $foo->bar isn't, assuming bar is private, of course.
So if we apply this to your code, it becomes a lot simpler and prettier to look at (by PHP standards):
class TestClass2
{
private $test_var="value";
public function getVar(){
return $this->test_var;
}
}
$myclass = new TestClass2();
$myclass->test_var; // Error
$myclass->getVar(); // Not an error

PHP Scope and Class Instance Interaction

It seems as though different instances of a class can know about each others' private member variables.
I have provided some code that attempts to showcase my issue, and I will try to explain it.
We have a class with a private member variable, $hidden. modifyPrivateMember sets the value of $hidden to 3. accessPrivateMember takes an Object as a parameter and accesses its private $hidden member to return its value.
Example code:
<?php
// example.php
class Object {
private $hidden;
public function modifyPrivateMember() {
$this->hidden = 3;
}
public function accessPrivateMember(Object $otherObject) {
return $otherObject->hidden;
}
}
$firstObject = new Object;
$firstObject->modifyPrivateMember();
$otherObject = new Object;
echo $otherObject->accessPrivateMember($firstObject);
Output of the above code:
$ php example.php
3
Can anyone explain why private members of objects are accessible to other instances of the same class? Is there some justification for this ostensible breach of scope?
private means it's restricted to only that class, not only that object.
That's just how php works. It's the same as how Java works. See http://php.net/manual/en/language.oop5.visibility.php for more info.
The only situation in which this behavior seemed useful was in a factory function:
class Object
{
private $state;
public static function makeObject()
{
$obj = new Object;
$obj->state = 'some state';
return $obj;
}
}
Even in this case, there are better solution and I agree with you that it is a breach of scope, although not that big in my opinion. After all, the one who writes the class decides if she needs to access private members from objects passed as arguments. So, it may seem useless (even to me), but you never know. It's not like you're exposing your internals to subclasses or something. It all happens in the same class and it's your business what you're doing in there.
By the way, one language that implements access modifiers per object and not per class is Ruby.

Categories