it-swarm.com.de

Verwendung der IN-Klausel in Joomla-Abfragen

Ich versuche, Datensätze auszuwählen, in denen sich eine Spalte in einer vorgeschlagenen Liste befindet, wenn Werte die IN-Klausel verwenden. Ich habe die folgende Abfrage ausprobiert, aber das System funktioniert nicht.

    $db = JFactory::getDbo();
    $query = $db->getQuery(true); 
    $query
        ->select(array('type', 'name', 'id', 'created_by', 'amount', 'created', 'cat_id', 'status'))
        ->from($db->quoteName('#__Zoo_item'))
        ->where($db->quoteName('created_by') .' = '.$db->quote(10))
        ->where($db->quoteName('status') .' IN '.$db->quote(1,2,4))//THIS IS MY PROBLEM.
        ->group($db->quoteName('created_by'))
        ->order('id DESC')
        ->setLimit(1);
    $db->setQuery($query);
    $loan = $db->loadObject();

Die problematische Klausel ist dies

->where($db->quoteName('status') .' IN '.$db->quote(1,2,4))

Ich freue mich, wenn jemand helfen kann, danke.

3
David Addoteye

Zunächst das Problem mit

_->where($db->quoteName('status') .' IN '.$db->quote(1,2,4))
_

ist nicht nur, dass ein Syntaxfehler in der Abfrage generiert wird, sondern auch, dass $ db-> quote () _1_ als _$text_ -Parameter behandelt und _2,4_ als erwarteter bool Wert für den Parameter _$escape_. (Ich programmiere auf PhpStorm und diese Tatsache ist klargestellt)

Leider bleibt für Ihr Projekt der logische Fehler bestehen, während die von Ihnen bereitgestellte Lösung den Syntaxfehler in Ihrer Abfrage beseitigt. Tatsächlich wurden die Werte _2_ und _4_ bei all Ihren Abfragen ignoriert.

Wenn Sie $query->dump() aufrufen, sehen Sie, dass Ihre generierte Abfrage folgendermaßen aussieht:

_SELECT type,name,id,created_by,amount,created,cat_id,status
FROM `zyxwv_Zoo_item`
WHERE `created_by` = '10' AND `status` IN ('1')
GROUP BY `created_by`
ORDER BY id DESC LIMIT 1
_

Dies ist derselbe beschädigte Wert für IN wie in Ihrem ursprünglichen Code, außer dass er jetzt in Klammern steht.


Zweitens ist ein häufiges Missverständnis , dass Sie [~ # ~] brauchen [~ # ~] , um jeden möglichen Datenpunkt in Ihren Joomla-SQL-Abfragen anzugeben. Diese Codierungspraxis ist mit Vorsicht zu genießen - und kein schrecklicher Ratschlag, da einige Joomla-Entwickler sehr neu sind und keine sichere/stabile Abfrage von einer unsicheren/instabilen kennen.

Die Wahrheit ist, wenn Sie Ganzzahlen fest in ein Array codieren (oder allgemeiner gesagt, die Daten werden nicht von einer nicht vertrauenswürdigen Quelle geliefert - Benutzereingabe oder eine externe Ressource - und Sie integrieren keine Werte mit monkeywrenching-Zeichen wie Anführungszeichen) Sie haben ausreichende Kontrolle über die Stabilität der Abfrage und es gibt keine Auswirkungen auf die Sicherheit.

Für die oben angegebene Abfrage ist es VOLLSTÄNDIG stabil und sicher, sie so zu schreiben:

_$query = $db->getQuery(true)
    ->select(['type', 'name', 'id', 'created_by', 'amount', 'created', 'cat_id', 'status'])
    ->from("#__Zoo_item")
    ->where(["created_by = 10", "status IN (1,2,4)"])
    ->order("id DESC")
    ->setLimit(1);
_

Es gibt keine MySQL Reserved Keywords , keine Variablen, keine Anführungszeichen in Zeichenfolgen, und es wird davon ausgegangen, dass das Tabellenpräfix _#___ anfangs stabil ist, daher kann die Abfrage ausgeführt werden mit viel weniger Code-Bloat geschrieben werden, die Effizienz verbessern und trotzdem genauso sicher und stabil sein.

* Beachten Sie, dass die SELECT-Klausel keine AGGREGATE-Funktionen enthält. Daher habe ich die unnötige group() -Klausel entfernt.


Für andere Forscher ...

Sie können could die ganzen Zahlen wie folgt in Anführungszeichen setzen:

_->where("status IN (" . implode(',', $db->q($array)) . ")")
_

Obwohl diese Technik Ihre Abfrage vor einem Injection-Angriff schützt, werden die Eingabewerte nicht als Ganzzahlen bereinigt. Dies ist eher eine Abkürzung als eine geeignete Lösung, da dadurch völlig fehlerhafte Datentypen in die Abfrage eingehen könnten.

Wenn Sie über ein nicht vertrauenswürdiges/dynamisches Array von Zeichenfolgenwerten verfügen (von denen angenommen wird, dass es sich um Ganzzahlen handelt), können Sie Ihren eigenen benutzerdefinierten Bereinigungsprozess schreiben oder jeden Wert als Ganzzahl umwandeln.

_->where("status IN (" . implode(',', array_map('intval', $array)) . ")")  
_

oder Sie können die ArrayHelper-Methode im Kern verwenden (die effektiv das gleiche tut) ...

Dies wird im Abschnitt @ Secure_arrays_of_integers der Joomla-Dokumentation unter https://docs.joomla.org/Secure_coding_guidelines ** zum Ausdruck gebracht.

_->where($db->quoteName('status') . ' IN (' . implode(',', ArrayHelper::toInteger($array)) . ')')
_

Sie können sehen, dass der Joomla-Kern seine eigenen Abfragen mit toInteger() in Dateien wie _administrator/components/com_contact/models/contacts.php_ angemessen absichert.

* Beachten Sie, dass Sie abhängig von der Zugänglichkeit Ihres Skripts möglicherweise Folgendes deklarieren müssen:

_use \Joomla\Utilities\ArrayHelper;
_

Für alle, die einen durch Kommas getrennten String in Anführungszeichen/Escapezeichen für IN generieren möchten (da die Werte keine Ganzzahlen sind), wird die Syntax etwas länger:

sub-PHP7.4

_->where("fullname IN (" . implode(',', array_map(function($n)use($db){return $db->q($n);}, $array)) . ")")
_

PHP7.4 +

_->where("fullname IN (" . implode(',', array_map(fn($n) => $db->q($n), $array)) . ")")
_

Dieses letzte Snippet wird jede Zeichenkette korrekt in einfache Anführungszeichen setzen und die einfachen Anführungszeichen in jeder Zeichenkette umgehen (z. B. _'Mark O\'Malley'_). Hier ist ein ähnlicher Beitrag für ein bisschen mehr Lesen.

6
mickmackusa

Ich habe es gelöst Ich habe die quote () -Methode mit einer Klammer umgeben

->where($db->quoteName('status') .' IN ('.$db->quote(1,2,4).')')

Dies löste das Problem. Ich hoffe es hilft jemandem.

0
David Addoteye