ZF2 - База данных транзакций с обновлением нескольких таблиц

Я хочу использовать транзакцию БД ZF2 для обновления нескольких таблиц. Обычно я делаю транзакцию примерно так для одной таблицы:

 $connection = null;
 try {
        $connection = $this->tableGateway->getAdapter()->getDriver()->getConnection();
        $connection->beginTransaction();
        $this->tableGateway->insert($data);
        $connection->commit();
     }
  catch (Exception $e) {
       if ($connection instanceof \Zend\Db\Adapter\Driver\ConnectionInterface) {
          $connection->rollback();
       }
  }

Теперь я хочу обновить две таблицы внутри одной транзакции. В ZF1 я сделал это, создав экземпляр класса table2 и вызвав соответствующий метод внутри той же транзакции. Но так как я не знаю метод для вызова другого класса модели внутри модели, я не могу сделать как ZF1. Мне это нужно для такой простой задачи, как добавление новых строк в таблицу tbl_invoice и обновление рабочего номера таблицы tbl_runno для счетов при вводе нового счета (счета).

2 ответа

В вашем контроллере вы можете сделать:

$db = $this->getServiceLocator()->get('Zend\Db\Adapter\Adapter');
$con = $db->getDriver()->getConnection();
$con->beginTransaction();
try {
    //get tables and do sth
    $con->commit();
} catch (Exception $e) {
    $con->rollback();
}

Используйте шаблон проектирования DataMapper. Pattern TableGateway служит для проецирования данных в одну таблицу.

  • http://akrabat.com/development/objects-in-the-model-layer
  • http://akrabat.com/php/objects-in-the-model-layer-part-2
  • http://www.slideshare.net/aaronsaray/midwest-php-2013
  • https://leanpub.com/zendframework2-en Вы можете использовать что-то вроде этого:

    namespace ScContent\Mapper;
    
    use Zend\Db\Sql\Sql;
    use Zend\Db\Sql\Select;
    use Zend\Db\Sql\SqlInterface;
    use Zend\Db\Sql\PreparableSqlInterface;
    
    use Zend\Db\Adapter\AdapterInterface;
    use Zend\Db\Adapter\Driver\ResultInterface;
    
    use Zend\Stdlib\Hydrator\ClassMethods;
    use Zend\StdLib\Hydrator\HydratorInterface;
    
    abstract class AbstractDbMapper
    {
        /**
         * @var string
         */
        const JoinInner = Select::JOIN_INNER;
    
        /**
         * @var string
         */
        const JoinLeft = Select::JOIN_LEFT;
    
        /**
         * @var string
         */
        const JoinRight = Select::JOIN_RIGHT;
    
        /**
         * @var Zend\Db\Adapter\AdapterInterface
         */
        protected $_adapter;
    
        /**
         * @var Zend\Db\Sql\SqlInterface
         */
        protected $_sql;
    
        /**
         * @var Zend\Stdlib\HydratorInterface
         */
        protected $_hydrator;
    
        /**
         * @var array
         */
        protected $_tables = array();
    
        /**
         * @param Zend\Db\Adapter\AdapterInterface $adapter
         */
        public function setAdapter(AdapterInterface $adapter)
        {
            $this->_adapter = $adapter;
        }
    
        /**
         * @return Zend\Db\Adapter\AdapterInterface
         */
        public function getAdapter()
        {
            if(!$this->_adapter instanceof AdapterInterface) {
                throw new Exception('Adapter is not installed.');
            }
            return $this->_adapter;
        }
    
        /**
         * @param Zend\Db\Sql\SqlInterface $sql
         */
        public function setSql(SqlInterface $sql)
        {
            $this->_sql = $sql;
        }
    
        /**
         * @return Zend\Db\Sql\SqlInterface
         */
        public function getSql()
        {
            if(!$this->_sql instanceof SqlInterface) {
                $this->_sql = new Sql($this->getAdapter());
            }
            return $this->_sql;
        }
    
        /**
         * @param Zend\Stdlib\HydratorInterface $hydrator
         */
        public function setHydrator(HydratorInterface $hydrator)
        {
            $this->_hydrator = $hydrator;
        }
    
        /**
         * @return Zend\Stdlib\HydratorInterface
         */
        public function getHydrator()
        {
            if(!$this->_hydrator instanceof HydratorInterface) {
                $this->_hydrator = new ClassMethods();
            }
            return $this->_hydrator;
        }
    
        /**
         * @param string $alias
         * @param string $name
         */
        public function setTable($alias, $name)
        {
            $this->_tables[$alias] = $name;
        }
    
        /**
         * @param string $alias
         * @throws Exception
         * @return string
         */
        public function getTable($alias)
        {
            if(!array_key_exists($alias, $this->_tables)) {
                throw new Exception(sprintf("Unknown table alias '%s'.", $alias));
            }
            return $this->_tables[$alias];
        }
    
        /**
         * @return int|null|false
         */
        protected function lastInsertId()
        {
            return $this->adapter->getDriver()->getConnection()->getLastGeneratedValue();
        }
    
        /**
         * @param void
         * @return void
         */
        protected function beginTransaction()
        {
            $this->getAdapter()->getDriver()->getConnection()->beginTransaction();
        }
    
        /**
         * @param void
         * @return void
         */
        protected function commit()
        {
            $this->getAdapter()->getDriver()->getConnection()->commit();
        }
    
        /**
         * @return bool
         */
        protected function inTransaction()
        {
            return $this->getAdapter()->getDriver()
                ->getConnection()->getResource()->inTransaction();
        }
    
        /**
         * @param void
         * @return void
         */
        protected function rollBack()
        {
            $this->getAdapter()->getDriver()->getConnection()->rollBack();
        }
    
        /**
         * @param Zend\Db\Sql\PreparableSqlInterface $sqlObject
         * @return Zend\Db\Adapter\ResultInterface
         */
        protected function execute(PreparableSqlInterface $sqlObject)
        {
            return $this->getSql()->prepareStatementForSqlObject($sqlObject)->execute();
        }
    
        /**
         * @param Zend\Db\Adapter\ResultInterface $source
         * @return array
         */
        protected function toArray(ResultInterface $source)
        {
            $result = array();
            foreach($source as $item) {
                $result[] = $item;
            }
            return $result;
        }
    
        /**
         *
         */
        protected function toString(SqlInterface $sqlObject)
        {
            return $this->getSql()->getSqlStringForSqlObject($sqlObject);
        }
    }
    

    Пример использования:

    <?php  
    
    
    namespace ScContent\Mapper;
    
    use Zend\Db\Adapter\AdapterInterface;
    
    class ContentMapper extends AbstractDbMapper
    {
        /**
         * @var string
         */
        const ContentTableAlias = 'contentalias';
    
        /**
         * @var string
         */
        const UsersTableAlias = 'usersalias';
    
        /**
         * @param AdapterInterface $adapter
         */
        public function __construct(AdapterInterface $adapter) {
            $this->setAdapter($adapter);
        }
    
        /**
         * @var array
         */
        protected $_tables = array(
            self::ContentTableAlias => 'sc_content',
            self::UsersTableAlias   => 'sc_users'
        );
    
        /**
         * @param integer $id
         * @return null | array
         */
        public function findById($id)
        {
            $select = $this->getSql()->select()
                ->from(array('content' => $this->getTable(self::ContentTableAlias)))
                ->join(
                    array('users' => $this->getTable(self::UsersTableAlias)),
                    'content.author = users.user_id',
                    array('username'),
                    self::JoinInner
                )
                ->where(array('`content`.`id` = ?' => $id));
            return $this->execute($select)->current();
        }
    }
    
Другие вопросы по тегам