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;
}
Related
I am noob in PHP because I am mostly do .NET/Java. In code base I am working, I have,
class SomeOtherBaseClass{
public $prop2;
public function __construct(string $prop3)
{
$this->prop2 = $prop3;
}
public function __toString()
{
return $this->prop2 . ' '. $this->prop2;
}
}
class SomeClass
{
public function __toString()
{
return $this->prop1 . ' '. $this->prop1;
}
public $prop1;
public function someMethod() : SomeOtherBaseClass
{
return $this->createClass();
}
public function __construct()
{
$this->prop1 = 'foo';
}
private function createClass(
): SomeOtherBaseClass {
return new class(
$this->prop1
) extends SomeOtherBaseClass {
};
}
}
$class = new SomeClass();
echo $class;
echo $class->someMethod();
Why I am getting error that prop1 not found. Clearly createClass function is part of SomeClass which have prop1. Why I cannot access prop1 inside createClass?
It's because $prop1 has no value or meaning.
You can add a __construct() function to resolve your issue:
public function __construct()
{
$this->prop1 = 'foo';
}
now when you call this class (e.g. $foo = new SomeClass();):
$prop1 has a value of foo which can be used in your functions:
public function echoProp()
{
echo $this->prop1; # will output foo
}
Note: This is just an explanation answer - not a copy/paste solution - but the principles are all here for you to use in your code.
Let me know if this wasn't what you were looking for :)
Edit:
if prop1 exists in SomeOtherClass, when you construct you can do
public function __construct()
{
$this->class = new SomeClass();
$this->prop1 = $this->class->prop1;
}
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'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'm trying to return data with chain static method , but i can't because the method return one thing only .
class Input
{
public static function set($input)
{
$data = $input;
$class = get_class();
return $data;
return self::$class = new $class;
}
public static function get()
{
echo ' - get method';
}
}
Input::set('ahmed')->get();
but it's only print " -get method "
I think you want
class Input
{
private static $data;
public static function set($input)
{
self::$data = $input;
return self;
}
public static function get()
{
echo self::$data.' - get method';
}
}
Input::set('ahmed')->get(); // ahmed - get method
but this you can use only once better is set name for value
class Input
{
private static $data = array();
public static function set($name, $input)
{
self::$data[$name] = $input;
return self;
}
public static function get($name)
{
echo self::$data[$name].' - get method';
}
}
Input::set('name', 'ahmed')->get('name'); // ahmed - get method
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