Zum Inhalt springen

Extbase query setOrdering mit "FIELD(tableRow, 'tableValue1', 'tableValue2') ASC

Erstellt am 19. Oktober 2015 · 2 Antworten · letzte Antwort am 22. Oktober 2015

Tags: Frage

xraysoft ·

Hallo Forum,

ich suche nun schon einige Zeit eine Möglichkeit ein MySQL ORDER BY in eine Extbase query zu bekommen.
Gleich vorneweg ich möchte hier nicht mit der query Funktion statement() arbeiten.

Die SQL-Abfrage soll dabei eigentlich folgendes machen:
SELECT ...
FROM ...
WHERE ...
ORDER BY FIELD(tableRow, 'tableValue1', 'tableValue2', 'tableValue3', ...) ASC

Und als Extbase query:
$query = $this->createQuery();
$query->matching(
$query->logicalAnd(
// Mein Where
)
);
$query->setOrderings(????);
$query->setOffset($offset);
$query->setLimit((int)$settings['pagelimit']);
$result = $query->execute();

Hat irgendjemand eine Idee wie ich das ORDER BY in setOrdering abbilden kann?

xraysoft ·

Danke aemka, Deine Antwort hat geholfen!

folgendes habe ich gemacht:
1. In der ext_localconf.php der Extension folgendes hinzufügen:

$GLOBALS['TYPO3_CONF_VARS']['SYS']['Objects']['TYPO3\\CMS\\Extbase\\Persistence\\Generic\\Storage\\Typo3DbQueryParser'] = array(
  'className' => '###VENDOR###\\###EXTENSIONNAME###\\Xclass\\Typo3DbQueryParser',
);

2. Im Ordner Classes einen Ordner Xclass anlegen.
3. Im Ordner Xclass die Datei Typo3DbQueryParser.php anlegen.

<?php
namespace VENDOR\EXTENSIONNAME\Xclass;

class Typo3DbQueryParser extends \TYPO3\CMS\Extbase\Persistence\Generic\Storage\Typo3DbQueryParser {
  /**
	 * Constants representing the direction when ordering result sets.
	 */
	const ORDER_FIELD_ASCENDING = 'ASC_FIELD';
	const ORDER_FIELD_DESCENDING = 'DESC_FIELD';
  
  /**
	 * Parses the query and returns the SQL statement parts.
	 *
	 * @param QueryInterface $query The query
	 * @return array The SQL statement parts
	 */
	public function parseQuery($query) {
		$sql = array();
		$sql['keywords'] = array();
		$sql['tables'] = array();
		$sql['unions'] = array();
		$sql['fields'] = array();
		$sql['where'] = array();
		$sql['additionalWhereClause'] = array();
		$sql['orderings'] = array();
		$sql['limit'] = ((int)$query->getLimit() ?: NULL);
		$sql['offset'] = ((int)$query->getOffset() ?: NULL);
		$source = $query->getSource();
		$this->parseSource($source, $sql);
		$this->parseConstraint($query->getConstraint(), $source, $sql);
		$this->parseOrderings($query->getOrderings(), $source, $sql);

		$tableNames = array_unique(array_keys($sql['tables'] + $sql['unions']));
		foreach ($tableNames as $tableName) {
			if (is_string($tableName) && !empty($tableName)) {
				$this->addAdditionalWhereClause($query->getQuerySettings(), $tableName, $sql);
			}
		}

		return $sql;
	}
  
  /**
	 * Transforms orderings into SQL.
	 *
	 * @param array $orderings An array of orderings (TYPO3\CMS\Extbase\Persistence\Generic\Qom\Ordering)
	 * @param TYPO3\CMS\Extbase\Persistence\Generic\Qom\SourceInterface $source The source
	 * @param array &$sql The query parts
	 * @throws \TYPO3\CMS\Extbase\Persistence\Generic\Exception\UnsupportedOrderException
	 * @return void
	 */
	protected function parseOrderings(array $orderings, \TYPO3\CMS\Extbase\Persistence\Generic\Qom\SourceInterface $source, array &$sql) {
		foreach ($orderings as $propertyName => $order) {
			switch ($order) {
				case \TYPO3\CMS\Extbase\Persistence\Generic\Qom\QueryObjectModelConstantsInterface::JCR_ORDER_ASCENDING:

				case \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_ASCENDING:
					$order = 'ASC';
          $field = false;
					break;
				case \TYPO3\CMS\Extbase\Persistence\Generic\Qom\QueryObjectModelConstantsInterface::JCR_ORDER_DESCENDING:

				case \TYPO3\CMS\Extbase\Persistence\QueryInterface::ORDER_DESCENDING:
					$order = 'DESC';
          $field = false;
					break;
          
        case Typo3DbQueryParser::ORDER_FIELD_ASCENDING:
          $order = 'ASC';
          $field = true;
          break;
          
        case Typo3DbQueryParser::ORDER_FIELD_DESCENDING:
          $order = 'DESC';
          $field = true;
          break;
           
				default:
					throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception\UnsupportedOrderException('Unsupported order encountered.', 1242816074);
			}
			$className = '';
			$tableName = '';
			if ($source instanceof TYPO3\CMS\Extbase\Persistence\Generic\Qom\SelectorInterface) {
				$className = $source->getNodeTypeName();
				$tableName = $this->dataMapper->convertClassNameToTableName($className);
				while (strpos($propertyName, '.') !== FALSE) {
					$this->addUnionStatement($className, $tableName, $propertyName, $sql);
				}
			} elseif ($source instanceof TYPO3\CMS\Extbase\Persistence\Generic\Qom\JoinInterface) {
				$tableName = $source->getLeft()->getSelectorName();
			}
      $columnName = $this->dataMapper->convertPropertyNameToColumnName($propertyName, $className);
      if($field) {
        if ($tableName !== '') {
  				$sql['orderings'][] = 'FIELD(' . $tableName . '.' . $propertyName . ') ' . $order;
  			} else {
  				$sql['orderings'][] = 'FIELD(' . $propertyName . ') ' . $order;
  			}
      } else {
  			if ($tableName !== '') {
  				$sql['orderings'][] = $tableName . '.' . $columnName . ' ' . $order;
  			} else {
  				$sql['orderings'][] = $columnName . ' ' . $order;
  			}
      }
		}
	}
}
?>

4. Nun kann man in seinen Repository folgendes setOrdering machen:

$query->setOrderings(array(
      'TABLE_ROW_NAME, \'ROW_VALUE_1\', \'ROW_VALUE_2\', \'ROW_VALUE_3\', \'ROW_VALUE_4\', \'ROW_VALUE_5\', \'ROW_VALUE_6\'' => \Netzweber\NwCitavilist\Xclass\Typo3DbQueryParser::ORDER_FIELD_ASCENDING
    ));

Bitte darauf achten das bei TABLE_ROW_NAME, der Name benutzt wird der wirklich in der Datenbank für diese Feld genutzt wird und nicht wie bei den anderen setOrdering der Name aus dem Model.