Zend DB fetchAll(): where as array - zend-framework

I'm confused as to why Zend_DB doesn't accept an array of WHERE clauses - or am I incorrect? I have made the following work around:
$all = new ORM_Model_DbTable_Asset();
$wheres = array('id > 0', 'enabled' => 1);
$all = $all->fetchAll(implode(' AND ', $wheres))->toArray();
for what I hoped would be:
$all = new ORM_Model_DbTable_Asset();
$wheres = array('id > 0', 'enabled' => 1);
$all = $all->fetchAll($wheres)->toArray();
Slightly disappointing, am I missing something?

From Zend_Db_Table_Abstract
/**
* Fetches all rows.
*
* Honors the Zend_Db_Adapter fetch mode.
*
* #param string|array|Zend_Db_Table_Select $where OPTIONAL An SQL WHERE clause or Zend_Db_Table_Select object.
* #param string|array $order OPTIONAL An SQL ORDER clause.
* #param int $count OPTIONAL An SQL LIMIT count.
* #param int $offset OPTIONAL An SQL LIMIT offset.
* #return Zend_Db_Table_Rowset_Abstract The row results per the Zend_Db_Adapter fetch mode.
*/
public function fetchAll($where = null, $order = null, $count = null, $offset = null)
So you are incorrect, fetchAll() does accept an array of where clauses.
Your array should look like this (based on the definition in Zend_Db_Select)
$where = array(
'id > 0',
'enabled = ?' => 1
);

First we will look at your original code:
$wheres = array('id > 0', 'enabled' => 1);
Remember that => is an assignment operator. In your array above you start out with string automatically assigned to key 0. The next element is the number 1 assigned to the key 'enabled'. The solution proposed in answer 1 assigns the number 1 to key 'enabled = ?'.
Try this:
$all = new ORM_Model_DbTable_Asset();
$where = array();
$where[] = 'id > 0';
$where[] = $all->quote_into('enabled >= ?', 1, 'INTEGER'); // 1 could be a variable
$result = $all->fetchAll($where);

Related

Zend 2: How do I execute multiple SQL queries using Zend\Db\Adapter?

Im executing this query:
$query = "
Select * From table1 Where id = 1;
Select * From table2 Where name = 'test';
";
With \Zend\Db\Adapter\Adapter:
$stmt = $this->dbAdapter->query($query);
$rawResult = $stmt->execute();
How can I access the second result?
$rawResult->next() only returns values from first query.
Use two different queries.
/*
* First Query
*/
$query = "
Select * From table1 Where id = 1
";
$stmt = $this->dbAdapter->query($query);
$rawResult = $stmt->execute();
/*
* Second Query
*/
$query = "
Select * From table2 Where name = 'test'
";
$stmt = $this->dbAdapter->query($query);
$rawResult = $stmt->execute();
I don't believe it works the way you had it to where two queries in a row are sent this way.
To avoid code duplication you can wrap the duplicated code into a method.
$rawResult1 = $this->getResults("Select * From table1 Where id = 1");
$rawResult2 = $this->getResults("Select * From table2 Where name = 'test'");
function getResults(string $query)
{
$stmt = $this->dbAdapter->query($query);
return $stmt->execute();
}

Doctrine Datetime and where condition

I am writing a Doctrine 2.3 Query and I am facing some issues:
The SQL Query which I am reflecting was:
SELECT *
FROM `entry`
WHERE `plate` LIKE '%'
AND `recognition_datetime` BETWEEN '2013-03-13 22:20:18'
AND '2013-03-13 22:20:20';
I am getting the out put with the rows selected.
Doctrine which I am trying:
Opt 1:
$qry = $this->manager()->createQueryBuilder()
->from($this->entity, 'e')
->select('e');
$qry->where('e.plate like :plate');
$qry->setParameter('plate', $plate);
$qry->add('where', "e.datetime between '2013-03-13 22:20:18' and '2013-03-13 22:20:20'");
$qry->setMaxResults( $limit );
It out puts only the first where condition:
SELECT e FROM Myproject\Domain\result e WHERE e.plate like '%'
Opt 2:
$qry = $this->manager()->createQueryBuilder()
->from($this->entity, 'e')
->select('e');
$qry->where('e.plate like :plate');
$qry->setParameter('plate', $plate);
$qry->andWhere('e.datetime BETWEEN :monday AND :sunday')
->setParameter('monday', $fromdate->format('Y-m-d H:i:s'))
->setParameter('sunday', $todate->format('Y-m-d H:i:s'));
It prints only the second where as query. Can some one help me how to write multiple where/And/or condition?
After some Research I found few thing which solved my problems:
Query Generation:
//CREATING QUERY BUILDER
$qry = $this->manager()->createQueryBuilder()
->from('YOUR_ENTITY_HERE', 'e')
->select('e');
//LIKE
$ex1 = $qry->expr()->like('e.user', "'".$user."'");
//BETWEEN
$ex2 = $qry->expr()->between('e.datetime',"'".$datetime."'","'".$dateto."'");
//IN
$ex3 = $qry->expr()->in('e.country', $country);
//ADDING ALL EXPRESSION TO ONE INBETWEEN EXPRESSION "AND" OPERATION
$Query = $qry->expr()->andX($ex1,$ex2,$ex3);
//ADDING ALL EXPRESSION TO ONE INBETWEEN EXPRESSION "OR" OPERATION
$Query = $qry->expr()->orX($ex1,$ex2,$ex3);
//ADDING TOTAL EXPRESSIONS TO WHERE
$qry->where($Query);
//GENERATE QUERY
$qry->getQuery();
//FINAL OPERATIONS
//EXECUTE
$qry->execute();
//GET ARRAY OUT PUT
$qry->getArrayResult();
//GET DB OBJECT
$qry->getResult();
Other Methods for Providing IN Operations:
OTHER WAY TO USE IN OPERATION:
$country=array('Us','UK','IND','BE');
$exp = $this->manager()->getExpressionBuilder();
$qry = $this->manager()->createQueryBuilder()
->select('e')
->from('YOUR_ENTITY_HERE', 'e')
->add('where', $exp->in('e.country', $country));

Zend_DB subselect / subquery how to?

I have this raw sql statement which I am trying to execute through Zend_DB.
$sql = 'SELECT relocationaction.id, relocationaction.vehicle, relocationaction.start, relocationaction.end, relocationaction.return ' .
'FROM relocationaction,
(SELECT vehicle, MAX(end) AS maxend
FROM relocationaction
GROUP BY vehicle) AS co2
WHERE co2.vehicle = relocationaction.vehicle
AND(relocationaction.monitor = 1)
AND (relocationaction.return IS NULL)
AND (start <= ?)
AND relocationaction.end = co2.maxend';
I have found a possible solution using this type of notation, but it is rendered to a totally different and wrong sql statement with joins and strange table names.
$tbl = $this->getDbTable();
$select = $tbl->select()->setIntegrityCheck(false);
$subSelect = $select->from('relocationaction', array('vehicle', 'maxend' => 'MAX(relocationaction.end)'))
->group('vehicle');
$subSelectString = '(' . $subSelect->__toString() . ')';
$select ->from(
array('relocationaction'), array('id', 'date' => 'start', 'enddate' => 'end', 'return'),
array('co2' => $subSelectString)
)
->joinLeft('exhibitvehicle', 'exhibitvehicle.id = relocationaction.vehicle', array())
->where('co2.vehicle = relocationaction.vehicle')
->where('relocationaction.monitor = 1')
->where('relocationaction.return IS NULL')
->where('start <= ?', $start->get('yyyy-MM-dd'))
->where('relocationaction.end = co2.maxend');
Can anyone please give me a hint?
Thanks
Jesse
UPDATE
This is the result of the second expression (total rubbish)
SELECT `relocationaction`.`vehicle`,
MAX(relocationaction.end) AS `maxend`,
`relocationaction_2`.`id`,
`relocationaction_2`.`start` AS `date`,
`relocationaction_2`.`end` AS `enddate`,
`relocationaction_2`.`return`
FROM `relocationaction`
INNER JOIN `(
SELECT ``relocationaction``.``vehicle``,
MAX(relocationaction.end) AS ``maxend`` FROM ``relocationaction`` GROUP BY ``vehicle``)`.`relocationaction` AS `relocationaction_2`
LEFT JOIN `exhibitvehicle` ON exhibitvehicle.id = relocationaction.vehicle
WHERE (col2.vehicle = relocationaction.vehicle)
AND (relocationaction.monitor = 1)
AND (relocationaction.return IS NULL)
AND (start <= '2013-05-08')
AND (relocationaction.end = col2.maxend)
GROUP BY `vehicle`
If you use a string in from(), Zend_Db_Select will consider it to be a table name so it escapes it.
The solution is to wrap your subselect into a Zend_Db_Expr.
$tbl = $this->getDbTable();
$select = $tbl->select()->setIntegrityCheck(false);
$subSelect = $select->from('relocationaction', array('vehicle', 'maxend' => 'MAX(relocationaction.end)'))
->group('vehicle');
$subSelectString = '(' . $subSelect->__toString() . ')';
$select ->from(
array('relocationaction'), array('id', 'date' => 'start', 'enddate' => 'end', 'return'),
array('co2' => new Zend_Db_Expr($subSelectString))
)
->joinLeft('exhibitvehicle', 'exhibitvehicle.id = relocationaction.vehicle', array())
->where('co2.vehicle = relocationaction.vehicle')
->where('relocationaction.monitor = 1')
->where('relocationaction.return IS NULL')
->where('start <= ?', $start->get('yyyy-MM-dd'))
->where('relocationaction.end = co2.maxend');
Ok here we go. I tried hard to find a solution with Zend_Db_Table but failed big time. That's why I finally did it with PDO, as suggested by #user466764. Thanks for your help.
$tbl = $this->getDbTable();
$query = 'SELECT relocationaction.id,
relocationaction.vehicle,
relocationaction.start,
relocationaction.end,
relocationaction.return
FROM relocationaction
(SELECT vehicle, MAX(end) AS maxend
FROM relocationaction
GROUP BY vehicle) AS co2
WHERE co2.vehicle = relocationaction.vehicle
AND(relocationaction.monitor = 1)
AND (relocationaction.return IS NULL)
AND (start <= "' . $start->get('yyyy-MM-dd') . '")
AND relocationaction.end = co2.maxend';
$sth = $tbl->getAdapter()->prepare($query);
$sth->execute();
$entries = $sth->fetchAll();

OR clause in Zend DB update?

I'd like to do a Zend db update with an OR clause. What would be the equivalent statement to:
UPDATE mail
SET message_read = 1
WHERE id = 5
OR id = 10
When calling Zend_Db_Adapter::update(), multiple WHERE conditions will automatically be combined using AND (line 698 of Zend/Db/Adapter/Abstract.php in function _whereExpr).
You can get around this by creating your own Zend_Db_Expr which you will use as the WHERE condition and it will be left untouched.
For example:
$where[] = new Zend_Db_Expr(
$table->getAdapter()->quoteInto('id = ?', 5) . ' OR ' .
$table->getAdapter()->quoteInto('id = ?', 10)
);
// resulting expression:
// WHERE (id = 5 OR id = 10)
$table->update($data, $where);
If you had additional WHERE conditions, they would be combined with the OR condition by an AND.
Example:
$where[] = new Zend_Db_Expr(
$table->getAdapter()->quoteInto('id = ?', 5) . ' OR ' .
$table->getAdapter()->quoteInto('id = ?', 10)
);
$where[] = $table->getAdapter()->quoteInto('type = ?', 'sometype');
// resulting expression:
// WHERE (id = 5 OR id = 10) AND (type = 'sometype')
->where() will add a where clause to the query and will put an 'AND'. There is an orWhere method that exists to do that.
$select = $this->select();
$select->where('id = 5');
$select->orWhere('id = 10');
$this->fetchAll($select);

use joins in zend framework query

I want to use joins in zend. Below is my query
$select = $this->_db->select()
->from(array('evaluationcriteria' => 'procurement_tbltenderevaluationcriteria'),
array('ScoringCriteriaID','ScoringCriteriaWeight'))
->join(array('scoringcriteria' => 'procurement_tbltenderscoringcriteria'),
'scoringcriteria. TenderId=evaluationcriteria.TenderId')
->join(array('tenderapplications' => 'procurement_tbltenderapplications','tendersupplier' => 'tblsupplier'),
'tenderapplications. TenderInvitationContractorID=tendersupplier.UserID');
I have UserID in tendersupplier table. but its giving following error :-
Column not found: 1054 Unknown column 'tendersupplier.UserID' in 'on clause
I think its not the right way to include more than one tale in same array of a join.
Try code like this..
->from(array('evaluationcriteria' => 'procurement_tbltenderevaluationcriteria'),
array('ScoringCriteriaID','ScoringCriteriaWeight'))
->join(array('scoringcriteria' => 'procurement_tbltenderscoringcriteria'),
'scoringcriteria. TenderId=evaluationcriteria.TenderId')
'scoringcriteria. TenderId=evaluationcriteria.TenderId')
->join(array('tenderapplications' => 'procurement_tbltenderapplications'),
'tenderapplications.TenderInvitationContractorID=tblsupplier.UserID');
I am not sure whether you are planning to join values from tblsupplier table also.
The where condition is not written the way you did .
I dount that tblsupplier is a table then it should be in an array
This code is not tested!
$select = $this->_db->select()
->from(array('evaluationcriteria' => 'procurement_tbltenderevaluationcriteria'),
array('ScoringCriteriaID','ScoringCriteriaWeight'))
->join(array('scoringcriteria' => 'procurement_tbltenderscoringcriteria'),
'scoringcriteria. TenderId=evaluationcriteria.TenderId')
->join(array('tenderapplications' => 'procurement_tbltenderapplications'), array('tendersupplier' => 'tblsupplier'))
->where('tenderapplications. TenderInvitationContractorID=tendersupplier.UserID');
Looks like you are trying to join 2 tables in one ->join, I don't think you can do that.
join code from Zend_Db_Select()
/**
* Adds a JOIN table and columns to the query.
*
* The $name and $cols parameters follow the same logic
* as described in the from() method.
*
* #param array|string|Zend_Db_Expr $name The table name.
* #param string $cond Join on this condition.
* #param array|string $cols The columns to select from the joined table.
* #param string $schema The database name to specify, if any.
* #return Zend_Db_Select This Zend_Db_Select object.
*/
public function join($name, $cond, $cols = self::SQL_WILDCARD, $schema = null)
{
return $this->joinInner($name, $cond, $cols, $schema);
}
Here is the comment block from from()
/**
* Adds a FROM table and optional columns to the query.
*
* The first parameter $name can be a simple string, in which case the
* correlation name is generated automatically. If you want to specify
* the correlation name, the first parameter must be an associative
* array in which the key is the correlation name, and the value is
* the physical table name. For example, array('alias' => 'table').
* The correlation name is prepended to all columns fetched for this
* table.
*
* The second parameter can be a single string or Zend_Db_Expr object,
* or else an array of strings or Zend_Db_Expr objects.
*
* The first parameter can be null or an empty string, in which case
* no correlation name is generated or prepended to the columns named
* in the second parameter.
*
* #param array|string|Zend_Db_Expr $name The table name or an associative array
* relating correlation name to table name.
* #param array|string|Zend_Db_Expr $cols The columns to select from this table.
* #param string $schema The schema name to specify, if any.
* #return Zend_Db_Select This Zend_Db_Select object.
*/
Maybe try something like this instead:
$select = $this->_db->select()
//FROM table procurement_tbltenderevaluationcriteria AS evaluationcriteria, SELECT FROM
//COLUMNS ScoringCriteriaID and ScoringCriteriaWeight
->from(array('evaluationcriteria' => 'procurement_tbltenderevaluationcriteria'),
array('ScoringCriteriaID','ScoringCriteriaWeight'))
//JOIN TABLE procurement_tbltenderscoringcriteria AS scoringcriteria WHERE
//TenderId FROM TABLE scoringcriteria == TenderId FROM TABLE evaluationcriteria
->join(array('scoringcriteria' => 'procurement_tbltenderscoringcriteria'),
'scoringcriteria.TenderId=evaluationcriteria.TenderId')
//JOIN TABLE procurement_tbltenderapplications AS tenderapplications
->join(array('tenderapplications' => 'procurement_tbltenderapplications'))
//JOIN TABLE tblsupplier AS tendersupplier WHERE TenderInvitationContractorID FROM TABLE
// tenderapplications == UserID FROM TABLE tendersupplier
->join(array('tendersupplier' => 'tblsupplier'),
'tenderapplications.TenderInvitationContractorID=tendersupplier.UserID');
you may also need to alter your select() definition to allow joins:
//this will lock the tables to prevent data corruption
$this->_db->select(Zend_Db_Table::SELECT_WITHOUT_FROM_PART)->setIntegrityCheck(FALSE);
I hope I'm reading your intent correctly, this should get you closer if not all the way there. (one hint, use shorter aliases...)