I'm trying to make my code a little drier by doing the follow in PHP:
function accessor($obj, $property) {
return $obj->$property;
}
class SomeClass {
private $variable;
function variable() {
return accessor($this, 'variable');
}
}
$some = new SomeClass;
echo $some->variable();
The above code throws an error because the external function can't access the private variable. The code is simplified, further coding would make it more useful.
I'm not sure if this is possible but it would sure be nice!
What you want are traits (PHP 5.4+)- they are practically pasted into their parent classes, so they can access private state:
trait VariableThingy {
function accessor($property) {
return $this->$property;
}
}
class Test {
use VariableThingy;
private $variable = 15;
function variable() {
return $this->accessor("variable");
}
}
But no, it's not nice. It's atrocious. And the whole code is rather pointless. If you want dry, just go with a public variable. DRY and encapsulated are usually mutually exclusive.
Related
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();
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.
My application has a single point of entry let's call it index.php.
In index.php it instantiates a class like below;
final class Griff {
public $a, $b, $c, $d, $e;
public function __construct() {
spl_autoload_register(array($this, 'autoload',));
$this->a = 'a';
// blah blah blah
new RouterGriff($this);
}
private function autoload($name) {
// autoload function
}
}
new Griff();
You will notice that RouterGriff is instantiated inside Griff::__construct(), RouterGriff looks like below:
final class RouterGriff {
private $griff;
public function __construct(Griff $griff) {
$this->griff = $griff;
$this->griff->b = 'b';
$this->griff->c = 'c';
}
}
My question is as follows; you will notice I am setting variables for properties that are stored in Griff from RouterGriff as I want a registry kind of structure to my application but do not want to use a singleton.
Would it be better if I just had the properties set in RouterGriff instead of Griff? Or is passing Griff around to every class a valid way of doing things, considering my application could go 10 classes deep before it outputs anything?
I hope I made sense and thank you
EDIT
By the other way I ment doing it this way,
final class Griff {
public $a;
public function __construct() {
spl_autoload_register(array($this, 'autoload',));
$this->a = 'a';
// blah blah blah
new RouterGriff();
}
private function autoload($name) {
// autoload function
}
}
new Griff();
final class RouterGriff {
public $b, $c;
public function __construct() {
$this->b = 'b';
$this->c = 'c';
}
}
The answer to you question you are looking for is named "dependency injection" or "dependency injection container". This is a wide topic filling books. If you are interessted in this topic, I can suggest you: Clean Code: A Handbook of Agile Software Craftsmanship (Robert C. Martin)
If you're talking about global application settings (Which I think you are), just use constants.
They're global, but cannot be changed, and they are easy to write and use.
I dont think youre wrong about injecting Griff into everything that is fine. As far as what classes get which propertied i think the depends on the nature of the properties. For example i would have included a GriffRequest in this example which is where you would access/store the parsed params the router supplied for example:
final class Griff {
protected $_request,
$_response,
$_router;
public function __construct() {
spl_autoload_register(array($this, 'autoload',));
$this->_request = new GriffRequest($this);
$this->_response = new GriffResponse($this);
$this->_router = new RouterGriff($this);
}
private function autoload($name) {
// autoload function
}
public function getRequest() { return $this->_request; }
public function getResponse() { return $this->_response; }
public function getRouter() { return $this->_router; }
}
final class RouterGriff {
protected $_application;
public function __construct(Griff $application) {
$this->_application = $application;
}
public function route() {
// do stuff with request
// assign params
$request = $application->getRequest();
$request->a = 'value';
$request->b = 'value2';
}
}
If you make Griff store a ref to all the important submodules of the app and then inject Griff into all those modules then you can get access to everything you might need by going through Griff at some point. You can always make convenience getters if you feel the chain is to long.
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;
}
}
I have a variable on the global scope that is named ${SYSTEM}, where SYSTEM is a defined constant. I've got a lot of classes with functions that need to have access to this variable and I'm finding it annoying declaring global ${SYSTEM}; every single time.
I tried declaring a class variable: public ${SYSTEM} = $GLOBALS[SYSTEM]; but this results in a syntax error which is weird because I have another class that declares class variables in this manner and seems to work fine. The only thing I can think of is that the constant isn't being recognised.
I have managed to pull this off with a constructor but I'm looking for a simpler solution before resorting to that.
EDIT
The global ${SYSTEM} variable is an array with a lot of other child arrays in it. Unfortunately there doesn't seem to be a way to get around using a constructor...
Ok, hopefully I've got the gist of what you're trying to achieve
<?php
// the global array you want to access
$GLOBALS['uname'] = array('kernel-name' => 'Linux', 'kernel-release' => '2.6.27-11-generic', 'machine' => 'i686');
// the defined constant used to reference the global var
define(_SYSTEM_, 'uname');
class Foo {
// a method where you'd liked to access the global var
public function bar() {
print_r($this->{_SYSTEM_});
}
// the magic happens here using php5 overloading
public function __get($d) {
return $GLOBALS[$d];
}
}
$foo = new Foo;
$foo->bar();
?>
This is how I access things globally without global.
class exampleGetInstance
{
private static $instance;
public $value1;
public $value2;
private function initialize()
{
$this->value1 = 'test value';
$this->value2 = 'test value2';
}
public function getInstance()
{
if (!isset(self::$instance))
{
$class = __CLASS__;
self::$instance = new $class();
self::$instance->initialize();
}
return self::$instance;
}
}
$myInstance = exampleGetInstance::getInstance();
echo $myInstance->value1;
$myInstance is now a reference to the instance of exampleGetInstance class.
Fixed formatting
You could use a constructor like this:
class Myclass {
public $classvar;
function Myclass() {
$this->classvar = $GLOBALS[SYSTEM];
}
}
EDIT: Thanks for pointing out the typo, Peter!
This works for array too. If assignment is not desired, taking the reference also works:
$this->classvar =& $GLOBALS[SYSTEM];
EDIT2: The following code was used to test this method and it worked on my system:
<?php
define('MYCONST', 'varname');
$varname = array("This is varname", "and array?");
class Myclass {
public $classvar;
function Myclass() {
$this->classvar =& $GLOBALS[MYCONST];
}
function printvar() {
echo $this->classvar[0];
echo $this->classvar[1];
}
};
$myobj = new Myclass;
$myobj->printvar();
?>
The direct specification of member variables can not contain any references to other variables (class {public $membervar = $outsidevar;} is invalid as well). Use a constructor instead.
However, as you are dealing with a constant, why don't you use php's constant or class constant facilities?
You're trying to do something really out-of-the-ordinary here, so you can expect it to be awkward. Working with globals is never pleasant, especially not with your dynamic name selection using SYSTEM constant. Personally I'd recommend you use $GLOBALS[SYSTEM] everywhere instead, or ...
$sys = $GLOBALS[SYSTEM];
... if you're going to use it alot.
You could also try the singleton pattern, although to some degree it is frowned upon in OOP circles, it is commonly referred to as the global variable of classes.
<?php
class Singleton {
// object instance
private static $instance;
// The protected construct prevents instantiating the class externally. The construct can be
// empty, or it can contain additional instructions...
protected function __construct() {
...
}
// The clone and wakeup methods prevents external instantiation of copies of the Singleton class,
// thus eliminating the possibility of duplicate objects. The methods can be empty, or
// can contain additional code (most probably generating error messages in response
// to attempts to call).
public function __clone() {
trigger_error('Clone is not allowed.', E_USER_ERROR);
}
public function __wakeup() {
trigger_error('Deserializing is not allowed.', E_USER_ERROR);
}
//This method must be static, and must return an instance of the object if the object
//does not already exist.
public static function getInstance() {
if (!self::$instance instanceof self) {
self::$instance = new self;
}
return self::$instance;
}
//One or more public methods that grant access to the Singleton object, and its private
//methods and properties via accessor methods.
public function GetSystemVar() {
...
}
}
//usage
Singleton::getInstance()->GetSystemVar();
?>
This example is slightly modified from wikipedia, but you can get the idea. Try googling the singleton pattern for more information
I'd say the first two things that stand out to me are:
You don't need the brackets around the variable name, you can simply do public $system or public $SYSTEM.
While PHP may not always require it it is standard practice to encapsulate non-numeric array indexes in single or double quotes in case the string you're using becomes a constant at some point.
This should be what you're looking for
class SomeClass {
public $system = $GLOBALS['system'];
}
You can also use class constants which would instead be
class SomeClass {
const SYSTEM = $GLOBALS['system'];
}
This can be referenced within the class with 'self::SYSTEM' and externally with 'SomeClass::SYSTEM'.