Yii фреймворк "meta db model" создание + наследование postgres - PullRequest
0 голосов
/ 25 августа 2010

У меня есть несколько таблиц БД, которые создаются с использованием наследования из одной таблицы. Это своего рода «шаблон» для создания новых таблиц, и теперь у меня есть набор бизнес-логических методов, которые работают с столбцами, наследуемыми от шаблона, дополнительными столбцами.используются только в качестве параметров для представления моделей, они не имеют значения для логики.

Цель состоит в том, чтобы разделить бизнес-логические методы по всем этим таблицам, я знаю, теперь это можно сделать, добавив еще однуКласс witch расширяет CActiveRecord, расширяет из него каждую модель или упаковывает логику как поведение и добавляет ее к моделям.Но для этого потребуется написать как минимум файл класса «dump» для каждой таблицы / модели, но эти таблицы «живут» в системе и будут удалены / созданы с жизненным циклом системы.

Есть ли способнаписать какую-нибудь «метамодель», которую примет в качестве параметра имя таблицы или, может быть, какой-нибудь способ создать модели для таблиц «на лету» и добавить к ним бизнес-логику?

I 'Мы задавали этот вопрос на доске объявлений Yii, но не нашли никакого ответа: / Я считаю, что это своего рода вызов кода, поэтому любая помощь / подсказки приветствуются:)

[ПРАВИТЬ]

Некоторые примеры: таблицы для разных клиентских устройств

  • hfc.cable_modem
  • lan.switch_port
  • lan.voip_gateway
  • (в ближайшем будущем в систему будет добавлено больше «технологий», поэтому появятся новые таблицы для клиентских устройств и будет возможность отказаться от поддержки некоторых из них)

для каждой таблицынаследует от таблицы шаблонов client_device, у которой есть поля:

  • client_id
  • service_id
  • core_device_id
  • (плюс некоторые мета-столбцы для поведения с меткой времени, такого как созданный, обновленный, обновляющий и т. Д.)

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

Моя цель - иметь "метамодель«клиентское устройство, которое будет применять бизнес-логику ко всем этим таблицам и по-прежнему обеспечивать для каждой из них доступ к определенным полям без необходимости писать класс модели для каждой таблицы (ведь мне придется это делать каждый раз,когда будет добавлена ​​новая технология или в будущем будет прекращена поддержка данной технологии)

1 Ответ

2 голосов
/ 26 августа 2010

Ну, если я вас правильно понял, у меня есть предложение, основанное на чем-то похожем, что я делаю:

У меня есть базовая "особенность" модели. Но эта функция может быть «текстовой» или «графической» и т. Д. Но все они имеют общий «идентификатор функции» и несколько других столбцов. Поэтому я выбрал подход EAV . У меня есть одна таблица «функций», а затем у меня есть таблица для каждого подтипа (текст, изображение и т. Д.). Один из столбцов в таблице «Feature» содержит информацию о подтипе. Затем в моем методе "afterFind ()" на базовой модели "Feature" я смотрю на столбец подтипа. Если подтипом является «текст», я присоединяю поведение «текстового» типа, которое я сделал. Это поведение получает переменные из таблицы подтипов и настраивает их для доступа так же, как атрибуты базовой модели.

Примерно так:

client_device_table : (базовая таблица)
-client_id (первичный ключ)
-service_id
-core_device_id
-device_type (имя поведения, например CableModemBehavior или VoipGatewayBehavior)

cable_modem_table
-core_device_id
-modem_info_1
-modem_into_2

voip_gateway_table
-core_device_id
-gateway_info_1
-gateway_into_2

В модели ClientDevice CActiveRecord (базовая модель):

protected function afterFind() {
  parent::afterFind();
  // remember $this->device_type holds the relevant behavior i.e. CableModemBehavior
  $this->attachBehavior($this->device_type,call_user_func(array($this->device_type, 'model')));
}

И поведение выглядит примерно так:

class CableModemBehavior extends CActiveRecordBehavior {
  public modem_info_1;
  public modem_info_2;
  public function attach($owner)
  {
    parent::attach($owner);
    $connection = Yii::app()->getDb();
    $command=$connection->createCommand("SELECT * 
      FROM cable_modem_table 
      WHERE core_device_id=:device_id");
    $command->bindParam(':device_id',$this->owner->core_device_id);
    $data=$command->queryRow();
    $this->modem_info_1 = $data->modem_info_1;
    $this->modem_info_2 = $data->modem_info_2;
  }
}

Это не проверено, но СЛЕДУЕТ произойти сейчас, если вы получите модель ClientDevice с CableModemBehavior в качестве записи столбца подтипа , вы сможете получить доступ к атрибутам модема (modem_info_1) так же, как обычные атрибуты ClientDevice (client_id):

ClientDevice-> modem_info_1

Будет, конечно, нечто большее, чем это. Это только для случая "найти". Вам нужно будет проделать еще некоторую работу, чтобы заставить массовое назначение атрибутов работать для $ _POST, или передавать Relations, или добавить методы afterDelete, validate и afterSave для поддержки сохранения и удаления и т. Д., Но я надеюсь, что это полезно начать.

Вы также можете сделать это намного лучше, переопределив методы __get и __set базовой модели в поведении, так что если запрашивается столбец из таблицы подтипов, он идет и получает его из текстовой таблицы прозрачно, выполнение поиска схемы для получения имен столбцов и т. д. Лучше, чем жесткое кодирование, как я делал в этом примере. Было бы полезно взглянуть на EavBehavior в репозитории yiiext и AdvancedArBehavior (или аналогичных), чтобы понять, как сделать его более гладким. Вместо поведения для каждого подтипа, вы можете иметь общее поведение и просто передать имя таблицы подтипов. (ооо мне это нравится на самом деле)

Ура!

...