Table Gateway and fetching one filtered row
Closed this issue · 2 comments
I need to return a single rowset from my tablegateway but which match additional conditions.
However because I am using paginator to fetch multiple results I need to use getSql->select() in order to maanipulate and then pass that $select object to fetchAll().
My problem is fetchRow() method which looks like this:
protected function fetchRow($passedSelect)
{
$row = $this->tableGateway->select(function (\Zend\Db\Sql\Select $select) use ($passedSelect) {
$select = $passedSelect;
});
return $row->current();
}
And here is my TableGateway:
public function getBy(array $params = array())
{
$select = $this->tableGateway->getSql()->select();
if (isset($params['id'])) {
$select->where('id = ?', $params['id']);
$params['limit'] = 1;
}
if (isset($params['title'])) {
$select->where('title = ?', $params['title']);
}
if (isset($params['thumb'])) {
$select->where('thumb = ?', $params['thumb']);
}
if (isset($params['limit'])) {
$select->limit($params['limit']);
}
$result = (isset($params['limit']) && $params['limit'] == 1)
? $this->fetchRow($select)
: $this->fetchAll($select, ['limit' => $this->resultsPerPage, 'page' => $params['page']]);
return $result;
}
Usage:
$object->getBy(['id'] => 3);
Why closure in fetchRow(), return first element in table, instead of passed id of 3? It looks like closure doesn't overrride $select var at all.
No, it would not because closures do not overwrite original variables.
$select = $passedSelect;
Does not move $passedSelect
up to where $select
came from. Instead, there is a local variable $select
which is pointing to object from table gateway. Once you make it equal something else you are actually saying "I do not want original reference anymore, now $select
should be point to $passedSelect
instead". The change is within the closure only.
Instead of making a new select object and passing it to closure you can have
protected function fetchRow($passedSelect)
{
$row = $this->tableGateway->select(function (\Zend\Db\Sql\Select $select) use ($additionalCriteria) {
$select->where($additionalCriteria);
});
return $row->current();
}
As long as you do not destroy what $select is pointing to, you can perform operations on it, like adding your extra where statement with id
.
Thanks for your reply, I've managed to fixed it by doing the following:
public function getBy(array $params = array())
{
$select = $this->tableGateway->getSql()->select();
if (!isset($params['page'])) {
$params['page'] = 0;
}
if (isset($params['id'])) {
$select->where(['id' => $params['id']]);
$params['limit'] = 1;
}
if (isset($params['title'])) {
$select->where(['title' => $params['title']]);
}
if (isset($params['thumb'])) {
$select->where(['thumb' => $params['thumb']]);
}
if (isset($params['limit'])) {
$select->limit($params['limit']);
}
$result = (isset($params['limit']) && $params['limit'] == 1)
? $this->fetchRow($select)
: $this->fetchAll($select, ['limit' => $this->resultsPerPage, 'page' => $params['page']]);
return $result;
}
and inside AbstractTable:
protected function fetchRow($passedSelect)
{
$row = $this->tableGateway->selectWith($passedSelect);
return $row->current();
}