Access static variable from within a class - php

Simple question, is it possible to access a static variable from a $this-> call?
class testA
{
public static $var1 = "random string";
// current solution
public function getVar()
{
return self::$var1;
}
}
class testB
{
private $myObject;
public function __construct() {
$this->myObject = new testA();
// This line is the question
echo $this->myObject::var1;
// current solution
echo $this->myObject->getVar();
}
}
I'm afraid I've answered my own question. But having a few static variables I didn't want to have a function for each variable, Or even a single getVar($staticVar) when I could access it directly.
If this is the only solution. Any recommendations on a better way to implement this.
If I'm going to require a function call for each, I might as well get rid of the static variables altogether.
//method
public function staticVar1() {
return (string) 'random string';
}

You simply access the variable like this:
testA::$var1;
So using your exemple, it would be
class testB
{
private $myObject;
public function __construct() {
$this->myObject = new testA();
// This line is the question
echo testA::$var1;
// current solution
echo $this->myObject->getVar();
}
}

Try to understand the purpose of static.
static makes them accessible without needing an instantiation of the class.
They should accessed as below if the static variable is in the class
self::$var1;
below is possible in your case
testA::$var1;
would do the job here.

Related

PHP OOP - Accessing property value is returning empty

I have the following class, and for some reason it's not accessing the test property. Why is this? I'm new to OOP, so please be easy on me. Thanks
class Test {
private $test;
function __contruct() {
$this->test = "test";
}
static function test() {
echo $this->test;
}
}
$test = new Test;
$test::test();
Because static methods are callable without an instance of the object
created, the pseudo-variable $this is not available inside the method
declared as static.
PHP Documentations.
Good morning.
It seems you have 3 issues with your code.
There is a syntax error at constructor line change it from __contruct to __construct.
Change test function visibility to public
Access your function with the -> instead of ::
To elaborate further on the above answers: Static methods and variables are not linked to any particular instance of the object, this is why you have to call test with $test::test(). This also means that you cannot access an instance variable from without a static method and it doesn't really make sense to do so (If you had multiple instances of the object with different values set for that variable, how would the interpreter know which instance/value to use?)
If you want to have a field accessible from a static method then you have to make the field static as well. So, if you wanted to have $test accessible from your static method test() then you'd have to write your function as something along these lines:
class Test {
private static $test;
function __contruct() {
Test::$test = "test";
}
public function test() {
echo Test::$test;
}
}
$test = new Test;
$test::test();
However, it doesn't really make sense to be initialising a static field like that in your constructor. So you'd more likely be wanting to do something like:
class Test {
private static $test = "test";
function __contruct() {
}
public static function test() {
echo Test::$test;
}
}
$test = new Test;
$test::test();
Or, if you don't actually require test() to be static then you could just make it an instance method:
class Test {
private $test = "test";
function __contruct() {
$this->$test = "test"
}
public function test() {
echo $this->$test;
}
}
$test = new Test;
$test->test();

How do I make variable classwide accessable (Object oriented Programming PHP)

I have a class named testclass and several functions in it. They all need to access one predefined variable $need_to_have. I want to define it within the class, but how?
Example:
class testclass {
// This won't work:
private static $need_to_have = get_some_info();
public static testfunction1() {
// Do Something with $need_to_have
}
public testfunction2 () {
// Do something else with $need_to_have
}
}
Forgot to mention: I want to have it privat and I'm calling the variable only on static functions, so I can't use the constructor.
You can't do that, because you can't initialize class properties with non-constant expressions.
What you can do is put an accessor method between you and the property, e.g.:
class testclass {
private static $need_to_have;
private static $need_to_have_initialized;
public static testfunction1()
{
// Do Something with getNeedToHave()
}
private static function getNeedToHave()
{
if (!self::$need_to_have_initialized) {
self::$need_to_have = get_some_info();
self::$need_to_have_initialized = true;
}
return self::$need_to_have;
}
}
If there is a constant value that get_some_info is guaranteed to never return, you can use that to initialize $need_to_have; this will allow you to get rid of the helper property $need_to_have_initialized:
// example: get_some_info() never returns false
private static $need_to_have = false;
private static function getNeedToHave()
{
if (self::$need_to_have === false) {
self::$need_to_have = get_some_info();
}
return self::$need_to_have;
}
Another possible modification (improvement?) is to make the property (and the "initialized" flag, if applicable) local static variables inside getNeedToHave; this way they won't even be visible from anywhere within the class itself:
private static function getNeedToHave()
{
static $need_to_have = false;
if ($need_to_have === false) {
$need_to_have = get_some_info();
}
return $need_to_have;
}
This, pretty much, has a lot of ways to do it.
The most popular way here is having a so called getter (accessor) method, which will return the current information regarding the property and it still can be private.
class TestClass {
private static $myVar = 5;
public static getMyVar() {
return self::$myVar;
}
}
So, with proper autoloader, across all your application, you will be able to call
TestClass::getMyVar();
And, as you stated in the comments, nobody will have access to change it from outside the class.
However, it could be considered bad practice, not only for the static way, as also that you should not refer to a class which you have nothing coupled to it, only to retrieve information.
Best way here is to implement registry pattern, where you can register information to the global space.
Make a separated class which implements the Registry design pattern, and maybe set some constraints, so once setted your myVar nobody can reset it, on order to be able to use the following syntax
Registry::get('myVar');
This, of course, will give you the opportunity to put some more logic in that property before registering it into the globalspace, because, defining a property, might make you troubles regarding some definitions.
Make it a property of the class, set it once and use it everywhere:
class testclass
{
public static $need_to_have;
public function __construct()
{
//$this->need_to_have=1;
// Or rather the value returned by
// whatever it is you are doing with it
$this->need_to_have=$this->setNeed();
}
public function testfunction1()
{
// Do Something with $need_to_have
echo $this->need_to_have
}
public function testfunction2 ()
{
echo $this->need_to_have
}
public function setNeed()
{
$x=4;
$y=6;
$ret=$x*$y;
return $ret;
}
}
There is no (object oriented) way to "make variable classwide accessable". But it's not needed.
What you are looking for are object and class properties or class constants.
class TestClass {
const TEST_CLASS_CONSTANT = 'foo';
private static $testClassProperty;
// or with value: private static $testClassProperty = 'bar';
private $testObjectProperty;
// or with value: private $testObjectProperty = 'baz';
// This won't work
// private static $need_to_have = get_some_info();
// -- since you only can execute functions/methods outside of class structure
// or within other functions/methods.
public function testMethod() {
// Writable access to TEST_CLASS_CONSTANT: not possible, since it's a constant.
// Writable access to $testClassProperty: possible with keywords self, parent, and static.
self::$testClassProperty = 'newbar';
// Writable access to $testObjectProperty: possible with keywords this or parent.
$this->testClassProperty = 'newbaz';
// Readable access to TEST_CLASS_CONSTANT: possible with keywords self, parent, and static.
echo self::TEST_CLASS_CONSTANT;
echo PHP_EOL;
// Readable access to $testClassProperty: possible with keywords self, parent, and static.
echo self::$testClassProperty;
echo PHP_EOL;
// Readable access to $testObjectProperty: possible with keywords this or parent.
echo $this->testClassProperty;
}
}
$testObject = new TestClass();
$testObject->testMethod();

Pull variables from separate function

If I have two public functions and I want to pull a variable from one inside of another, what is the best way to accomplish this? I know about 'global' but this method seems like it could cause me problems down the road.
Imagine I have something like this:
class myCMS {
public function process_apples() {
$a = $_POST['$apples'];
}
public function display_apples() {
echo $a;
}
}
How would I go about using display_apples() to report $a from process_apples()? Im new to PHP, so feel free to let me know if I am violating some best practicing for organizing my code.
If you have two methods in a class, and want a variable to shared between them, you should use a class property -- which is kind of a variable that's inside a class.
Your class would then look like this :
class myCMS {
protected $a; // declare the property (won't be visible from outside the class)
public function process_apples() {
$this->a = $_POST['$apples'];
}
public function display_apples() {
echo $this->a;
}
}
And a couple of notes :
You need to use $this->property_name to access a property
Not related, but you should generally no use $_POST from inside your class : it makes your class dependent on external global variables -- of course, up to you to determine whether it's a problem or not.
You would have:
class myCMS {
private $a;
public function process_apples() {
$this->a = $_POST['$apples'];
// process
}
public function display_apples() {
echo $this->a;
}
}
Since you're using a class, you could make a private class variable, like this:
class myCMS {
private $a;
public function process_apples() {
$this->a = $_POST['$apples'];
}
public function display_apples() {
echo $this->a;
}
}

PHP class: Global variable as property in class

I have a global variable outside my class = $MyNumber;
How do I declare this as a property in myClass?
For every method in my class, this is what I do:
class myClass() {
private function foo() {
$privateNumber = $GLOBALS['MyNumber'];
}
}
I want this
class myClass() {
//What goes here?
var $classNumber = ???//the global $MyNumber;
private function foo() {
$privateNumber = $this->classNumber;
}
}
EDIT: I want to create a variable based on the global $MyNumber but
modified before using it in the methods
something like: var $classNumber = global $MyNumber + 100;
You probably don't really want to be doing this, as it's going to be a nightmare to debug, but it seems to be possible. The key is the part where you assign by reference in the constructor.
$GLOBALS = array(
'MyNumber' => 1
);
class Foo {
protected $glob;
public function __construct() {
global $GLOBALS;
$this->glob =& $GLOBALS;
}
public function getGlob() {
return $this->glob['MyNumber'];
}
}
$f = new Foo;
echo $f->getGlob() . "\n";
$GLOBALS['MyNumber'] = 2;
echo $f->getGlob() . "\n";
The output will be
1
2
which indicates that it's being assigned by reference, not value.
As I said, it will be a nightmare to debug, so you really shouldn't do this. Have a read through the wikipedia article on encapsulation; basically, your object should ideally manage its own data and the methods in which that data is modified; even public properties are generally, IMHO, a bad idea.
Try to avoid globals, instead you can use something like this
class myClass() {
private $myNumber;
public function setNumber($number) {
$this->myNumber = $number;
}
}
Now you can call
$class = new myClass();
$class->setNumber('1234');
Simply use the global keyword.
e.g.:
class myClass() {
private function foo() {
global $MyNumber;
...
$MyNumber will then become accessible (and indeed modifyable) within that method.
However, the use of globals is often frowned upon (they can give off a bad code smell), so you might want to consider using a singleton class to store anything of this nature. (Then again, without knowing more about what you're trying to achieve this might be a very bad idea - a define could well be more useful.)
What I've experienced is that you can't assign your global variable to a class variable directly.
class myClass() {
public $var = $GLOBALS['variable'];
public function func() {
var_dump($this->var);
}
}
With the code right above, you get an error saying "Parse error: syntax error, unexpected '$GLOBALS'"
But if we do something like this,
class myClass() {
public $var = array();
public function __construct() {
$this->var = $GLOBALS['variable'];
}
public function func() {
var_dump($this->var);
}
}
Our code will work fine.
Where we assign a global variable to a class variable must be inside a function. And I've used constructor function for this.
So, you can access your global variable inside the every function of a class just using $this->var;
What about using constructor?
class myClass {
$myNumber = NULL;
public function __construct() {
global myNumber;
$this->myNumber = &myNumber;
}
public function foo() {
echo $this->myNumber;
}
}
Or much better this way (passing the global variable as parameter when inicializin the object - read only)
class myClass {
$myNumber = NULL;
public function __construct($myNumber) {
$this->myNumber = $myNumber;
}
public function foo() {
echo $this->myNumber;
}
}
$instance = new myClass($myNumber);
If you want to access a property from inside a class you should:
private $classNumber = 8;
I found that globals can be used as follows:
Create new class:
class globalObj{
public function glob(){
global $MyNumber;
return $this;
}
}
So, now the global is an object and can be used in the same way:
$this->glob();
class myClass
{
protected $foo;
public function __construct(&$var)
{
$this->foo = &$var;
}
public function foo()
{
return ++$this->foo;
}
}

How to make a globally accessible object

Hi i have a little collection of classes some of which should be globally accessible.
I found something similar in Zend_Registry, but reading its code i cant understand how a call to a static function could return an initialized instance of a class...
i need to do something like:
<?php
//index.php
$obj = new myUsefulObject();
$obj->loadCfg("myFile.xml");
$req = new HTTPRequest();
$req->filter("blablabla");
myappp::registerClass("object",$obj);
myappp::registerClass("request",$req);
$c = new Controller();
$c->execute();
?>
Here i have filtered the Request object and i want the controller to be able to reach that already filtered request.
<?php
class Controller
{
function __construct()
{
$this->request = Application::getResource("request");//This must be the filtered var =(
}
}
?>
I don't know how to implement that Application::getResource(), the only thing i know is that it must be a static method because it can't be related to a specific instance.
Aside from static methods, PHP also has static properties: properties that are local to the class. This can be used to implement singletons, or indeed a Registry:
class Registry {
private static $_registry;
public static function registerResource($key, $object)
{
self::$_registry[$key] = $object;
}
public static function getResource($key) {
if(!isset(self::$_registry[$key]))
throw InvalidArgumentException("Key $key is not available in the registry");
return self::$_registry[$key];
}
}
1: You can acess global variables with the global keyword:
$myVar = new SomethingProvider();
class MyClass {
public function __construct() {
global $myVar;
$myVar->doSomething();
}
}
2: You can do the same using the $GLOBALS super-global:
$myVar = new SomethingProvider();
class MyClass {
public function __construct() {
$GLOBALS['myVar']->doSomething();
}
}
3: You can define a singleton class (the wikipedia has a nice example, too).
4: You could add globals as public static members (or private static members with public getters/setters) to a class:
class Constants {
const NUM_RETIES = 3;
}
if ($tries > Constants::NUM_RETRIES) {
# User failed password check too often.
}
class Globals {
public static $currentUser;
}
Globals::$currentUser = new User($userId);
I wouldn't recommend the first two methods, overwriting the values of these global variables unintentionally is too easy.
Seems to me like you might need some form of Singleton design pattern;
Check this out!
Hope it helps!

Categories