it-swarm.com.de

Wie sortiere ich nach verschiedenen Spalten in derselben Ansicht?

Ich versuche, eine Glossaransicht in Drupal 8) zu erstellen. Angenommen, ich habe drei Inhaltstypen: Person, Artikel, Ereignis. Ich möchte nach Titel ASC für Artikel und Ereignis sortieren, aber sortieren nach Nachname für Person. Diese Auflistung würde also so etwas wie zeigen.

Deep Study on Dolphins (Artikel) John Doe (Person) Jam in the Backyard (Veranstaltung)

Und nicht

Deep Study Jam im Hinterhof John Doe

Ich denke, ich kann dies mit hook_views_query_alter tun, aber die einzigen Beispiele, die ich gesehen habe, sind für Drupal 7.

Ich habe so etwas

function mymodule_views_query_alter(ViewExecutable $view, QueryPluginBase $query) {
  if ($view->id() == 'glossary_everything') {
     $query->orderby[0]['field'] = "CASE WHEN node_field_data.last_name IS NULL THEN node_field_data.title ELSE node_field_data.last_name END";
  }
}

Aber ich erhalte den SQL-Fehler "Spalte nicht gefunden". Ich denke, es behandelt die gesamte CASE-Anweisung als ein großes Feld. Liegt das an der Bezeichnung ['Feld'] in meinem Array?

3
Greg

Wenn Sie in Drupal 8) eine ORDER BY ändern möchten, insbesondere um eine Formel zu verwenden, müssen Sie einen Ausdruck hinzufügen und dann order by it :

$query->addExpression('SUBSTRING(thread, 1, (LENGTH(thread) - 1))', 'order_field');
$query->orderBy('order_field', 'ASC');

In Ansichten kann es zu Verwirrung kommen, da die Version von addExpression Sql :: addField lautet. Tatsächlich können Sie mit Sql :: addOrderBy ein Feld hinzufügen und in einem Aufruf danach sortieren.

Ihr Code würde also so aussehen:

$sql = <<<SQL
CASE
     WHEN node_field_data.last_name IS NULL THEN node_field_data.title
          ELSE node_field_data.last_name
END
SQL;

$query->addField(NULL, $sql, 'last_name_else_title');
$query->orderby[] = array(
  'field' => 'last_name_else_title',
  'direction' => 'ASC',
);

Oder nur...

$query->addOrderBy(NULL, $sql, 'ASC', 'last_name_else_title');

Vielen Dank an agileadam für den Hinweis auf den Fehlerpunkt ( siehe auch ).

3
ognockocaten

Dies wird durch den Aufruf von $this->connection->escapeField($field) in \Drupal\Core\Database\Query\Select::__toString() verursacht.

\Drupal\Core\Database\Connection::escapeField löscht die Leerzeichen (CASE WHEN wird beispielsweise zu CASEWHEN), wodurch Ihre Anweisung ungültig wird.

Ich habe keine Zeit, um die Lösung zu finden, aber dort bricht sie.

2
agileadam

In this Beispiel würden Sie folgendermaßen vorgehen, um nach einem Datumsfeld und Node Veröffentlichungsdatum:

   $orderBySql = <<<ORDER_BY_SQL
CASE
  WHEN node__field_date.field_date_value IS NULL THEN node_field_data.created
  ELSE UNIX_TIMESTAMP(DATE_FORMAT(node__field_date.field_date_value, '%Y%m%d'))
END
ORDER_BY_SQL;

    // Override existing Order rules.
    $query->orderby = [];
    $query->addOrderBy(NULL, $orderBySql, 'ASC', 'diff_date_fields');
0
hugronaphor