I am using zend framework 1.12. I have following query to run.
"SELECT name,(select count(*) from org_quote_template_items where org_quote_template_items.quote_template_id = org_quote_templates.`id` ) as total_line_item FROM `org_quote_templates`"
In my model file , I created it like this. following is my model file.
class default_Model_DbTable_QuoteTemplates extends Zend_Db_Table_Abstract
{
/**
* Name of the original db table
*
* #var string
*/
protected $_name = 'org_quote_templates';
public function getAllTemplate($where){
$select = $this->select();
$subquery = " (SELECT COUNT(*) FROM org_quote_template_items WHERE org_quote_template_items.quote_template_id = org_quote_templates.`id` )";
$select->from(array($this), array('org_quote_templates.*','total_line_items' => new Zend_Db_Expr($subquery)));
$select = $select->where('organization_id = ?',$where['org_id']);
$adapter = new Zend_Paginator_Adapter_DbSelect($select);
$paginator = new Zend_Paginator($adapter);
$paginator->setItemCountPerPage(
Zend_Registry::get('config')->paginator->general);
pr($adapter);
exit;
}
}
I am getting following error when I run the code.
" exception 'Zend_Db_Table_Select_Exception' with message 'Select query cannot join with another table' "
please let me know what should I do ?
There is an error in your request. You should have:
$select = $this->select ();
$subquery = "(SELECT COUNT(*) FROM dtempls WHERE order_id = orders.id)";
$select->from ($this, array (
'id',
'total_line_items' => new Zend_Db_Expr ($subquery)
));
I think you have to use setIntegrityCheck(false) for accomplishing that. Check this link
You can try this way in zend
$this->select()
->setIntegrityCheck(false)
->from(array('oqt' => 'org_quote_templates'),array('total_line_item'))
->joinLeft(array('oqti' => 'org_quote_template_items'), 'oqti.quote_template_id = oqt.id', array(count(*) as count))
Related
I'm trying to query entietes in a language, other than the system default one, my repository method looks like this,
public function findOneByMaterialnumber( $materialnumber, $sysLanguageUid ){
$query = $this->createQuery();
$query->matching($query->like('materialnumber',$materialnumber));
$query->getQuerySettings()->setIgnoreEnableFields(true);
$query->getQuerySettings()->setRespectStoragePage(false);
$query->getQuerySettings()->setLanguageUid($sysLanguageUid);
//$query->getQuerySettings()->setRespectSysLanguage(false);
//$query->getQuerySettings()->setLanguageMode('strict');
//$query->getQuerySettings()->setLanguageOverlayMode(false);
$parser = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Storage\\Typo3DbQueryParser');
$queryParts = $parser->parseQuery($query);
//\TYPO3\CMS\Core\Utility\DebugUtility::debug($queryParts, 'Query');
print_r($queryParts);
exit;
return $query->execute()->getFirst();
}
but the query this results in still incorporates the sys_language_uid in the non-strict way. The debugged query object looks like this.
[keywords] => Array
(
)
[tables] => Array
(
[tx_productfinder_domain_model_product] => tx_productfinder_domain_model_product
)
[unions] => Array
(
)
[fields] => Array
(
[tx_productfinder_domain_model_product] => tx_productfinder_domain_model_product.*
)
[where] => Array
(
[0] => tx_productfinder_domain_model_product.materialnumber LIKE :
)
[additionalWhereClause] => Array
(
[0] => (tx_productfinder_domain_model_product.sys_language_uid IN (0,-1))
)
[orderings] => Array
(
[0] => tx_productfinder_domain_model_product.ordercode ASC
[1] => tx_productfinder_domain_model_product.title ASC
[2] => tx_productfinder_domain_model_product.materialnumber ASC
)
[limit] =>
[offset] =>
[tableAliasMap] => Array
(
[tx_productfinder_domain_model_product] => tx_productfinder_domain_model_product
)
This happens regardless of the sys_language_uid i query for. What am I doing wrong?
As you can see, I've tried combinations of all sorts of QuerySettings, setRespectSysLanguage, setLanguageMode and setLanguageOverlayMode. As I understand it, I have to query strictly and without language overlay. But none of those, nor their combinations, worked as intended.
This works with TYPO3 8.7.xx
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper;
/**
* The repository for Products
*/
class ProductRepository extends \TYPO3\CMS\Extbase\Persistence\Repository
{
/*
* #param int $uid id of record
* #param int $langUid sys_language_uid of the record
* #return \ITSHofmann\ItsProductfile\Domain\Mpdell\Product
*/
public function findByUidAndLanguageUid($uid,$langUid)
{
$query = $this->createQuery();
$object = $query->matching(
$query->equals('uid', $uid)
)->execute()->getFirst();
if ($object) {
$className = get_class ($object);
$dataMapper = $this->objectManager->get(DataMapper::class);
$tableName = $dataMapper->getDataMap($className)->getTableName();
$transOrigPointerField = $GLOBALS['TCA'][$tableName]['ctrl']['transOrigPointerField'];
$languageField = $GLOBALS['TCA'][$tableName]['ctrl']['languageField'];
$connection = GeneralUtility::makeInstance(ConnectionPool::class);
$queryBuilder = $connection->getQueryBuilderForTable($tableName );
$statement = $queryBuilder->select('*')
->from($tableName )
->where(
$queryBuilder->expr()->eq(
$transOrigPointerField,$queryBuilder->createNamedParameter($object->getUid(), \PDO::PARAM_INT)),
$queryBuilder->expr()->eq(
$languageField,$queryBuilder->createNamedParameter($langUid, \PDO::PARAM_INT))
)->execute();
$objectRow = $statement ->fetch();
if ($objectRow) {
$langObject = $dataMapper->map($className,[$objectRow]);
if ($langObject ) {
return reset ($langObject );
}
}
}
return $object;
}
}
edit. The answer I posted here originally turned out not to work either. What I ended up doing instead, was to write a custom statement, execute it to return the raw data and map it, via DataMapper->map(); Refer to Christop Hofmanns answer for details.
Hi I have a problem with Zend Framework 2.
File:
/home/marketplace/htdocs/vendor/zendframework/zendframework/library/Zend/Db/Adapter/Driver/Pdo/Statement.php:240
Message:
SQLSTATE[42P01]: Undefined table: 7 ERROR: relation "users" does not exist
LINE 1: ...ELECT COUNT(1) AS "c" FROM (SELECT "users".* FROM "users") A...
^
In my model I have
public function fetchAll($paginated=false)
{
if($paginated) {
$select = new Select('users');
$select->order('id DESC');
$resultSetPrototype = new ResultSet();
$resultSetPrototype->setArrayObjectPrototype(new User());
$paginatorAdapter = new DbSelect(
$select,
$this->tableGateway->getAdapter(),
$resultSetPrototype
);
$paginator = new Paginator($paginatorAdapter);
return $paginator;
}
$resultSet = $this->tableGateway->select(function(Select $select){
$select->limit('30')->order('id DESC');
});
return $resultSet;
}
What is strange is that in locale server everything is working...
Any suggestion where to find the problem?
Thanks
UPDATE:
If I do the same query directly,
$sql = 'SELECT COUNT(1) AS "c" FROM (SELECT "users".* FROM "users") AS "original_select"';
$resultSet = $this->tableGateway->getAdapter()->query($sql);
return $resultSet;
everything is ok.
I found the problem.
The search-path of Postgresql was setted to another Schema and not to main schema "public"
Thanks to Richard!
I'm using Zend Framework.
I save users information in two tables.
I have one table for his basic information and password, and in the other table I save his e-mails.
He can login with any e-mail.
My question is how should I extend Zend_Auth_Adapter_DbTable so that I can allow this?
I prefer not to use table views.
[edit]
I found a solution. What worked for me:
class My_Auth_Adapter_DbTable extends Zend_Auth_Adapter_DbTable
{
protected function _authenticateCreateSelect()
{
// build credential expression
if (empty($this->_credentialTreatment) || (strpos($this->_credentialTreatment, '?') === false)) {
$this->_credentialTreatment = '?';
}
$credentialExpression = new Zend_Db_Expr(
'(CASE WHEN ' .
$this->_zendDb->quoteInto(
$this->_zendDb->quoteIdentifier($this->_credentialColumn, true)
. ' = ' . $this->_credentialTreatment, $this->_credential
)
. ' THEN 1 ELSE 0 END) AS '
. $this->_zendDb->quoteIdentifier(
$this->_zendDb->foldCase('zend_auth_credential_match')
)
);
// get select
//$dbSelect = clone $this->getDbSelect();
$mdl = new My_Model_Db_Table_Users();
$dbSelect = $mdl->select();
$dbSelect = $dbSelect->setIntegrityCheck(false);
$dbSelect = $dbSelect->from(array('u' => $this->_tableName), array('*', $credentialExpression));
$dbSelect = $dbSelect->joinInner(array('ue' => 'users_emails'), 'ue.id_user = u.user_id', array('user_email'));
$dbSelect = $dbSelect->where('ue.' . $this->_zendDb->quoteIdentifier($this->_identityColumn, true) . ' = ?', $this->_identity);
return $dbSelect;
}
}
I explained what did it for me in the question.
But, to repeat, easiest for me was to change Zend_Auth_Adapter_DbTable::_authenticateCreateSelect().
There are a method named Zend_Auth_Adapter_DbTable::getDbSelect returns Zend_Db_Select object.
Call it and then you can join those two tables.
Hope this help.
Regards,
Ahmed B.
Here's an alternate method.
Extend the Zend_Auth_Adapter_DbTable class.
class My_Auth_Adapter_DbTable extends Zend_Auth_Adapter_DbTable {
public function setDbSelect($select) {
$this->_dbSelect = $select;
return $this;
}
}
Create instance of your new adapter
$authAdapter = new My_Auth_Adapter_DbTable(
$this->dbTable->getAdapter()
, 'Users'
, 'Users.username'
, 'Users.password'
);
In your Application_Model_DbTable_Users class, create a method that returns the select object with the joined tables.
public function getSelectAuth() {
$select = $this
->select()
->setIntegrityCheck(false)
->from(array('SystemPeopleJoined' => $this->_name)
, array(
'id'
, 'person_id'
, 'system_role_id'
, 'created_on'
, 'expires_on'
)
)
->joinInner(
'People'
, 'People.id = SystemPeopleJoined.person_id'
, array(
'first_name' => 'first_name'
, 'last_name' => 'last_name'
, 'name' => "CONCAT_WS(' ', `People`.`first_name`, `People`.`last_name`)"
)
return $select;
}
Set the select object in your adapter
$select = $this->dbTable->getSelectAuth();
$authAdapter
->setDbSelect($select)
->setIdentity($params['username'])
->setCredential($params['password'])
->setCredentialTreatment("SHA1(?)")
;
$select->joinRight(array('i' => '(SELECT * FROM images ORDER BY image_id)'),'i.ad_id = '. $main .'.id',$imarray);
Like that doesn't work. Subquery getting inside quotes.
Like that:
RIGHT JOIN `(SELECT * FROM images ORDER BY image_id)` AS `i` ON i.ad_id = a.id
Thanks ;)
Use
$select->joinRight(
array('i' => new Zend_Db_Expr('(SELECT * FROM images ORDER BY image_id)')),
'i.ad_id = '. $main .'.id',
$imarray
);
I feel This is easier to read and navigate...
$sub = $this->select()
->setIntegrityCheck(false)
->from(array('i' => 'images'), array('*'))
->order('i.image_id');
$select = $this->select()
->setIntegrityCheck(false)
->from(array('m' => 'MAIN_TABLE'), array('*'))
->joinRight(array('i' => $sub), 'i.ad_id = m.id', array('*'));
return $this->select($select);
I'm trying to do a group by using Zend framework. Here's my code:
$table = new TableClass();
$select = $table->select();
$select->from ("table", array("date", "column1" => "sum(column1)"));
$select->group ( array ("date") );
$results = $table->fetchAll ($select);
$result = $results[0];
$date = $result->date;
$column1 = $result->column1;
TableClass extends 'Zend_Db_Table_Abstract'.
I can see the query by looking at the mysql query log. The query is well formed - column1 is named in the query and the results look correct if I run the query in mysql workbench.
I cannot access the data in 'column1' - I always get this exception:
Uncaught exception 'Zend_Db_Table_Row_Exception' with message 'Specified column "column1" is not in the row'
I can however access the date column without issue.
I tried:
accessing the columns by array index:
$result[0]
but you get an exception (can't access the columns by index).
not using a column alias:
$select->from ("table", array("date", "sum(column1)"));
$column1 = $result["sum(column1)"];
but you get an exception (no such column "sum(column1)").
throwing in a Zend_Db_Expr:
"column1" => new Zend_Db_Expr ( "sum(column1)" )
but this doesn't help.
Some other examples I have seen suggest the use of the column names without aggregate functions, ie. "column1" instead of "sum(column1)" but that doesn't seem to me to be the answer - the query doesn't have any aggregate functions in it so mysql won't know what to do with it.
Any help appreciated.
Firstly, a quick tip for working with Zend_Db_Select (and by extension Zend_Db_Table_Select), you can view the generated SQL by invoking the toString method. It is vital to verify that your code generates the correct query before working with a result set:
$select = $table->select();
$select->from ("table", array("date", "column1" => "sum(column1)"));
$select->group ( array ("date") );
$sql = (string) $select; //Retrieve SQL as a string
Or simply
die($select); //print SQL
I wrote the following test script using your example and have no problems:
class Table extends Zend_Db_Table_Abstract
{
protected $_primary = 'id';
protected $_name = 'table';
}
$db = Zend_Db::factory('Pdo_Mysql', array(
'dbname' => 'test',
'username' => 'root',
'password' => '',
'host' => 'localhost'
));
$table = new Table($db);
$select = $table->select();
$select->from ($table, array("date", "column1" => new Zend_Db_Expr("sum(column1)")));
$select->group ( array ("date") );
$sql = (string) $select;
echo $sql;
$results = $table->fetchAll ($select);
$result = $results[0];
$date = $result->date;
$column1 = $result->column1;
echo '<br>' . $date . ': ' . $column1;
Use Zend_Debug::dump($result); to inspect data inside the Zend_Db_Table_Row if necessary.
In my case the SQL generated is as follows:
SELECT `table`.`date`, sum(column1) AS `column1` FROM `table` GROUP BY `date`