Typo3 QueryBuilder as LIKE search with dynamic parameter - typo3

Using Typo3 QueryBuilder as LIKE search with dynamic parameter does not work.
If I replace the variable with a static string than I get the expected result
public function getAutocompleteData($query)
{
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_kesearch_index');
$queryBuilder->select('title')
->from('tx_kesearch_index')
->where(
$queryBuilder->expr()->like(
'title',
$queryBuilder->createNamedParameter('%' . $queryBuilder->escapeLikeWildcards($query)) // 'test' works
)
);
debug($queryBuilder->getSQL());
$data = $queryBuilder->execute();
return $data->fetchAll();
}
What makes here the difference? How should be used correctly with dynamic values?

Maybe it's because auf the missing % at the end:
$queryBuilder->createNamedParameter('%' . $queryBuilder->escapeLikeWildcards($query) . '%')

Related

How to write an extbase Repository-Method for Update in TYPO3?

I have written an update query in TYPO3, Now I need to change it to query-object repository method. How to change the code below?
public function updatePaymentDetails($uid, $txnID, $amt, $stats)
{
$itemUID = $uid;
$transID = $txnID;
$amountPaid = $amt;
$txStatus = $stats;
$tableName = 'tx_paypalpayment_domain_model_transactions AS tpp';
$whereCondition = 'tpp.uid=' . '"' . $itemUID . '"';
$setValues = ['transactionid' => $transID, 'amount' => $amountPaid, 'txnstatus' => $txStatus];
$result = $GLOBALS['TYPO3_DB']->exec_UPDATEquery($tableName, $whereCondition, $setValues);
return $result;
}
I created this much in my own idea (don't know it is correct or not), What should be the remaining portion?
public function paymentUpdate($uid, $txnID, $amt, $stats) {
$query = $this->createQuery();
$query->matching(
$query->logicalAnd(
$query->equals("transactionid", $txnID),
$query->equals("amount", $amt),
$query->equals("txnstatus", $stats)
)
);
/*--- Update Code ---*/
return $query->execute();
}
Is there any way to do that?
The TYPO3/Extbase way is to first fetch your transaction from the persistence layer then apply your changes to the domain object and then update it in your repository.
Something like below in your controller action:
$transaction = $this->transactionRepository->findByIdentifier($itemUid);
$transaction->setTransactionId($transID);
$transaction->setAmount($amountPaid);
$transaction->setStatus($txStatus);
$this->transactionRepository->update($transaction);
If you wants to do a direct update instead of first fetching the record then take a look at the \TYPO3\CMS\Core\Database\Query\QueryBuilder (Only exists in newer versions of TYPO3 - 8.7 and above). In older versions of TYPO3 you could take a look at $GLOBALS['TYPO3_DB']->exec_*.

How to create a dynamic 'WHERE' SQL clause using TYPO3 Querybuilder

How can I dynamically add extra conditions to 'WHERE' clauses in TYPO3 database queries please? The new TYPO3 Version 8 docs say how to make fixed queries, but not variable ones.
In the past, I could create a SQL statement and modify it dynamically like this:
if (condition) {
$strWhere = 'some SQL';
} else {
$strWhere = 'same SQL with extra bits';
}
$dbRes = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
"*", // SELECT ...
"tableName", // FROM ...
$strWhere , // WHERE...
etc.
I can't see how to do something like this using Querybuilder. What I want to achieve is an expression that does something like this
if (condition) {
->where($queryBuilder->expr()->eq(... ))
}
else {
->where($queryBuilder->expr()->eq(... ))
->andWhere($queryBuilder->expr()->eq(... ))
}
Any hints would be much appreciated. Thanks.
Solved. My mistake was in thinking that the various parts of a Query builder statement HAVE to come together - they don't.
So this:
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_tablename');
$queryBuilder
->select('uid', 'header', 'bodytext')
->from('tt_content')
->where(
$queryBuilder->expr()->eq('bodytext', $queryBuilder->createNamedParameter('klaus')),
$queryBuilder->expr()->eq('header', $queryBuilder->createNamedParameter('a name'))
)
->execute();
can also be split into parts, such as:
switch ($scope) {
case 'limitfields':
$queryBuilder->select('uid','header','bodytext');
break;
default:
$queryBuilder->select('*');
break;
}
$queryBuilder
->from('tt_content')
->where(
$queryBuilder->expr()->eq('bodytext', $queryBuilder->createNamedParameter('klaus')),
$queryBuilder->expr()->eq('header', $queryBuilder->createNamedParameter('a name'))
)
->execute();
$queryBuilder = GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Database\\ConnectionPool')->getQueryBuilderForTable('tx_igldapssoauth_config');
$expressionBuilder = $queryBuilder->expr();
$conditions = $expressionBuilder->andX();
$conditions->add(
$expressionBuilder->eq('somefield', 1)
);
$conditions->add(
$expressionBuilder->eq('someotherfield', 2)
);
$rows = $queryBuilder->select('*')
->from('tx_igldapssoauth_config')
->where(
$queryBuilder->expr()->eq('uid', 1)
)
->andWhere($conditions)
->execute()->fetchAll();

Writing to extConf in extbase controller

I have a litte extbase extension that changes my color settings (e.g. css, cookiebar, etc.), and I also want to change the color of the backend plugin button, in the backend sysext in my controller.
Getting the value:
$var = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['backend']);
$var["loginHighlightColor"]="#444444";
But now, how do I save the value?
When trying the following statement, it sets the value correctly but it doesn't get persisted:
$GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['backend'] = serialize($var);
Even trying to persist manually with the PersistentManager doesn't work.
Thanks to Bernd Wilke I got it:
$var = unserialize($GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['backend']);
$var["loginHighlightColor"]="#444444";
$GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['backend'] = serialize($var);
$configurationUtility = $this->objectManager->get(\TYPO3\CMS\Extensionmanager\Utility\ConfigurationUtility::class);
$newConfiguration = $configurationUtility->getCurrentConfiguration("backend");
\TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule($newConfiguration, $var);
$configurationUtility->writeConfiguration(
$configurationUtility->convertValuedToNestedConfiguration($newConfiguration),
"backend"
);
This is how it works inside my AdditionalConfiguration.php. Maybe you can adapt it:
$resourcePath = 'EXT:' . $extKey . '/Resources/Public/Images/';
$GLOBALS['TYPO3_CONF_VARS']['EXT']['extConf']['backend'] = serialize(
[
'loginLogo' => $resourcePath . 'logo.svg',
'loginHighlightColor' => '#c0c0c0',
'loginBackgroundImage' => $resourcePath . 'login-bg.svg',
]
);
you propably need to do the same than found here:
http://api.typo3.org/typo3cms/current/html/_configuration_controller_8php_source.html#l00156
as that function is protected you can't call it from your code.
there are two public functions you possibly can use:
public function saveAction(array $config, $extensionKey) (line 109)
public function saveAndCloseAction(array $config, $extensionKey) (line 131)

TYPO3: How to render translated content in extension

I am developing a TYPO3 6.0 plugin that shows the subpages of the current page as tabs. For example, on the following pages my plugin is inserted on TabRoot:
If TabRoot is requested, the plugin's ActionController looks up the database for the subpage titles and contents and passes all gathered data to a Fluid template. The page is then rendered like the following:
With JS in place I always hide/show content below based on the selection. My problem is that I want to show the translated content of the subpages based on the current language selection. How am I able to do this? I've tried it with several methods, but neither of them was flawless. These are the methods I've tried:
Using RECORDS This method is not affected by the selected language, it always returns the content in the default language:
//Get the ids of the parts of the page
$select_fields = "uid";
$from_table = "tt_content";
$where_clause = 'pid = ' . $pageId;
$res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
$select_fields,
$from_table,
$where_clause,
$groupBy='',
$orderBy='sorting',
$limit=''
);
$ids = '';
$firstIteration = true;
while ( $row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc( $res ) ) {
if (!$firstIteration) $ids .= ",";
$ids .= $row ['uid'];
$firstIteration = false;
}
$GLOBALS['TYPO3_DB']->sql_free_result( $res );
//Render the parts of the page
$conf ['tables'] = 'tt_content';
$conf ['source'] = $ids;
$conf ['dontCheckPid'] = 1;
$content = $this->cObj->cObjGetSingle ( 'RECORDS', $conf );
Using CONTENTS According to TYPO3: How to render localized tt_content in own extension, this is the way to do it, however for me this also returns the content rendered with the default language. It is not affected by a language change.
$conf = array(
'table' => 'tt_content',
'select.' => array(
'pidInList' => $pageId,
'orderBy' => 'sorting',
'languageField' => 'sys_language_uid'
)
);
$content = $this->cObj->cObjGetSingle ( 'CONTENT', $conf );
Using VHS: Fluid ViewHelpers I installed the vhs extension and tried to render the content with <v:content.render />. The result is the same as with CONTENTS; it only works with the default language.
{namespace v=Tx_Vhs_ViewHelpers}
...
<v:content.render column="0" order="'sorting'" sortDirection="'ASC'"
pageUid="{pageId}" render="1" hideUntranslated="1" />
Using my own SQL query I've tried to get the bodytext fields of the page and then render those with \TYPO3\CMS\Frontend\Plugin\AbstractPlugin::pi_RTEcssText(). This method returns the content based on the current language, however the problem is that bodytext's do not contain the complete content (images, other plugins, etc).
$select_fields = "bodytext";
$from_table = "tt_content";
$where_clause = 'pid = ' . $pageId
. ' AND sys_language_uid = ' . $GLOBALS ['TSFE']->sys_language_uid;
$res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
$select_fields,
$from_table,
$where_clause,
$groupBy='',
$orderBy='sorting',
$limit=''
);
$content = '';
while ( $row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc( $res ) ) {
$content .=
\TYPO3\CMS\Frontend\Plugin\AbstractPlugin::pi_RTEcssText( $row ['bodytext'] );
}
$GLOBALS['TYPO3_DB']->sql_free_result( $res );
What am I missing? Why isn't the content rendered with the current language in the case of the CONTENTS method?
Easiest way is to use the cObject viewhelper to render right from TypoScript.
And inside your TypoScript template provide the configuration:
lib.myContent = CONTENT
lib.myContent {
...
}
BTW, you are bypassing the TYPO3 CMS API. Please do not do so. Always use the API methods to query for data.
e.g. \TYPO3\CMS\core\Database\DatabaseConnection is always available at GLOBALS['TYPO3_DB']->. Do not use the the mysql function.
On top of that, I believe that you can archive whatever you are trying to do with pure TypoScript, without the need to program anything. Feel free to ask a new questions to get help on this.
In TYPO3 4.x you could use the following methods to load the translated record:
t3lib_pageSelect->getRecordOverlay
t3lib_pageSelect->getPageOverlay
They are also available at $GLOBALS['TSFE']->sys_page->getRecordOverlay().

OR condation in symfony find Query query

Hi I am unable to use OR condation in my following Symfony findBy query.
$searchArrayTasks = array(
"name" => new \MongoRegex('/.*'.trim($_POST['keyword']).'.*/')
);
$documents = $dm->getRepository('WorkOrganisationBundle:Tasks')->findBy($searchArrayTasks)->sort($sortArray )->limit($limit)->skip($skip);
Can any one suggest please how to use OR condation in this query.Because i want to make a search basis on different parameters Like Name OR class OR Type.
Thanks Advance
This way (certainly in your Manager) is a bad practice.
Its purpose is for really dumb request.
2 things :
-Put your code in a Repository
-And code your query in sql or dql :
public function common($qb, $limit)
{
$qb->setMaxResults($limit)
->orderBy('task.id', 'DESC');
return $qb;
}
public function findByNameClassOrType($keyword, $limit)
{
$qb = $this->createQueryBuilder('task');
$qb->select('task')
->where('task.name LIKE ?', '%'.$keyword.'%')
->orWhere('task.class LIKE ?', '%'.$keyword.'%')
->orWhere('task.type LIKE ?', '%'.$keyword.'%');
$qb = $this->common($qb, $limit);
return $qb->getQuery()->getResult();
}
Use ? symbol to be sure that Doctrine escape your strings.
EDIT (mongodb) : with Mongo use addOr($expr)
$q = $doctrineOdm->createQueryBuilder('Work\OrganisationBundle\Document\Tasks');
$q->addOr($q->expr()->field('task.name')->equals($keyword));
$q->addOr($q->expr()->field('task.type')->equals($keyword));
$result = $q->getQuery()->execute();
For more informations see https://doctrine-mongodb-odm.readthedocs.org/en/latest/reference/query-builder-api.html