Reset Class Instance Variables via Method - php

Does anyone know how to reset the instance variables via a class method. Something like this:
class someClass
{
var $var1 = '';
var $var2 = TRUE;
function someMethod()
{
[...]
// this method will alter the class variables
}
function reset()
{
// is it possible to reset all class variables from here?
}
}
$test = new someClass();
$test->someMethod();
echo $test->var1;
$test->reset();
$test->someMethod();
I know I could simply do $test2 = new SomeClass() BUT I am particularly looking for a way to reset the instance (and its variables) via a method.
Is that possible at all???

You can use reflection to achieve this, for instance using get_class_vars:
foreach (get_class_vars(get_class($this)) as $name => $default)
$this -> $name = $default;
This is not entirely robust, it breaks on non-public variables (which get_class_vars does not read) and it will not touch base class variables.

Yes, you could write reset() like:
function reset()
{
$this->var1 = array();
$this->var2 = TRUE;
}
You want to be careful because calling new someClass() will get you an entirely new instance of the class completely unrelated to the original.

this could be easy done;
public function reset()
{
unset($this);
}

Sure, the method itself could assign explicit values to the properties.
public function reset()
{
$this->someString = "original";
$this->someInteger = 0;
}
$this->SetInitialState() from Constructor
Just as another idea, you could have a method that sets the default values itself, and is called from within the constructor. You could then call it at any point later as well.
<?php
class MyClass {
private $var;
function __construct() { $this->setInitialState(); }
function setInitialState() { $this->var = "Hello World"; }
function changeVar($val) { $this->var = $val; }
function showVar() { print $this->var; }
}
$myObj = new MyClass();
$myObj->showVar(); // Show default value
$myObj->changeVar("New Value"); // Changes value
$myObj->showVar(); // Shows new value
$myObj->setInitialState(); // Restores default value
$myObj->showVar(); // Shows restored value
?>

Related

Is it possible to make a class' variable read-only in PHP? [duplicate]

Is there a way to make a read-only property of an object in PHP? I have an object with a couple arrays in it. I want to access them as I normally would an array
echo $objObject->arrArray[0];
But I don't want to be able to write to those arrays after they're constructed. It feels like a PITA to construct a local variable:
$arrArray = $objObject->getArray1();
echo $arrArray[0];
And anyways, while it keeps the array in the object pristine, it doesn't prevent me from re-writing the local array variable.
Well, the question is where do you want to prevent writing from?
The first step is making the array protected or private to prevent writing from outside of the object scope:
protected $arrArray = array();
If from "outside" of the array, a GETTER will do you fine. Either:
public function getArray() { return $this->arrArray; }
And accessing it like
$array = $obj->getArray();
or
public function __get($name) {
return isset($this->$name) ? $this->$name : null;
}
And accessing it like:
$array = $obj->arrArray;
Notice that they don't return references. So you cannot change the original array from outside the scope of the object. You can change the array itself...
If you really need a fully immutable array, you could use a Object using ArrayAccess...
Or, you could simply extend ArrayObject and overwrite all of the writing methods:
class ImmutableArrayObject extends ArrayObject {
public function append($value) {
throw new LogicException('Attempting to write to an immutable array');
}
public function exchangeArray($input) {
throw new LogicException('Attempting to write to an immutable array');
}
public function offsetSet($index, $newval) {
throw new LogicException('Attempting to write to an immutable array');
}
public function offsetUnset($index) {
throw new LogicException('Attempting to write to an immutable array');
}
}
Then, simply make $this->arrArray an instance of the object:
public function __construct(array $input) {
$this->arrArray = new ImmutableArrayObject($input);
}
It still supports most array like usages:
count($this->arrArray);
echo $this->arrArray[0];
foreach ($this->arrArray as $key => $value) {}
But if you try to write to it, you'll get a LogicException...
Oh, but realize that if you need to write to it, all you need to do (within the object) is do:
$newArray = $this->arrArray->getArrayCopy();
//Edit array here
$this->arrArray = new ImmutableArrayObject($newArray);
If you're using PHP 5+ you can do it with __set() and __get() methods.
You have to define how they work but should do just this.
Edit an example would be like this.
class Example {
private $var;
public function __get($v) {
if (is_array($v)) {
foreach () {
// handle it here
}
} else {
return $this->$v;
}
}
}
This might not be the "best" way of doing it but it'll work depending on what you need
If defined, the magic functions __get() and __set() will be called whenever a non-existing or private property is accessed. This can be used to create "get" and "set" methods for private properties, and for instance make them read-only or manipulate the data when stored or retrieved in it.
For instance:
class Foo
{
private $bar = 0;
public $baz = 4; // Public properties will not be affected by __get() or __set()
public function __get($name)
{
if($name == 'bar')
return $this->bar;
else
return null;
}
public function __set($name, $value)
{
// ignore, since Foo::bar is read-only
}
}
$myobj = new Foo();
echo $foo->bar; // Output is "0"
$foo->bar = 5;
echo $foo->bar; // Output is still "0", since the variable is read-only
See also the manual page for overloading in PHP.
For PHP 8.1+, you can use readonly properties:
class Test
{
public readonly array $arrArray;
public function __construct()
{
$this->arrArray = [1, 2, 3];
}
}
$test = new Test();
var_dump($test->arrArray); // OK
$test->arrArray = [4, 5, 6]; // Error
in the class, do this:
private $array;
function set_array($value) {
$this->array = $value;
}
then you just set like this:
$obj->set_array($new_array);

Get a static property of an instance

If I have an instance in PHP, what's the easiest way to get to a static property ('class variable') of that instance ?
This
$classvars=get_class_vars(get_class($thing));
$property=$classvars['property'];
Sound really overdone. I would expect
$thing::property
or
$thing->property
EDIT: this is an old question. There are more obvious ways to do this in newer
PHP, search below.
You need to lookup the class name first:
$class = get_class($thing);
$class::$property
$property must be defined as static and public of course.
From inside a class instance you can simply use self::...
class Person {
public static $name = 'Joe';
public function iam() {
echo 'My name is ' . self::$name;
}
}
$me = new Person();
$me->iam(); // displays "My name is Joe"
If you'd rather not
$class = get_class($instance);
$var = $class::$staticvar;
because you find its two lines too long, you have other options available:
1. Write a getter
<?php
class C {
static $staticvar = "STATIC";
function getTheStaticVar() {
return self::$staticvar;
}
}
$instance = new C();
echo $instance->getTheStaticVar();
Simple and elegant, but you'd have to write a getter for every static variable you're accessing.
2. Write a universal static-getter
<?php
class C {
static $staticvar = "STATIC";
function getStatic($staticname) {
return self::$$staticname;
}
}
$instance = new C();
echo $instance->getStatic('staticvar');
This will let you access any static, though it's still a bit long-winded.
3. Write a magic method
class C {
static $staticvar = "STATIC";
function __get($staticname) {
return self::$$staticname;
}
}
$instance = new C();
echo $instance->staticvar;
This one allows you instanced access to any static variable as if it were a local variable of the object, but it may be considered an unholy abomination.
classname::property;
I think that's it.
You access them using the double colon (or the T_PAAMAYIM_NEKUDOTAYIM token if you prefer)
class X {
public static $var = 13;
}
echo X::$var;
Variable variables are supported here, too:
$class = 'X';
echo $class::$var;
You should understand what the static property means. Static property or method is not for the objects. They are directly used by the class.
you can access them by
Class_name::static_property_name
These days, there is a pretty simple, clean way to do this.
<?php
namespace Foo;
class Bar
{
public static $baz=1;
//...
public function __toString()
{
return self::class;
}
}
echo Bar::$baz; // returns 1
$bar = new Bar();
echo $bar::$baz; // returns 1
You can also do this with a property in PHP 7.
<?php
namespace Foo;
class Bar
{
public static $baz=1;
public $class=self::class;
//...
}
$bar = new Bar();
echo $bar->class::$baz; // returns 1
class testClass {
public static $property = "property value";
public static $property2 = "property value 2";
}
echo testClass::$property;
echo testClass::property2;

Restricting variable access

I need to have a variable that only one function can write (let's call that function a) and that only one other function can read (let's call that function b). Is that possible?
You could use a static variable:
function foo($val=null) {
static $var = null;
if (!is_null($var)) $var = $val;
return $val;
}
Here $var is only visible inside the function foo and is maintained throughout multiple calls:
foo(123);
echo foo(); // 123
foo(456);
echo foo(); // 456
Or use a class with a private member and access/modify it with public methods:
class A {
private $var;
public function setVar($val) {
$this->var = $val;
}
public function getVar() {
return $this->var;
}
}
With this the private member var is only visible to a particular instance of this class:
$obj1 = new A();
$obj1->setVar(123);
$obj2 = new A();
$obj2->setVar(456);
echo $obj1->getVar(); // 123
echo $obj2->getVar(); // 456
If you make the member static, then there is just one for the class instead of for each instance:
class A {
private static $var;
public function setVar($val) {
self::$var = $val;
}
public function getVar() {
return self::$var;
}
}
$obj1 = new A();
$obj1->setVar(123);
$obj2 = new A();
$obj2->setVar(456);
echo $obj1->getVar(); // 456
echo $obj2->getVar(); // 456
You can use a static abstract class.
abstract class Settings
{
private static var $_settings = array();
public static function get($key,$default = false)
{
return isset(self::$_settings[$key]) ? self::$_settings[$key] : $default;
}
public static function set($key,$value)
{
self::$_settings[$key] = $value;
}
}
Example Usage:
Settings::set('SiteName',`SomeResult`);
echo Settings::get('SiteName');
Since 5.3.0, you can use anonymous functions as closures. The advantage here, is that you can hold on to b... which is returned by a... and fire it off when you're ready:
<?php
function a()
{
// Only a() can write to $myVar
$myVar = 42;
$b = function() use ($myVar)
{
// $b can read $myVar
// no one else can
return $myVar;
};
return $b;
}
// get $b
$test = a();
// use $b
echo $test();
?>
Another solution before 5.3.0, but here a has to fire b which may not be that practical:
You can simply create an internal variable and pass it as an argument. You can do this inside a class, or just inside simple functions:
function a()
{
// ...
// Write the variable that
// only this function can write to
$thisVar = 1;
b($thisVar);
//...
}
function b($myVar)
{
// ...
// Do stuff w $myVar, a copy of $thisVar
// Changing $myVar has no effect on $thisVar
//
}
Do you mean friend functions? Because I'd love to be able to do that. So far I haven't found an easy way though (although you could try using Reflection, but that seems like way to much effort).
For me, it usually hasn't been an issue of maintaining data integrity / encapsulation, but of keeping the list of public methods (which is kinda like a class's API) free of clutter. A perfect framework should be easy to use, have obvious function names etc etc etc. Methods intended for use by a single other method really mess things up. The "solution" I've taken to is prefixing those function names by one or two underscores and writing "intended for internal use only" or something to that extent in the comments.

property not updating in object when page is posted

I have set a property in a constructor like so
function __construct()
{
$this->count = count(#$_SESSION['filearray']); //count how many files in array
}
and using it in condition statements if($this->count > 10) //then do something
but it appears the count isn't being updated when I use another method of injecting values into this 'filearray' until I refresh the page.
am I doing something wrong? I thought that my constructor would detect a change had been made in the session and whenever I call $this->count I would get the current count value but it seems to be 1 step behind until I refresh the page.
If this is all vague I can include my form page that has all the method calls, but this is the jist of my question, why is my property not updating and how do I fix it :)
TIA
$this->count won't automatically be updated with the count every time you add or subtract from the filearray session. Constructors are only invoked upon instantiation of the class or when called directly.
You can achieve this sort of functionality using a getter.
class myClass {
public function getCount() {
return count(#$_SESSION['filearray']);
}
}
$_SESSION['filearray'] = array('bar');
$foo = new myClass();
echo $foo->getCount(); // 1
Or by using the __get() magic-method:
class myClass {
public function __get($property_name) {
if ($property_name == 'count') {
return count(#$_SESSION['filearray']);
}
}
}
$_SESSION['filearray'] = array('bar');
$foo = new myClass();
echo $foo->count; // 1
Or a combination of the two:
class myClass {
private $_count;
public function __get($property_name) {
if ($property_name == 'count') {
return $this->_getCount();
}
}
private function _getCount() {
return $this->_count = count(#$_SESSION['filearray']);
}
}
$_SESSION['filearray'] = array('bar');
$foo = new myClass();
echo $foo->count; // 1

Simple PHP classes question

So I have:
class foo {
public $variable_one;
public $variable_two;
function_A(){
// Do something
$variable_one;
$variable_two;
// If I define variable_3 here!
$variable_3
// Would I be able to access it in function_B?
}
function_B(){
// Do something
$variable_4 = $variable_3
}
}
$myObj = new foo();
// Now what do I write in order to assign "variable_one" and "two" some value?
$myObj->$variable_one = 'some_value' ??
$myObj->$variable_two = 'some_value' ??
First, when you write simply $variable_one; inside A() it does not refer to the member variables of your class! That would be a completely different, newly created local variable called $variable_one bearing no relation to the class variable.
Instead, you want:
function A() {
$this->variable_one;
}
Second, your $variable_3 is also a local variable, and will not be accessible in any other function.
Third, your assignments at the bottom are correct in form, but not in syntax: there's an extra $ in there. You want:
$myObj->variable_one = 'some value';
No, $variable_3 was created (and will be destroyed) in the scope of function_A. This is due to function scope.
http://us3.php.net/manual/en/language.variables.scope.php
If you would like $variable_3 to be retained by your object once execution leaves function_A's scope, you need to assign it as a class property, similar to $variable_1 and $variable2.
class YourClass
{
public $variable_1;
public $variable_2;
public $variable_3;
function_A()
{
$this->variable_3 = "some value"; // assign to the object property
$variable_4 = "another value"; // will be local to this method only
}
function_B()
{
echo $this->variable_3; // Would output "some value"
echo $variable_4; // var does not exist within the scope of function_B
}
}
$myObj->variable_one = aValue;
$myObj->variable_two = anotherValue;
The correct code would be the following (see answer within comments)
class foo {
public $variable_one;
public $variable_two;
private $variable_three; // private because it is only used within the class
function _A(){
// using $this-> because you want to use the value you assigned at the
// bottom of the script. If you do not use $this-> in front of the variable,
// it will be a local variable, which means it will be only available inside
// the current function which in this case is _A
$this->variable_one;
$this->variable_two;
// You need to use $this-> here as well because the variable_3 is used in
// function _B
$this->variable_3;
}
function _B(){
// Do something
$variable_4 = $this->variable_3
}
}
$myObj = new foo();
$myObj->variable_one = 'some_value1'; // Notice no $ in front of the var name
$myObj->variable_two = 'some_value2'; // Notice no $ in front of the var name
Class variables (properties) must be accessed using the $this-> prefix, unless they are static (in your example they aren't). If you do not use the prefix $this-> they will be local variables within the function you define them.
I hope this helps!
If variable_one and variable_two are public, you can assign them as you specified (just remove the "$"...so $classObject->variable_one). Typically you want to encapsulate your variables by making them either protected or private:
class MyClass
{
protected $_variable_one;
public function getVariableOne()
{
return $this->_variable_one;
}
public function setVariableOne($value)
{
$this->_variable_one = $value;
}
}
$c = new MyClass();
$c->setVariableOne("hello!");
echo $c->getVariableOne(); // hello!

Categories