【发布时间】:2016-07-21 13:13:27
【问题描述】:
如果我想使用 extbase 模型查询(使用对象关系模型)进行以下操作,我该怎么办。
SELECT uid FROM table WHERE fIND_IN_SET('4',column_name);
或者类似的东西
SELECT SUM(column_name) FROM table WHERE 1
注意:我不想通过
statement()方法使用自定义查询
【问题讨论】:
如果我想使用 extbase 模型查询(使用对象关系模型)进行以下操作,我该怎么办。
SELECT uid FROM table WHERE fIND_IN_SET('4',column_name);
或者类似的东西
SELECT SUM(column_name) FROM table WHERE 1
注意:我不想通过
statement()方法使用自定义查询
【问题讨论】:
如果您指定了为什么不“想要”使用自定义语句,您会意识到您错了。您的情况是 statement() 首先存在的确切原因。几乎不惜一切代价试图避免使用它是不合理的,因为 extbase 的 SQL 能力远不能涵盖所有用例。总而言之:使用 extbase API 是合乎逻辑且明显的好选择,但不要回避 statement() 使用它的地方是明显的最佳选择,因为使用 extbase API“看起来更好”或者看起来像你的 API'重新“充分利用框架的潜力”。
【讨论】:
到目前为止,FIND_IN_SET 函数和聚合函数都没有等效项。
您只能通过自定义语句或编写自己的 TYPO3\CMS\Extbase\Persistence\Generic\Query 类扩展来解决此问题。当然,使用自定义 statement(). 时,您必须考虑一些安全注意事项。但是,同样的安全隐患也适用于类扩展。
更具体地说明FIND_IN_SET 函数:您不能只使用 like() 方法。例如,如果您正在搜索 id 1,您会在包含 10、11、12、13 等任何一个的集合中找到它。此外,也无法解决这个问题,因为like() 方法只接受属性名称,并且不允许您将列名称包装在函数中。
【讨论】:
根据您的问题:我认为没有任何方法可以在不使用statement() 的情况下在extbase 中使用mysql 函数。
根据你的例子:你可以试试$query->like('columnName', "%{4}%")。
【讨论】:
column_name 是什么类型?有什么不同的结果?能举个例子吗?
statement() 就无法做到这一点。 extbase 中的查询函数调色板非常小,这迫使我比预期更频繁地使用statement()。尤其是没有join()-function 让我抓狂。
这是可能的,但需要一些努力。我在我的新闻扩展中做到了这一点。代码是这样的
$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;
通过使用DataMapper,您还可以将原始结果映射回模型(如果需要)。代码看起来是这样的
$dataMapper = $objectManager->get(DataMapper::class);
$records = $dataMapper->map($className, $rows);
【讨论】: