Как да промените името на Zend_Db_Table в рамките на модел, за да вмъкнете в множество таблици

Използвайки Zend Framework, създадох модел за вмъкване на запис в база данни. Въпросът ми е след $this->insert($data) как мога да превключа активната таблица, така че да мога да вмъкна запис в друга таблица?

Ето моят код досега:

class Model_DbTable_Foo extends Zend_Db_Table_Abstract
{
  protected $_name = 'foo';

  public function addFoo($params)
  {
    $data = array(
      'foo' => $params['foo'],
    );
    $this->insert($data);
    $foo_id = $this->getAdapter()->lastInsertId();

    $data2 = array(
      'bar' => $params['bar']
    );
    // I need to change the Db Table name here.
    $this->insert($data2);
    $bar_id = $this->getAdapter()->lastInsertId();
  }
}

person jwhat    schedule 12.03.2010    source източник


Отговори (3)


Zend_Db_Table е шлюз за таблични данни. То

действа като шлюз към таблица на база данни. Един екземпляр обработва всички редове в таблицата.

Това означава, че имате един клас на маса. Вашият Model_DbTable_Foo представлява таблицата Foo във вашата база данни и само тази таблица. Не трябва да прави вмъквания на други маси. Това е, за което бихте използвали друг клас таблица. Най-чистият вариант би бил да добавите друг слой върху вашите TDG, който знае как да обработва вмъквания в множество таблици, напр.

class Model_Gateway_FooBar
{
    protected $_tables;

    public function __construct(Zend_Db_Table_Abstract $foo, 
                                Zend_Db_Table_Abstract $bar)
    {
        $this->_tables['foo'] = $foo;
        $this->_tables['bar'] = $bar;
    }

    public function addFoo($data)
    {
        $this->_tables['foo']->insert($data['foo']);
        // yaddayaddayadda
        $this->_tables['bar']->insert($data['bar']);
    }
}

Въпреки това, това е вашето приложение и можете да решите да не се притеснявате и просто да създадете нов екземпляр на другия клас в класа Foo и да направите вмъкването от там, напр.

$otherTable = new Model_DbTable_Bar;
$otherTable->insert($data);

Друга възможност е да поставите логиката в контролера, но не мога да го препоръчам, защото това не е отговорност на контролера и обикновено контролерите трябва да са слаби, а моделите трябва да са дебели.

В странична бележка, когато правите множество вмъквания, може да искате да използвате транзакции, за да накарате и двете вмъквания да работят според очакванията, напр.

$this->_tables['foo']->getAdapter()->beginTransaction();

и след това commit() или rollback() в зависимост от резултата от заявката.

Също така имайте предвид, че от ZF1.9 можете също да създавате екземпляри на Zend_Db_Table, без да се налага първо да дефинирате конкретен подклас, напр.

$fooTable = new Zend_Db_Table('foo');

Вижте главата за Zend_Db_Table в ZF Reference Guide.

person Gordon    schedule 12.03.2010
comment
Страхотен съвет! Забравих всичко за транзакциите, определено искам да ги използвам. Благодаря! - person jwhat; 13.03.2010
comment
Гордън, можете ли да обясните защо бих искал да напиша cast $foo и $bar в конструктора като Zend_Db_Table_Abstract вместо моите персонализирани Model_DbTable_Foo и Model_DbTable_Bar? - person jwhat; 13.03.2010
comment
Само бележка за всеки друг, който се интересува от MySQL транзакции: трябваше да променя моя тип DB от MyISAM на InnoDB за поддръжка на транзакции. - person jwhat; 13.03.2010
comment
@jwhat това не е typecast, а typehint. Вижте php.net/manual/en/language.oop5.typehinting.php - можете да използвате вашите персонализирани класове на модели тук, но това ще свърже вашите конкретни класове на модели с шлюза. Когато използвате абстрактния клас за подсказка, вие се уверете, че предадените екземпляри са (само) екземпляри на таблица. Те не са непременно вашите персонализирани класове, но смисълът в този случай е да се уверите, че екземплярите имат методите на Zend_Db_Table_Abstract. Освен това е по-гъвкав, в случай че трябва да замените персонализирания клас с нещо друго. - person Gordon; 14.03.2010
comment
@jwhat Накратко: Винаги е по-добре да разчитате на абстрактни типове (интерфейси, абстрактни базови класове), а не на конкретни типове. Това ви позволява да промените изпълнението на метод, без да засягате нито един от неговите извикващи. - person Gordon; 14.03.2010

Мисля, че трябва да имате друг Model_DbTable, Model_DbTable_Bar и да го извикате

вътрешно:

class Model_DbTable_Foo ... {
  public function addFooAndBar() {
    ...
    $bar = new Model_DbTable_Bar();
    $bar->insert($data2);
  }
}

или външно:

class ModelX ... {
  public function addFoos() {
    $foo = new Model_DbTable_Foo();
    $foo->insert($data);
    $bar = new Model_DbTable_Bar();
    $bar->insert($data2);
  }
}
person chelmertz    schedule 12.03.2010
comment
Уникалните класове за уникални маси имат смисъл и се чувстват по-чисти. Благодаря! - person jwhat; 13.03.2010

Също така можете да използвате класа Zend_Db_Table. Нещо като това:

 $fooTbl = new Zend_Db_Table('foo');
 $lastFooID = $fooTbl->insert($data2)
                     ->getAdapter()
                     ->lastInsertId();
person RDK    schedule 03.10.2012