phpzend-frameworkzend-framework2zend-dbtablegateway

Pre functions for TableGateway in zend framework 2 (zf2)


I am using table gateway in zf2. This is simple model table with following working functions. I can insert or update records but I need to know how can we define functions like beforeInsert or beforeUpdate like we do in doctrine(beforePersist).

namespace Application\Model\AnyModel;

use Zend\Db\TableGateway\TableGateway;

class AnyModelTable {

protected $tableGateway;

public function __construct(TableGateway $tableGateway) {
    $this->tableGateway = $tableGateway;
}

public function fetchAll() {
    $resultSet = $this->tableGateway->select();
    return $resultSet;
}

public function getRecord($id) {
    $id = (int) $id;
    $rowSet = $this->tableGateway->select(array('id' => $id));
    $row = $rowSet->current();
    if (!$row) {
        throw new \Exception("Could not found record with $id");
    }
    return $row;
}

public function saveRecord(AnyModel $record) {
    $data = array(
        'name' => $record->name,
        'description' => $record->description,
        'status' => $record->status,
        'created_by' => $record->created_by,
        'created_on' => $record->created_on,
    );
    $id = (int) $record->id;
    if ($id == 0) {
        $this->tableGateway->insert($data);
    } else {
        if ($this->getUser($id)) {
            $this->tableGateway->update($data, array('id' => $id));
        } else {
            throw new \Exception("Could not update user with id $id");
        }
    }
}

public function deleteRecord($id) {
    $this->tableGateway->delete(array('id' => $id));
}

public function getArrayCopy() {
    return get_object_vars($this);
}

Solution

  • A simple and flexible solution would be to use an event manager instance into your table mapper and trigger the events in the correct place.

    I'll expand on the Event Manager's quick start example; ideally allot of this bloat could be abstracted out in an abstract class.

    <?php
    use Zend\EventManager\EventManagerInterface;
    use Zend\EventManager\EventManager;
    use Zend\EventManager\EventManagerAwareInterface;
    
    class Foo implements EventManagerAwareInterface
    {
        const EVENT_INSERT_PRE   = 'insert.pre';
        const EVENT_INSERT_POST  = 'insert.post';
        const EVENT_INSERT_ERROR = 'insert.error';
    
        protected $events;
    
        public function setEventManager(EventManagerInterface $events)
        {
            $events->setIdentifiers(array(
                __CLASS__,
                get_called_class(),
            ));
            $this->events = $events;
    
            $this->init($events);
    
            return $this;
        }
    
        public function getEventManager()
        {
            if (null === $this->events) {
                $this->setEventManager(new EventManager());
            }
            return $this->events;
        }
    
        protected function init(EventManagerInterface $events)
        {
            $events->attach(
                static::EVENT_INSERT_PRE, // event that we listen to
                array($this, 'onPreInsert') // The method that is triggered
                100 // The priority 
            );
        }
    
        public function save(AnyModel $record) 
        {
            try {
                $em = $this->getEventManager();
    
                $data = array('foo' => 'bar');
    
                $em->trigger(static::EVENT_INSERT_PRE, compact('record', 'data'));
                //...
                $this->tableGateway->insert($data);
                //...
                $em->trigger(static::EVENT_INSERT_POST, compact('record'));
    
                return true;
            } catch (\Exception $e) {
                $em->trigger(static::EVENT_INSERT_ERROR, compact('e'));
    
                return false;
            }
        }
    
        public function onPreInsert(EventInterface $event)
        {
            $data = $events->getParam('data', false);
    
            if ($data !== $someValidDataTypeOrValue) {
                return;
            }
            /** do stuff **/
        }
    }