2011-12-16 5 views
0

Представьте, что у вас есть список некоторых объектов. Эти объекты являются экземплярами различных классов, которые расширяют базовый класс. Теперь я хотел бы сохранить эти объекты в базе данных.Динамические классы: хорошая практика?

В качестве дополнительного требования количество классов, которое расширяет базовый класс, может быть довольно большим.

Это хорошая практика, чтобы сохранить имя класса в виде строки в базе данных и извлечь его так:

<?php 
class Page { 
    abstract public function foo($args); 
} 

class ChartPage : Page{ 
    public function foo($args){ 
     var_dump($args); 
    } 
} 

// other classes like ChartPage would be defined here 

// fetched row from a MySQL database 
$row = array("id" => 21, "title" => "Test", "class" => "ChartPage", "args" => "{}"); 
$object = new $row['class']; 
$object->foo($row['args']); 
?> 

Существуют ли какие-либо методы, чтобы сделать что-нибудь подобное в лучшую сторону?

ответ

1

Если у вас нет особых причин для написания собственных функций для сериализации/десериализации те, которые доступны изначально в PHP:

Вы можете прочитать подробнее о Сериализации объектов PHP по следующей ссылке:

Если сериализованные данные для совместного использования с вещами вне PHP вы можете выбрать другой метод сериализации, как JSON или XML. Но если это просто вопрос хранения объектов для доступа через PHP, стандартные методы сериализации более чем достаточны.


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

Конечно, я видел методы десериализации, в которых ключи сериализованных данных использовались для поиска наилучших совпадающих типов объектов, но это не то, что я рекомендую, поскольку он не является 100% точным для всех случаев.


В вашем примере фрагмент кода я предполагаю, что Page::foo будет использоваться как завод строит свой новый класс.

Если вы собираетесь писать собственные методы сериализации/десериализации данных и хотите сохранить все данные, которые вам не нужны, чтобы заставить классы, которые наследуют Page, реализовать завод.

Page мог бы также иметь единый метод сериализации произвольных классов путем прокрутки пары ключ/значение, содержащейся в этом объекте. Однако есть небольшая проблема с этим подходом.

Если унаследованный объект имеет довольно сложный элемент (т. Е. Не базовый, например, определенный пользователем класс), вы можете не захотеть его точно сохранить.

Например, если объект имеет активное соединение mysql, вы хотите сохранить учетные данные для повторного открытия такого соединения, потому что как вы собираетесь хранить это соединение в своих сериализованных данных?

С другой стороны, хранение дескриптора файла, связанного с подключением сокета, и его открытие с использованием воображаемого объекта MySQLKeepConnAlive, который всегда работает в фоновом режиме, будет прохладным, но это часто бывает необходимо.

В любом случае; Если бы я был вами, я бы написал метод по умолчанию для сериализации/десериализации, доступный в базовом объекте, если унаследованный тип является сложным, разработчик должен переопределить эти методы и предоставить свои собственные методы.

Я бы сохранил объект, используя структуру данных, как показано ниже, что не так далеко от того, что вы описали ранее. «__PAYLOAD» будет содержать члены объекта, другие значения должны быть определены в базовом классе.

«__PAYLOAD» не будет выглядеть одинаково для двух экземпляров разных классов, но будет единый способ загрузки объекта с определенным идентификатором и типом и определения базовой информации об объекте.

Конечно, вы можете добавить больше «базовых» полей, чем показано ниже, это всего лишь пример того, что я думаю.

$serialized_data = array (
    '__TITLE': 'Test', 
    '__TYPE': 'CharPage', 
    '__ID':   21, 
    '__PAYLOAD': array (
    'member_1' => 'foobar', 
    'member_2' => 'barbaz', 
    'member_3' => 'bazbir' 
) 
); 
Смежные вопросы