3

What can i do if i want to something like following using extbase model query (Using Object Relational Model).

SELECT uid FROM table WHERE fIND_IN_SET('4',column_name);

OR something like

SELECT SUM(column_name) FROM table WHERE 1

Note : I don't want to use custom query using statement() method

Mihir Bhatt
  • 3,019
  • 2
  • 37
  • 41

4 Answers4

1

If you specified why you don't "want" to use a custom statement you would realize that you are mistaken. Your situation is the exact reason why statement() exists in the first place. Trying to avoid using it at almost any cost is unreasonable as the SQL abilities of extbase are far from covering all use cases. So in summary: use extbase API where logical and an obvious good choice but don't shy away from statement() where it's use is the obvious best choice just because usign extbase API "looks nicer" or it seems like with the API you're "using the framework to it's full potential".

Vlatko Šurlan
  • 405
  • 3
  • 10
0

As of now, there is neither an equivalent for the FIND_IN_SET function, nor for aggregate functions.

You will only get around this only with a custom statement or by writing your own extension of the TYPO3\CMS\Extbase\Persistence\Generic\Query class. There are, of course, security considerations which you'll have to mind with a custom statement(). However, the same security implications apply with the class extension.

To be more specific on the FIND_IN_SET function: You can't just use the like() method. If you're searching for id 1, for example, you would find it in a set that consists of any of 10,11,12,13 and so on. Furthermore can't get around that problem either because the like() method only accepts property names and doesn't let you wrap column names in functions.

andreas
  • 16,357
  • 12
  • 72
  • 76
j4k3
  • 1,167
  • 9
  • 28
-1

According to your question: I don't think there is any way to use mysql functions in extbase without using statement().

According to your example: You can try $query->like('columnName', "%{4}%").

Jay Dinse
  • 504
  • 4
  • 19
  • It will bring differ result than find_in_set, anyway it is not SQL function as well. – Mihir Bhatt Jul 22 '16 at 04:33
  • 1
    what type is ```column_name```? What are the different results? Can you give an example? – Jay Dinse Jul 22 '16 at 08:39
  • This has nothing to do with the difference, question is just about how to use SQL function inside query. I gave example of find_in_set, you can consider any SQL function. – Mihir Bhatt Jul 22 '16 at 09:07
  • See , I 've updated my question to be more precise. @jay dinse – Mihir Bhatt Jul 22 '16 at 09:10
  • 1
    I see. I think there is no way to do this without `statement()` as far as I know. The palette of query functions in extbase is very small which forced me to use `statement()` way more often than expected. Especially that there is no `join()`-function drives me nuts. – Jay Dinse Jul 22 '16 at 09:25
  • Join can be done with help of relation between two models, It comes by default. – Mihir Bhatt Jul 22 '16 at 09:28
-1

This is possible but needs a bit effort. I have done that in my news extension. The code looks like that

    $query = // your $query->execute();

    $queryParser = $this->objectManager->get(Typo3DbQueryParser::class);
    list($hash, $parameters) = $queryParser->preparseQuery($query);
    $statementParts = $queryParser->parseQuery($query);

    // Limit and offset are not cached to allow caching of pagebrowser queries.
    $statementParts['limit'] = ((int)$query->getLimit() ?: null);
    $statementParts['offset'] = ((int)$query->getOffset() ?: null);

    $tableNameForEscape = (reset($statementParts['tables']) ?: 'foo');
    foreach ($parameters as $parameterPlaceholder => $parameter) {
        if ($parameter instanceof LazyLoadingProxy) {
            $parameter = $parameter->_loadRealInstance();
        }

        if ($parameter instanceof \DateTime) {
            $parameter = $parameter->format('U');
        } elseif ($parameter instanceof DomainObjectInterface) {
            $parameter = (int)$parameter->getUid();
        } elseif (is_array($parameter)) {
            $subParameters = [];
            foreach ($parameter as $subParameter) {
                $subParameters[] = $GLOBALS['TYPO3_DB']->fullQuoteStr($subParameter, $tableNameForEscape);
            }
            $parameter = implode(',', $subParameters);
        } elseif ($parameter === null) {
            $parameter = 'NULL';
        } elseif (is_bool($parameter)) {
            return ($parameter === true ? 1 : 0);
        } else {
            $parameter = $GLOBALS['TYPO3_DB']->fullQuoteStr((string)$parameter, $tableNameForEscape);
        }

        $statementParts['where'] = str_replace($parameterPlaceholder, $parameter, $statementParts['where']);
    }

    $statementParts = [
        'selectFields' => implode(' ', $statementParts['keywords']) . ' ' . implode(',', $statementParts['fields']),
        'fromTable' => implode(' ', $statementParts['tables']) . ' ' . implode(' ', $statementParts['unions']),
        'whereClause' => (!empty($statementParts['where']) ? implode('', $statementParts['where']) : '1')
            . (!empty($statementParts['additionalWhereClause'])
                ? ' AND ' . implode(' AND ', $statementParts['additionalWhereClause'])
                : ''
            ),
        'orderBy' => (!empty($statementParts['orderings']) ? implode(', ', $statementParts['orderings']) : ''),
        'limit' => ($statementParts['offset'] ? $statementParts['offset'] . ', ' : '')
            . ($statementParts['limit'] ? $statementParts['limit'] : '')
    ];

    $sql = $GLOBALS['TYPO3_DB']->SELECTquery(
        $statementParts['selectFields'],
        $statementParts['fromTable'],
        $statementParts['whereClause'],
        '',
        $statementParts['orderBy'],
        $statementParts['limit']
    );

    return $sql;

By using the DataMapper you can map the raw result back to models if you need that as well. The code for that looks like that

$dataMapper = $objectManager->get(DataMapper::class);
$records = $dataMapper->map($className, $rows); 
Georg Ringer
  • 7,779
  • 1
  • 16
  • 34