As $GLOBALS['TYPO3_DB'] become obsolete, I am stuck at the following mm query.
$dbObj = $GLOBALS['TYPO3_DB']->exec_SELECT_mm_query('distinct tx_news_domain_model_news.uid',
'sys_category',
'sys_category_record_mm',
'tx_news_domain_model_news',
' AND sys_category_record_mm.uid_local IN ( '.$catUid.' ) AND tx_news_domain_model_news.pid='.$pid.' AND sys_category_record_mm.tablenames="tx_news_domain_model_news"',
'',
'',
''
);
It shows
Call to a member function exec_SELECT_mm_query() on null
Has anyone found any solution?
Thanks
Use the new QueryBuilder and join your relation.
Example (not a tested working example):
$table = 'tx_news_domain_model_news';
$joinTable = 'sys_category_record_mm';
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table);
$statement = $queryBuilder
->select('*')
->from($table)
->leftJoin(
$table,
$joinTable,
'categoryMM',
$queryBuilder->expr()->eq(
'categoryMM.uid_foreign',
$queryBuilder->quoteIdentifier('tx_news_domain_model_news.uid')
)
)
->where(
$queryBuilder->expr()->eq('categoryMM.tablenames', $table),
$queryBuilder->expr()->eq('categoryMM.fieldname', 'categories'),
$queryBuilder->expr()->eq(
'categoryMM.uid',
$queryBuilder->createNamedParameter($catUid, \PDO::PARAM_INT)
)
)
->execute();
I'm using this where an older version of news has related contents stored in an MM table.
$selectTable = 'tt_content';
$joinTable = 'tx_news_domain_model_news';
$mmTable = 'tx_news_domain_model_news_ttcontent_mm';
/** #var \TYPO3\CMS\Core\Database\Query\QueryBuilder $queryBuilder */
$queryBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Database\ConnectionPool::class)->getQueryBuilderForTable('tt_content');
$res = $queryBuilder->select('t.*')->from($selectTable, 't')
->leftJoin('t', $mmTable, 'mm',
$queryBuilder->expr()->andX(
$queryBuilder->expr()->eq('mm.uid_local', $queryBuilder->createNamedParameter($newsRecord['uid'])),
$queryBuilder->expr()->eq('mm.uid_foreign', $queryBuilder->quoteIdentifier('t.uid'))
)
)
->leftJoin('mm', $joinTable, 'n',
$queryBuilder->expr()->eq('mm.uid_local', $queryBuilder->quoteIdentifier('n.uid'))
)
->where(
$queryBuilder->expr()->gt('n.uid', $queryBuilder->createNamedParameter(0))
)->execute()->fetchAll();
Related
I would like to have the last UID of the entry. For mysql, it is "insertId()". How does that work at Extbase?
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table);
$queryBuilder
->insert($table)
->values([
'test_id' => 1,
'test2_id' => 2,
]);
$queryBuilder->execute();
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table2);
$queryBuilder
->insert($table2)
->values([
'uid_local' => ?, // uid from $table
'uid_foreign' => 1
]);
$queryBuilder->execute();
You can get the last insert id with $queryBuilder->getConnection()->lastInsertId();
So that would make it:
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table);
$queryBuilder
->insert($table)
->values([
'test_id' => 1,
'test2_id' => 2,
]);
$queryBuilder->execute();
$tableUid = $queryBuilder->getConnection()->lastInsertId();
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table2);
$queryBuilder
->insert($table2)
->values([
'uid_local' => $tableUid,
'uid_foreign' => 1
]);
$queryBuilder->execute();
I'm a bit unsure if it's available when using the QueryBuilder for inserting new records, but the migration guide in TYPO3 Docs explain how you migrate the sql_insert_id() method in the new Doctrine Database Layer
https://docs.typo3.org/typo3cms/CoreApiReference/ApiOverview/Database/Migration/Index.html#sql-insert-id
Hint:
(int)$databaseConnectionForPages->lastInsertId('pages');
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.
How to use aggerate function in zend framework
$select = $this->select()->from(dailyusages, new Zend_Db_Expr("SUM(offPeakTotal)"));
Example
$select = new Zend_Db_Select($dbadapter);
$result = $select
->from(
'table_name',
array(
'offPeakTotalSum' => 'SUM(offPeakTotal)'
)
)
->query(Zend_Db::FETCH_ASSOC)
->fetch();
var_dump($result);
I have an extbase database query like below.
$query = $this->createQuery();
$result = $query->statement("Select * FROM table1 WHERE hidden = 0 AND deleted = 0 AND (".$PublicationYears.") AND logo != '' ORDER BY uid ASC LIMIT 0, ".$iLimit." ")->execute();
return $result;
$PublicationYears = "ttra = '12' or ttra = '13' or ttra = '14'";
I converted this query as follows,
$query = $this->createQuery();
$query->getQuerySettings()->setRespectStoragePage(FALSE);
$query->matching( $query->logicalAnd(
$query->equals('deleted', 0),
$query->equals('hidden', 0)
));
$query->matching($query->logicalAnd($PublicationYears));
$query->matching($query->logicalNot(
$query->equals('logo', '')
));
$query->setOrderings(array('uid' => Tx_Extbase_Persistence_QueryInterface::ORDER_ASCENDING));
$query->setLimit((integer)$iLimit);
$Result = $query->execute();
return $Result;
But the resultant query does not contain the query part related to,
$query->matching($query->logicalAnd($PublicationYears));
I think there are also other mistakes in the above query.
Please help me to create correct query.
Thanks in advance.
first of all you dont need this
$query->matching( $query->logicalAnd(
$query->equals('deleted', 0),
$query->equals('hidden', 0)
));
disable fields are included in query from default according to setting of table in ext_tables.php
multiple matching will not work
cause your third matching
$query->matching($query->logicalNot(
$query->equals('logo', '')
));
is overwriting the matching() used before it
logicalAnd on string ? it won't work either
in your case you just need to put everything in logicalAnd do it like this
$constraints = array();
$subConstraints = array();
$subConstraints[] = $query->equals('ttra', 12);
$subConstraints[] = $query->equals('ttra', 13);
$subConstraints[] = $query->equals('ttra', 14);
$constraints[] = $query->logicalOr($subConstraints);
$constraints[] = $query->logicalNot(
$query->equals('logo', '')
));
$query->matching($query->logicalAnd($constraints));
For your PublicationYears values you have to make or query in matching like below:
I think it might work only for PublicationYears variable.
$query->matching($query->logicalAnd(
$query->logicalOr(
$query->equals('ttra', 12)
),
$query->logicalOr(
$query->equals('ttra', 13)
),
$query->logicalOr(
$query->equals('ttra', 14)
),
));
why zend_db_select does not pick up schema from config file? and how can i fix it?
config:
resources.database.adapter = "Oracle"
resources.database.params.dbname = "(DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = x.x.x.x)(PORT = 1521)) (CONNECT_DATA = (SID = xx)))"
resources.database.params.username = ''
resources.database.params.password = ''
resources.database.params.trace =
resources.database.params.schema = YYY
select:
$select->from(
array('pm' => 'tab_1'),
array(
'pm_id',
'status',
'pm_status',
'pm_tabno',
'pm_cardno',
'pm_start_dt',
'pm_endtk_dt',
'pm_signature',
'pm_servrec_no',
'pm_isdirector'
)
)
->joinLeft(
array('pa' => 'tab_2'),
'pm.pm_id = pa.pa_pm',
array(
'PRL_NAME',
'PRF_NAME',
'PRS_NAME'
)
)
->joinLeft(
array('ddpst' => 'tab_3'),
'pm.status = ddpst.dic_value',
'dic_name'
)
->joinLeft(
array('pst' => 'tab_4'),
'pm.pm_status = pst.dic_value',
'dic_sname'
)
->where(
'pa.status = 1'
);
result:
SELECT z2.*
FROM (
SELECT z1.*, ROWNUM AS "zend_db_rownum"
FROM (
SELECT pm.pm_id, pm.status, pm.pm_status, pm.pm_tabno, pm.pm_cardno, pm.pm_start_dt, pm.pm_endtk_dt, pm.pm_signature, pm.pm_servrec_no, pm.pm_isdirector, pa.PRL_NAME, pa.PRF_NAME, pa.PRS_NAME, ddpst.dic_name, pst.dic_sname FROM tab_1 pm
LEFT JOIN tab_2 pa ON pm.pm_id = pa.pa_pm
LEFT JOIN tab_3 ddpst ON pm.status = ddpst.dic_value
LEFT JOIN tab_4 pst ON pm.pm_status = pst.dic_value WHERE (pa.status = 1) ORDER BY PRL_NAME ASC
) z1
) z2
WHERE z2."zend_db_rownum" BETWEEN 1 AND 50
Schema doesn't appear to be a valid parameter accepted by Zend_Application_Resrouce_Db or Zend_Db_Adapter_Oracle. You can set the schema from your DbTable classes if you are using Zend_Db_Table_Abstract to define your DbTables.
See Example #4.
rsolved by overriding Zend_Db_Select (_join() for adding default schema) + overriding Zend_Db_Adapter (for returning own Select)