Интересно, можно ли сделать что-то вроде следующего (я знаю, что код не будет работать так, как задумано, просто пытаюсь донести цель):
class Form
{
private $v = array();
function __set($varName, $varValue)
{
... do some treatment on the varValue ...
$this->v[$varName] = $varValue;
}
function &__get($varName)
{
if(!isset($this->v[$varName]))
$this->v[$varName] = NULL;
return $this->v[$varName];
}
};
Я хочу иметь возможность установить такую переменную, как:
$form->Values['whatever'] = 'dirty';
И запустить его через функцию установки, которая вызовет некоторые операции очистки и фактически заполнит пару других массивов, таких как 'HtmlValues' и 'SqlValues', чтобы я мог просто вытащить значения, закодированные для нужного мне формата, чтобы позже я мог позвонить
echo $form->HtmlValues['whatever'];
Проблема, конечно, в том, что если вы просто используете _ get, вы в конечном итоге устанавливаете возвращаемое значение, и хотя & _get возвращает его по ссылке и что-то вроде работы, __set - это на самом деле никогда не вызывается, даже если вы устанавливаете частный член.
В общем, мне интересно, есть ли способ вызвать функцию для значения всякий раз, когда вы устанавливаете его в массиве (возможно, несколько массивов глубоких и что не нравится $form->Values['group']['item'] = 'whatever';
Желаемый результат будет примерно таким:
$form->Values['name'] = "&";
echo $form->HtmlValues['name']; = &
(Просто для подкрепления, я не ищу фактическую кодировку, а просто возможность вызывать ее для каждой переменной по мере ее установки / изменения без необходимости кодировать весь массив вручную)
3 ответа
Вы хотите реализовать интерфейс ArrayAccess. на связанной странице есть примеры того, как это сделать.
РЕДАКТИРОВАТЬ: Для облегчения доступа я включил пример с php.net ниже:
<?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;
}
}
$obj = new obj;
var_dump(isset($obj["two"]));
var_dump($obj["two"]);
unset($obj["two"]);
var_dump(isset($obj["two"]));
$obj["two"] = "A value";
var_dump($obj["two"]);
$obj[] = 'Append 1';
$obj[] = 'Append 2';
$obj[] = 'Append 3';
print_r($obj);
?>
Взгляните на ArrayAccess.
В этой ситуации я делаю так, чтобы __get()
возвращал объект, расширяющий ArrayObject
напрямую, а не массив.
private $v;
public function __construct()
{
$this->v = new ArrayObject(); // or MyArrayObject()
// repeat for each of your "arrays" you want to return
}
(Обратите внимание, что это отличается от реализации ArrayAccess
непосредственно родительским классом, что также может быть полезно в других ситуациях.)
Вот пример:
<?php
class MyArrayObject extends ArrayObject
{
private $validate;
public function __construct($validate)
{
parent::__construct();
$this->validate = $validate;
}
public function offsetSet($i, $v)
{
$validate = $this->validate;
if (!$validate($this, $i, $v))
throw new Exception();
parent::offsetSet($i, $v);
}
}
class Foo
{
private $v;
public function __construct()
{
$this->v = new MyArrayObject(function(MyArrayObject $me, $i, $v) {
// only accept values that are larger than 5
return $v > 5;
});
}
public function __get($key)
{
if ($key == 'bar') return $this->v;
}
}
$f = new Foo();
$f->bar[] = 10;
$f->bar[] = 5; // throws exception
Похожие вопросы
Связанные вопросы
Новые вопросы
php
PHP — это открытый, мультипарадигмальный, динамически типизированный и интерпретируемый язык сценариев, изначально разработанный для веб-разработки на стороне сервера. Используйте этот тег для вопросов о программировании на языке PHP.