How to declare a public variable variable in a class - php

Hey I have a class like this
class derp{
public $$ini;
public static function regIni($ini){
derp::$$ini = 'test';
}
}
And then in another file I have
core::regIni('register');
And then somewhere else I use
core::$register;
This produces an error
public $$ini
is not valid code but if I leave it without I can not set
core::$$ini
How do I fix this?
Please note that $$ini is a variable variable meaning the value of $ini is actuely the variable name so $ini = 'registry' then $$ini actualy means $registry.

Why not use access methods for setting and getting class data?
class derp {
protected static $_data = array();
public static function regIni($ini, $value) {
derp::$_data[$ini] = $value;
}
public static function getIni($ini, $default = NULL) {
return isset(derp::$_data[$ini]) ? derp::$_data[$ini] : $default;
}
}

So, this is not an overly helpful answer, as I can just conclude that it's currently not possible.
You cannot define a new ReflectionProperty("derp", "static_prop") for example and attach it. It's really for introspection only.
$c = new ReflectionClass("derp"); and $derp->setStaticPropertyValue("p", 123); is not working either. The properties need to be predefined still.
And lastly, neither can the runkit_* functions help with this task. They are intended for changing methods mainly.
Same for classkit.
I'm not aware of other such PECL extensions, but that wouldn't be useful as general solution anyway. So for current PHP versions you cannot add static class properties after the parsing stage.

take a look at magic methods __set and __get

Mario said:
It's not doable. Static properties can
only be defined at the parsing stage.
Neither ReflectionProperty or
ReflectionClass::setStaticPropertyValue,
nor runkit_* functions are currently
capable (intended) to create static
class properties. Sorry
Geuss i'l settle for a work around then.
Made an array $ini and loaded the values into there derp:$ini['base']['key']
Thanks for the help,
Robin

Related

Checking that a method parameter is a class constant

At the moment i am trying to create a helper class for our template designers, that have minimal PHP knowledge, so i would like to make it as fool proof as possible.
In that process i have stumbled upon a question i never really considered before:
How does one check to see if a parameter to a method call is the value of a defined class constant?
I can think of several ways to do it using reflection or the like, but was wondering if there is some way more simple that i have overlooked.
Taking a class like the following:
class Foo{
const TYPE_A = 'A';
const TYPE_B = 'B';
const TYPE_C = 'C';
public static function doSomething($type){
//Check to see if $type is indeed a class constant
}
}
//This would work
Foo::doSomething(Foo::TYPE_A);
Foo::doSomething(Foo::TYPE_B);
Foo::doSomething(Foo::TYPE_C);
Foo::doSomething('A');
Foo::doSomething('B');
Foo::doSomething('C');
//This should fail
Foo::doSomething('BAR');
Besides using reflection i could just use a private array or the like, but that would really defeat the purpose of the constants, or require that data is updated several places.
Does not seem to be possible without reflection or custom hacks so i am closing this
You can check if the constant is defined with http://php.net/manual/en/function.defined.php
public static function doSomething($type){
if (defined('self::' . $type)) {
// do someting
}
}

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

Inheritance bug in PHP [duplicate]

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';
}
}

implicit class variable declaration in php?

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';
}
}

When do/should I use __construct(), __get(), __set(), and __call() in PHP?

A similar question discusses __construct, but I left it in my title for people searching who find this one.
Apparently, __get and __set take a parameter that is the variable being gotten or set. However, you have to know the variable name (eg, know that the age of the person is $age instead of $myAge). So I don't see the point if you HAVE to know a variable name, especially if you are working with code that you aren't familiar with (such as a library).
I found some pages that explain __get(), __set(), and __call(), but I still don't get why or when they are useful.
This page will probably be useful. (Note that what you say is incorrect - __set() takes as a parameter both the name of the variable and the value. __get() just takes the name of the variable).
__get() and __set() are useful in library functions where you want to provide generic access to variables. For example in an ActiveRecord class, you might want people to be able to access database fields as object properties. For example, in Kohana PHP framework you might use:
$user = ORM::factory('user', 1);
$email = $user->email_address;
This is accomplished by using __get() and __set().
Something similar can be accomplished when using __call(), i.e. you can detect when someone is calling getProperty() and setProperty() and handle accordingly.
__get(), __set(), and __call() are what PHP calls "magic methods" which is a moniker I think that is a bit silly - I think "hook" is a bit more apt. Anyway, I digress...
The purpose of these is to provide execution cases for when datamembers (properties, or methods) that are not defined on the object are accessed, which can be used for all sorts of "clever" thinks like variable hiding, message forwarding, etc.
There is a cost, however - a call that invokes these is around 10x slower than a call to defined datamembers.
Another useful application of magic methods, especially __get and __set and __toString is templates. You can make your code independent from template engine just by writing simple adapter that uses magic methods. In case you want to move to another template engine, just change these methods only.
class View {
public $templateFile;
protected $properties = array();
public function __set($property, $value) {
$this->properties[$property] = $value;
}
public function __get($property) {
return #$this->properties[$property];
}
public function __toString() {
require_once 'smarty/libs/Smarty.class.php';
$smarty = new Smarty();
$smarty->template_dir = 'view';
$smarty->compile_dir = 'smarty/compile';
$smarty->config_dir = 'smarty/config';
$smarty->cache_dir = 'smarty/cache';
foreach ($this->properties as $property => $value) {
$smarty->assign($property, $value);
}
return $smarty->fetch($this->templateFile);
}
}
Hidden benefit of this approach is that you can nest View objects one inside another:
$index = new View();
$index->templateFile = 'index.tpl';
$topNav = new View();
$topNav->templateFile = 'topNav.tpl';
$index->topNav = $topNav;
And in index.tpl, the nesting looks like that:
<html>
<head></head>
<body>
{$topNav}
Welcome to Foobar Corporation.
</body>
</html>
All nested View objects gets converted to string (HTML to be exact) on the fly, as soon as you echo $index;
Redefining __get and __set can be especially useful in core classes. For example if you didn't want your config to be overwritten accidentally but still wanted to get data from it:
class Example
{
private $config = array('password' => 'pAsSwOrD');
public function __get($name)
{
return $this->config[$name];
}
}
I think it is bad for design you code. If you know and do a good design then you will not need to use the __set() and __get() within your code. Also reading your code is very important and if you are using studio (e.g. Zend studio), with __set() and __get() you can't see your class properties.
PHP allows us to create class variables dynamically which can cause problems. You can use __set and __get methods to restrict this behavior..see the example below...
class Person {
public $name;
public function printProperties(){
print_r(get_object_vars($this));
}
}
$person = new Person();
$person->name = 'Jay'; //This is valid
$person->printProperties();
$person->age = '26'; //This shouldn't work...but it does
$person->printProperties();
to prevent above you can do this..
public function __set($name, $value){
$classVar = get_object_vars($this);
if(in_array($name, $classVar)){
$this->$name = $value;
}
}
Hope this helps...
They're for doing "clever" things.
For example you could use __set() and __get() to talk to a database. Your code would then be: $myObject->foo = "bar"; and this could update a database record behind the scenes. Of course you'd have to be pretty careful with this or your performance could suffer, hence the quotes around "clever" :)
Overloading methods is especially useful when working with PHP objects that contain data that should be easily accessable. __get() is called when accessing a non-existent propery, __set() is called when trying to write a non-existent property and __call() is called when a non-existent method is invoked.
For example, imagine having a class managing your config:
class Config
{
protected $_data = array();
public function __set($key, $val)
{
$this->_data[$key] = $val;
}
public function __get($key)
{
return $this->_data[$key];
}
...etc
}
This makes it a lot easier to read and write to the object, and gives you the change to use custom functionality when reading or writing to object.
Example:
$config = new Config();
$config->foo = 'bar';
echo $config->foo; // returns 'bar'
One good reason to use them would be in terms of a registry system (I think Zend Framework implements this as a Registry or Config class iirc), so you can do things like
$conf = new Config();
$conf->parent->child->grandchild = 'foo';
Each of those properties is an automatically generated Config object, something akin to:
function __get($key) {
return new Config($key);
}
Obviously if $conf->parent already existed, the __get() method wouldn't be called, so to use this to generate new variables is a nice trick.
Bear in mind this code I've just quoted isn't functionality, I just wrote it quickly for the sake of example.
Probably not the cleanest design in the world but I had a situation where I had a lot of code that was referencing an instance variable in a class, i.e.:
$obj->value = 'blah';
echo $obj->value;
but then later, I wanted to do something special when "value" was set under certain circumstances so I renamed the value variable and implemented __set() and __get() with the changes I needed.
The rest of the code didn't know the difference.

Categories