Some code:
class MyClass
{
public function __get($key)
{
return $this[$key];
}
public function __set($key, $value)
{
$this[$key] = $value;
}
}
$m = new MyClass();
$m->name = 'This is my class.';
OR
$m['name'] = 'This is my class.';
But not working. Somebody can help me?
In order to be able to access values in your class using array access, you have to implement the ArrayAccess interface. In order to also arbitrary property names dynamically, copy the sample code from that page. Once you've implemented the ArrayAccess methods your __get and __set will work as-is.
<?php
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;
}
public function __get($key) {
return $this[$key];
}
public function __set($key, $value) {
$this[$key] = $value;
}
}
$foo = new obj();
$foo->pill = 123;
var_dump($foo->pill);
The problem you are having is that inside the __get and __set methods, you are accessing the properties as an array. You need to use $this->$key instead of $this[$key].
class MyClass
{
public function __get($key)
{
return $this->$key;
}
public function __set($key, $value)
{
$this->$key = $value;
}
}
$m = new MyClass();
echo "before set: \n";
var_dump($m);
$m->foo = "bar";
echo "after set: \n";
var_dump($m);
Example: http://codepad.viper-7.com/oNLbzq
Try this approach
class MyClass
{
private $m_var_data = array();
public function __set($p_name, $p_value)
{
$this->m_var_data[$p_name] = $p_value;
}
public function __get($p_name)
{
if (array_key_exists($p_name, $this->m_var_data))
{
return $this->m_var_data[$p_name];
}
}
}
$m = new MyClass();
$m->name = 'This is my class.';
In order to create a new property, you should do this:
class MyClass
{
private $data = array();
public function __set($name, $value)
{
echo "Setting '$name' to '$value'\n";
$this->data[$name] = $value;
}
public function __get($name)
{
echo "Getting '$name'\n";
if (array_key_exists($name, $this->data)) {
return $this->data[$name];
}
}
}
Then you can overload properties as you want in your example.
This link can give you more references:
http://www.php.net/manual/pt_BR/language.oop5.overloading.php#language.oop5.overloading.members
Related
I wrote this code for override a object method:
class A{
public function foo(){
echo "foo";
}
}
$a = new A();
$a->foo = function(){
echo "don't work";
}
$a->foo();
but the above code doesn't work i tried use a Closure but it didn't work.
so i wrote this utility class in my project, the class work and it works as expected.
class Wrapper
{
public $wrapped;
private $binds;
private $obj;
public function __construct($obj)
{
$this->wrapped = true;
$this->obj = $obj;
$this->binds = [];
}
public function bind($name, $function){
$this->binds[$name] = \Closure::bind($function, $this->obj, get_class($this->obj));
}
public function __set($name, $value)
{
$this->obj->$name = $value;
}
public function __get($name)
{
if(property_exists($this, $name)){
return $this->$name;
}
return $this->obj->$name;
}
public function __isset($name)
{
return isset($this->obj->$name);
}
public function __unset($name)
{
unset($this->obj->$name);
}
public function __call($name, $arguments)
{
if (array_key_exists($name, $this->binds) ) {
return call_user_func_array($this->binds[$name], $arguments);
}
return call_user_func_array([$this->obj, $name], $arguments);
}
public static function __callStatic($name, $arguments)
{
return call_user_func_array([get_class($this->obj, $name), $name], $arguments);
}
}
but the above class is a dirty fix, so how i can use the closure class or other method for do the same thing?
I've been doing a project in PHP for the last few hours and I have encountered into a problem.
The problem is I don't know how to access private variables in a class and I can't find it online.
Example:
<?php
class Example{
private $age;
public function __construct() {
$age = 14;
$this->checkAge();
}
private function checkAge() {
if($this->$age > 12)
echo "welcome!";
}
}
$boy = new Example();
?>
As far as I know, I should be able to access the variable with $this->$age but it isn't working.
Thank you.
EDIT: Got it working with help of the awesome stackoverflooooooooow community, this is how a working one looks.
<?php
class Example{
private $age;
public function __construct() {
$this->age = 14;
$this->checkAge();
}
private function checkAge() {
if($this->age > 12)
echo "welcome!";
}
}
$boy = new Example();
?>
Look at this approach.
first: create Entity that stores and retrieves data inside of private $attributes array, and with magic __set(), __get() You can also do like: $object->variable = 123
second: extend Entity with Human class and add some function specific to child class (for example hasValidAge()):
<?php
class Entity {
private $attributes;
public function __construct($attributes = []) {
$this->setAttributes($attributes);
}
public function setAttribute($key, $value) {
$this->attributes[$key] = $value;
return $this;
}
public function setAttributes($attributes = []) {
foreach($attributes AS $key => $value) {
$this->setAttribute($key, $value);
}
}
public function getAttribute($key, $fallback = null) {
return (isset($this->attributes[$key]))?
$this->attributes[$key] : $fallback;
}
public function __get($key) {
return $this->getAttribute($key);
}
public function __set($key, $value) {
$this->setAttribute($key, $value);
}
}
class Human extends Entity {
public function __construct($attributes = []) {
$this->setAttributes($attributes);
$this->checkAge();
}
public function hasValidAge() {
return ($this->getAttribute('age') > 12)? true : false;
}
}
$boy = new Human(['name' => 'Mark', 'age' => 14]);
if($boy->hasValidAge()) {
echo "Welcome ".$boy->name."!";
}
?>
p.s. I've removed echo "Welcome!" part from constructor because it's not cool to do echo from model object, in our example Human is model of Entity.
I'm getting value form Form class by creating object.It's working fine.But I wanna do it using static method.I tried but did not succeed.
public function display()
{
$newform=new Form();
echo "<pre>";
var_dump($newform->getAll());
var_dump($newform->get('name'));
}
<?php
class Form
{
private $value = array();
function __construct() {
// here you can use some validation or escapes
foreach($_POST as $key=>$value)
$this->value[$key] = $value;
}
public function getAll() {
return $this->value;
}
public function get($value) {
$this->value = $_POST[$value];
return $this->value;
}
}
Maybe You should just try to read PHP documentation about static keyword?
Example:
class Form {
private static $value = array();
public static function factory() {
// here you can use some validation or escapes
foreach($_POST as $key => $value) {
static::$value[$key] = $value;
}
}
public static function getAll() {
return static::$value;
}
public static function get($key) {
return static::$value[$key];
}
}
Use:
public function display() {
Form::factory();
echo "<pre>";
var_dump(Form::getAll());
var_dump(Form::get('name'));
echo "</pre>";
}
you do not declare a function as public/private/protected outside of the class
you you want to call this method statically, you may try it
<?php
function display()
{
$newform=new Form($_POST);
echo "<pre>";
var_dump(Form::getAll());
var_dump(Form::get('name'));
}
class Form
{
private static $value = array();
function __construct(){
// here you can use some validation or escapes
function __constract($array){
foreach($array as $key=>$value)
self::$value[$key] = $value;
}
}
public static function getAll(){
return self::$value;
}
public static function get($value){
self::$value = self::$value[$value];
return self::$value;
}
}
Here is an example for getAll method. For get method the same idea:
public function display()
{
var_dump(Form::getAll());
}
class Form
{
private static $value = array();
public static function initPost()
{
foreach($_POST as $key=>$value)
self::$value[$key] = $value;
}
public static function getAll()
{
return self::$value;
}
}
I have two Classes viz foo & Bar
class bar extends foo
{
public $element = null;
public function __construct()
{
}
}
and the Class foo goes as
class foo implements ArrayAccess
{
private $data = [];
private $elementId = null;
public function __call($functionName, $arguments)
{
if ($this->elementId !== null) {
echo "Function $functionName called with arguments " . print_r($arguments, true);
}
return true;
}
public function __construct($id = null)
{
$this->elementId = $id;
}
public function offsetSet($offset, $value)
{
if (is_null($offset)) {
$this->data[] = $value;
} else {
$this->data[$offset] = $value;
}
}
public function offsetExists($offset)
{
return isset($this->data[$offset]);
}
public function offsetUnset($offset)
{
if ($this->offsetExists($offset)) {
unset($this->data[$offset]);
}
}
public function offsetGet($offset)
{
if (!$this->offsetExists($offset)) {
$this->$offset = new foo($offset);
}
}
}
i want that when i run the below piece of code:
$a = new bar();
$a['saysomething']->sayHello('Hello Said!');
should return Function sayHello Called with arguments Hello Said! from foo's __call magic method.
Here, i want to say is saysomething should be passed in $this->elementId from foo's __construct function and sayHello should be taken as method and Hello Said should be taken as parameters for sayHello Function which would be rendered from __call magic method.
Also, need to chain methods like:
$a['saysomething']->sayHello('Hello Said!')->sayBye('Good Bye!');
If I'm not mistaken, you should change foo::offsetGet() to this:
public function offsetGet($offset)
{
if (!$this->offsetExists($offset)) {
return new self($this->elementId);
} else {
return $this->data[$offset];
}
}
It returns an instance of itself if there's no element at the given offset.
That said, foo::__construct() should be called from bar::__construct() as well and be passed a value other than null:
class bar extends foo
{
public $element = null;
public function __construct()
{
parent::__construct(42);
}
}
Update
To chain calls, you need to return the instance from __call():
public function __call($functionName, $arguments)
{
if ($this->elementId !== null) {
echo "Function $functionName called with arguments " . print_r($arguments, true);
}
return $this;
}
I am trying to store an array and manipulate that array using a custom class that extends ArrayObject.
class MyArrayObject extends ArrayObject {
protected $data = array();
public function offsetGet($name) {
return $this->data[$name];
}
public function offsetSet($name, $value) {
$this->data[$name] = $value;
}
public function offsetExists($name) {
return isset($this->data[$name]);
}
public function offsetUnset($name) {
unset($this->data[$name]);
}
}
The problem is if I do this:
$foo = new MyArrayObject();
$foo['blah'] = array('name' => 'bob');
$foo['blah']['name'] = 'fred';
echo $foo['blah']['name'];
The output is bob and not fred. Is there any way I can get this to work without changing the 4 lines above?
This is a known behaviour of ArrayAccess ("PHP Notice: Indirect modification of overloaded element of MyArrayObject has no effect" ...).
http://php.net/manual/en/class.arrayaccess.php
Implement this in MyArrayObject:
public function offsetSet($offset, $data) {
if (is_array($data)) $data = new self($data);
if ($offset === null) {
$this->data[] = $data;
} else {
$this->data[$offset] = $data;
}
}