Создание экземпляра объекта из отправленных данных - PHP - PullRequest
7 голосов
/ 16 сентября 2009

Каков наилучший способ создания и заполнения Объекта из значений, переданных из формы?

Если, например, у меня есть класс Car со свойствами Color, Model, Make, Year и методом Save, который либо вставит, либо обновит запись.

У меня есть форма, в которой есть поля для всех этих значений, и она отправляется. Я хочу создать экземпляр класса Car с опубликованными значениями, а затем вызвать метод Save. Все хорошо и хорошо.

Но каков наилучший способ присвоения публикуемых значений внутренним свойствам объектов? Предполагая, что это упрощенный сценарий, и в реальной ситуации будет гораздо больше свойств, что делает отдельные вызовы Set длительными.

Лучше ли просто вызывать метод Set для каждого из них? Или передать массив в метод (или конструктор), который затем вызывает методы Set? Или как-то иначе?

Любой совет по передовому опыту приветствуется

Приветствие Стюарт

Ответы [ 6 ]

6 голосов
/ 16 сентября 2009

Вы можете использовать немного Отражение магия:

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]);
    }
}

Вы можете реализовать этот метод в базовом классе и сделать так, чтобы весь объект yout наследовал от него, поэтому у вас есть эта функциональность в каждом объекте, не повторяя себя в каком-либо классе.

4 голосов
/ 16 сентября 2009

Если объекты общедоступны:

foreach($_POST as $key => $value)
    $obj->$key = $value;

Если им требуются сеттеры:

foreach($_POST as $key => $value) {
    $set = 'Set' . $key;
    $obj->$set($value);
}
2 голосов
/ 16 сентября 2009

Я бы реализовал магическую функцию __set_state(), так как она предназначена именно для этого варианта использования. Внедрение реализации в этот метод дает множество преимуществ:

  1. Очень хорошо определено, что делает эта функция (она определена в документации PHP, в отличие от вашего собственного исходного кода)
  2. Вы можете получить доступ к закрытым членам в функции
  3. Объекты, сброшенные с помощью var_export(), будут автоматически восстановлены с использованием этой функции.

РЕДАКТИРОВАТЬ В соответствии с просьбой в комментариях:

class A {
    private $member = 1000;
    public static function test(A $a) {
        echo $a->member;
    }
}
echo A::test(new A()); // outputs 1000

РЕДАКТИРОВАТЬ Выполнение еще одного запроса из комментариев:

Вы не можете знать, для какого класса был вызван статический метод, если вы не используете 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;
    }
}
1 голос
/ 16 сентября 2009

В случае, если объект, который вы публикуете, может стать более сложным, чем плоский список свойств в будущем (например, вложение, массивы как значения и т. Д.), Вы можете сначала создать объект JavaScript на стороне клиента и опубликовать его как JSON внутри одного параметра. Затем вы можете просто десериализовать строку JSON в объект PHP. PHP 5+ имеет встроенную поддержку десериализации JSON. Использование JSON позволит вам быть гибким в том, насколько сложным может быть ваш объект.

1 голос
/ 16 сентября 2009

Ну, вы можете преобразовать массив записей в объект за один шаг ...

$mypostobject = (object) $_POST;
echo $mypostobject->Colour;

РЕДАКТИРОВАТЬ: добавлена ​​ссылка на 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);
0 голосов
/ 16 сентября 2009

создать конструктор, который будет принимать все атрибуты

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
}

не забудьте заранее санировать / проверять ваш ввод! (не могу подчеркнуть это достаточно часто)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...