I'm wondering if it's possible, and in case it is, how shoud I achive that:
$this->id <-- i have such thing. but to make it more usable i'd like to have $this->(and here to change the values)
for ex: I might have $this->id $this->allID $this->proj_id
how can I make so that actually I have $this->($myvariable here, that has a unique name in it)?
You can simply use this:
$variable = 'id';
if ( isset ( $this->{$variable} ) )
{
echo $this->{$variable};
}
Here is the solution : http://www.php.net/manual/en/language.oop5.overloading.php#language.oop5.overloading.members
An example of using it is here :
class myClass {
/** Location for overloaded data. */
private $myProperties = array();
public function __set($name, $value)
{
$this->myProperties[$name] = $value;
}
public function __get($name)
{
if (array_key_exists($name, $this->myProperties))
{
return $this->data[$name];
}
}
}
You should check out the variable variables manual on the PHP site.
With that, it could look like:
<?php
echo ${'this->'.$yourvariable};
?>
I prefer to use call_user_func and pass the parameters as array instead.
public function dynamicGetterExample()
{
$property = 'name'; // as an example...
$getter = 'get'.ucfirst($property);
$value = call_user_func(array($this,$getter));
if (empty($value)) {
throw new \Exception('Required value is empty for property '.$property);
}
return $value;
}
Related
I want to declare a variable inside a class with an unknown name
class Example {
function newVar($name, $value) {
$this->$name = $value;
}
}
And I want to use it that way
$c = new Example();
$c->newVar('MyVariableName', "This is my Value");
echo($c->MyVariableName);
The Important thing is, that I do not know the name of the variable. So I cannot put a public $MyVariable inside the class.
Is that in anyway possible? and if yes, can i do this with different scopes (private, protected, public) ?
U should use magic methods __get and __set (example without checking):
class Example {
private $data = [];
function newVar($name, $value) {
$this->data[$name] = $value;
}
public function __get($property) {
return $this->data[$property];
}
public function __set($property, $value) {
$this->data[$property] = $value;
}
}
$c = new Example();
$c->newVar('MyVariableName', "This is my Value");
echo($c->MyVariableName);
// This is my Value
$c->MyVariableName = "New value";
echo($c->MyVariableName);
// New value
See http://php.net/manual/en/language.oop5.magic.php
If i am understanding this correctly you can tweak a little bit by using key value array
class Example {
private $temp;
function __construct(){
$this->temp = array();
}
function newVar($name, $value) {
$this->temp[$name] = $value;
}
function getVar($name){
return $this->temp[$name];
}
}
$c = new Example();
$c->newVar('MyVariableName', "This is my Value");
echo($c->getVar('MyVariableName'));
Instead of using private you can use protected as well.
Your looking for magic calling. In PHP you can use the __call() function to do stuff like that. Have a look here: http://www.garfieldtech.com/blog/magical-php-call
Off the top of my head, something like
function __call($vari, $args){
if(isset($this->$vari){
$return = $this->$vari;
}else{
$return = "Nothing set with that name";
}
}
This will also work for private, protected and public. Can also use it to call methods as required in a class
I was wondering if you could get the class name and property name from a property reference in PHP?
class Test {
public static $TestProp;
}
GetDoc(& Test::$TestProp);
function GetDoc($prop) {
$className = getClassName($prop);
$propertyName = getPropertyName($prop);
}
what I'm looking for is if it is possible to create the functions getClassName and getPropertyName?
What you want is basically not possible; a property doesn't know its parent structure.
The only sane thing I could think of is to use reflection for it:
class Test
{
public static $TestProp = '123';
}
//GetDoc(& Test::$TestProp);
GetDoc('Test', 'TestProp');
function GetDoc($className, $propName)
{
$rc = new ReflectionClass($className);
$propValue = $rc->getStaticPropertyValue($propName);
}
Within the Test class you could use __CLASS__ as a convenient reference for the class name.
I have figured out the way to get this to work there is a lot of magic that goes on just to get this to work, but in my case it's worth it.
class Test {
private $props = array();
function __get($name) {
return new Property(get_called_class(), $name, $this->props[$name]);
}
function __set($name, $value) {
$props[$name] = $value;
}
}
class Property {
public $name;
public $class;
public $value;
function __construct($class, $name, $value) {
$this->name = $name;
$this->class = $class;
$this->value = $value;
}
function __toString() {
return $value.'';
}
}
function GetClassByProperty($prop) {
return $prop->class.'->'.$prop->name;
}
$t = new Test();
$t->Name = "Test";
echo GetClassByProperty($t->Name);
this example yes I know it's complex, but it does the job how I'd want it to, will print out "Test->Name" I can also get the value by saying $prop->value. If I want to compare the value to another object I can simply do this:
if($t->Name == "Test") { echo "It worked!!"; }
hope this isn't too confusing but it was a fun exploration into PHP.
Php have a build in function called get_class
class Car {
function __construct() {
// echo 'car con';
}
function setInfo($car_arr) {
foreach ($car_arr as $key => $value) {
$this->{$key} = $value;
}
}
}
i try to access like bellow
$car1 = new Car();
$car1->setInfo('make', 'Toyota')->setInfo('model', 'scp10');
that gave to me bellow error
Call to a member function setInfo() on a non-object
how can i change setInfo() method call $car1->setInfo('make', 'Toyota')->setInfo('model', 'scp10'); after that car class set $make = 'Toyota', like that
how can i print this object like
bellow
make = Toyota
model = scp10
You need to add return $this; in the end of your method for chain-like calls.
change the setInfo code to return itself like:
function setInfo($car_arr,$car_val=null) {
if(is_array($car_arr)){
foreach ($car_arr as $key => $value) {
$this->{$key} = $value;
}
}else if(is_string($car_arr) && $car_val != null){
$this->{$car_arr} = $car_val;
}
return $this;
}
now you can chain the functions because its returning itself.
also if you want to call it like you want ( like $this->setInfo("make","Ford")) you need to add an else on is_array and add an optional parameter like shown in the code above
To combine all answers into one (well, except #EaterOfCorpses):
<?php
class Car {
private $data = array();
function setInfo(array $carInfo) {
foreach ($carInfo as $k => $v) {
$this->data[$k] = $v;
}
return $this;
}
function __set($key, $val) {
$this->data[$key] = $val;
}
function __get($key) {
return $this->data[$key];
}
}
$car = new Car();
$car->setInfo(['make' => 'Toyota', 'warranty' => '5 years']);
Note that there's no reason to return $this if you are setting all the properties at once.
Edited to add: also include magic getter/setter idea from Mark Baker just for the fun of it.
You should use $car1->setInfo('make', 'Toyota') only once. That's because you create a car, then set info, and then you want to set info to info, but you can't set info to info.
It's called a fluent interface
Add
return $this;
as the last line of your setInfo() method
Use array syntax: $car1->setInfo(array('make', 'Toyota'))
You can return $this in your function (if you have php 5.4):
function setInfo($car_arr) {
...
return $this;
}
Can anyone please explain to me why the following code does not set the values on the array as expected? $_SESSION['foo'] stays empty, even after assigning time() and rand(). I've checked, the __get accessor method is actually called when assigning the variables but they aren't stored for one reason or another.
$test = Session::getSession('test');
$test->foo = array();
$test->foo[] = time();
$test->foo['baz'] = rand(1,9);
var_dump($_SESSION);
Using this simple Session wrapper
class Session
{
protected $namespace = null;
public static function getSession($namespace)
{
return new Session($namespace);
}
public static function destroySession($namespace)
{
if(isset($_SESSION[$namespace])) {
unset($_SESSION[$namespace]);
return true;
}
return false;
}
private function __construct($namespace)
{
$this->namespace = $namespace;
if(!isset($_SESSION[$namespace])) {
$_SESSION[$namespace] = null;
}
}
public function &__get($name)
{
return (isset($_SESSION[$this->namespace][$name])) ? $_SESSION[$this->namespace][$name] : null;
}
public function __set($name, $value)
{
$_SESSION[$this->namespace][$name] = $value;
}
}
In case it might be relevant, i'm using php 5.3.6
I 'm not sure if this can be made to work at all.
For one, to return by reference you should add the & operator at the call site as well. I 'm not sure how that might be possible without screwing up the nice syntax you 're trying to achieve.
Also, you cannot return expressions by reference (only variables). So this won't work:
public function &__get($name)
{
return (isset($_SESSION[$this->namespace][$name]))
? $_SESSION[$this->namespace][$name]
: null;
}
At the very least it should be written as
public function &__get($name)
{
$value = isset($_SESSION[$this->namespace][$name])
? $_SESSION[$this->namespace][$name]
: null;
return $value;
}
Is there such a function like in_array, but can be used on objects?
Nope, but you can cast the object to an array and pass it into in_array().
$obj = new stdClass;
$obj->one = 1;
var_dump(in_array(1, (array) $obj)); // bool(true)
That violates all kinds of OOP principles though. See my comment on your question and Aron's answer.
First of all, arrays and objects are quite different.
A PHP object can not be iterated through like an array, by default. A way to implement object iteration is to implement the Iterator interface.
Concerning your specific question, you probably want to take a look at the ArrayAccess interface:
class obj implements ArrayAccess {
private $container = array();
public function __construct() {
$this->container = array(
"one" => 1,
"two" => 2,
"three" => 3,
);
}
public function offsetSet($offset, $value) {
if (is_null($offset)) {
$this->container[] = $value;
} else {
$this->container[$offset] = $value;
}
}
public function offsetExists($offset) {
return isset($this->container[$offset]);
}
public function offsetUnset($offset) {
unset($this->container[$offset]);
}
public function offsetGet($offset) {
return isset($this->container[$offset]) ? $this->container[$offset] : null;
}
}
Now you can access your object like an array in the following manner:
$object = new obj();
var_dump(isset($obj['two'])); // exists!
var_dump(isset($obj['foo'])); // does not exist
Before you go crazy on this though, please consider why you are actually trying to do this and take a look at the examples at php.net.
Option 2: when you are simply trying to see if a property exists, you can use property_exists() for this:
class foo {
public $bar = 'baz';
}
$object = new foo();
var_dump(property_exists($object, 'bar')); // true
You could cast the object to an array:
$obj = new stdClass();
$obj->var = 'foobar';
in_array( 'foobar', (array)$obj ); // true
function in_object($needle, $haystack) {
return in_array($needle, get_object_vars($haystack));
}
It's unbelievable how all the people miss the point of the usefulness of an in_object PHP method! Here is what I came up with, it is very useful, and you will see why!
Here is a simple function I wrote which will check if a value can be found within an object.
<?php
// in_object method
// to check if a value in an object exists.
function in_object($value,$object) {
if (is_object($object)) {
foreach($object as $key => $item) {
if ($value==$item) return $key;
}
}
return false;
}
?>
This is very useful if an object has been created dynamically (especially from external code, which you don't control, as in an application-plugin, CMS, etc), and you don't know the object's properties.
The above function will return the property, so you will be able to use it in your code later on.
Here is a very good basic example of how useful this function is!
<?php
class My_Class {
function __construct($key, $value) {
$this->$key = $value;
// As you can see, this is a dynamic class, its properties and values can be unknown...
}
}
function in_object($value,$object) {
if (is_object($object)) {
foreach($object as $key => $item) {
if ($value==$item) return $key;
}
}
return false;
}
function manipulate_property($value,$object) {
if ($property = in_object($value,$object)) {
// value found. I can now use this property.
// I can simply echo'it (makes no sense, as I could instead simply echo "value")
echo "<br />I found the property holding this value: ".$object->$property;
// or (here comes the good part)
// change the property
$object->$property = "This is a changed value!";
echo "<br />I changed the value to: ".$object->$property;
// or return it for use in my program flow
return $property;
} else {
echo "Value NOT FOUND!<br />";
return false;
}
}
// imagine if some function creates the class conditionally...
if ( 1 == 1) {
$class = new My_Class("property","Unchanged Value");
} else {
$class = new My_Class("property","Some Other Value");
}
// now let's check if the value we want exists, and if yes, let's have some fun with it...
$property = manipulate_property("Unchanged Value",$class);
if ($property) {
$my_variable = $class->$property;
echo "<br />This is my variable now:".$my_variable;
} else $my_variable = $some_other_variable;
?>
Just run it to see for yourself!
I don't recommend it, because it's very bad practice but you can use get_object_vars.
Gets the accessible non-static properties of the given object according to scope.
There are other limitations you should refer to the documentation to see if it is suitable for you.
if(in_array('find me', get_object_vars($obj)))
This is the most efficient and correct solution. With some modifications it could be applied to check any data type present in any object.
if(gettype($object->var1->var2) == "string"){
echo "Present";
}