Каков наилучший способ создания и заполнения объекта из значений, переданных из формы?
Если, например, у меня есть класс Car со свойствами Color, Model, Make, Year и метод Save, который либо вставляет, либо обновляет запись.
Затем у меня есть форма, которая имеет поля для всех этих значений и отправляется. Я хочу создать экземпляр класса Car с опубликованными значениями, а затем вызвать метод Save. Все хорошо и хорошо.
Но каков наилучший способ присвоения опубликованных значений внутренним свойствам объектов. Предполагая, что это упрощенный сценарий, и реальная ситуация будет иметь гораздо больше свойств, делая индивидуальные вызовы Set длинными.
Лучше всего просто вызвать метод Set для каждого из них? Или передать массив в метод (или конструктор), который затем вызывает методы Set? Или каким-то другим способом?
Любые рекомендации по передовым методам оцениваются
Приветствия Стюарта
Я бы выполнил магическую функцию __set_state()
, поскольку он предназначен именно для этого варианта использования. Существует несколько преимуществ внедрения реализации в этот метод:
var_export()
будут автоматически восстановлены с использованием этой функции. РЕДАКТИРОВАТЬ В комментариях:
class A { private $member = 1000; public static function test(A $a) { echo $a->member; } } echo A::test(new A()); // outputs 1000
EDIT Выполнение другого запроса из комментариев:
Вы не можете знать, на каком классе был вызван статический метод, если вы не используете php 5.3, в котором была введена требуемая функция ( поздняя статическая привязка ). Что вы можете сделать при эмуляции get_called_class()
, анализируя текущий стек (используя debug_backtrace()
). Если у вас есть работающая get_called_class()
, вы можете сделать следующее:
class BaseClass { public static function __set_state($state) { $class = get_called_class(); // Assumption: Constructor can be invoked without parameters! $object = new $class(); foreach (get_class_vars($class) as $member) { if (!isset($state[$member])) { // Member was not provided, you can choose to ignore this case throw new Exception("$class::$member was not provided"); } else { // Set member directly // Assumption: members are all public or protected $object->$member = $state[$member]; // Or use the setter-approach given by Chaos. $setter = 'set' . ucfirst($member); $object->setter($state[$member]); } } return $object; } }
Вы можете использовать немного магии Reflection :
public function loadFromArray($array) { $class = new ReflectionClass(get_class($this)); $props = $class->getProperties(); foreach($props as $p) { if (isset($array[$p->getName()]) $p->setValue($this, $array[$p->getName]); } }
Вы можете реализовать этот метод в базовом классе и сделать все, что вы наследуете от этого объекта, так что у вас есть эта функция в каждом объекте, не повторяясь в любом классе.
Если свойства общедоступны:
foreach($_POST as $key => $value) $obj->$key = $value;
Если им нужны сеттеры:
foreach($_POST as $key => $value) { $set = 'Set' . $key; $obj->$set($value); }
Ну, вы можете преобразовать массив сообщений в объект за один шаг …
$mypostobject = (object) $_POST; echo $mypostobject->Colour;
EDIT: добавлена ссылка на документы PHP. http://uk.php.net/manual/en/language.types.object.php
Если вы хотите сделать это со своим классом объектов, то какой-то конструктор или функция, которая принимает массив сообщений и настроит ваш класс, будет в порядке.
class MyCar { public function __construct($postdata) { $this->Colour = $postdata['Colour']; // etc } }; $car = new MyCar($_POST);
В случае, если объект, который вы публикуете, может стать более сложным, чем плоский список свойств в будущем (думаю, вложенность, массивы как значения и т. Д.), Вы можете сначала создать объект JavaScript на стороне клиента и опубликовать его как JSON внутри один параметр. Затем вы можете просто десериализовать строку JSON в объект PHP. PHP 5+ имеет встроенную поддержку десериализации JSON. Использование JSON позволит вам быть гибким в том, насколько сложным может быть ваш объект.
создайте конструктор, который примет все атрибуты
class Car { // private members … public function __construct($color, $type, $model, $make) { // assign your values here } // other methods };
если вы имеете дело с ассоциативными массивами, вы также можете использовать конструктор с массивом в качестве аргумента:
public function __construct($car_properties) {}
и затем соедините ваши свойства с помощью
foreach($car_properties as $property => $value) { if(isset($value)) $this->property = $value }
не забудьте заранее проработать / подтвердить свой ввод! (не может этого достаточно подчеркнуть)