web-dev-qa-db-fra.com

Comment récupérer des valeurs uniques avant une parenthèse dans une requête de filtrage JFormFieldList?

J'ai un filtre personnalisé JHtml renseigné par une classe étendue JFormField. Il est ajouté dans la vue avec le code suivant:

JHtmlSidebar::addFilter(
    '- Select Height -',
    'filter_height',
    JHtml::_('select.options', $heightOptions, "value", "text", $this->state->get('filter.height'), true)
);

Il fonctionne comme prévu, mais pour une raison quelconque, le filtre n’affiche pas le texte par défaut (- Sélectionnez Hauteur -), mais affiche plutôt la chaîne "Sélectionnez une option" (j’ai inclus un autre filtre - codé de la même manière - dans la capture d’écran pour montrer à quoi cela devrait ressembler).

enter image description here

Après quelques problèmes, j'ai compris que je pouvais résoudre ce problème en modifiant ma requête de base de données dans la classe JFormField. Ma classe originale JFormField est la suivante:

JFormHelper::loadFieldClass('list');

class JFormFieldHeight extends JFormFieldList
{
    protected $type = 'Height';

    public function getOptions()
    {
        $options = array();

        $db     = JFactory::getDbo();
        $query  = $db->getQuery(true);

        $query->select("DISTINCT LEFT(a.description2, LOCATE('(', a.description2) - 1) AS height");
        $query->from('#__cadcam_disc AS a');
        $query->order("LEFT(a.description2, LOCATE('(', a.description2) - 1)");

        $db->setQuery($query);
        $options = $db->loadObjectList();

        if ($db->getErrorNum()) {
            JError::raiseWarning(500, $db->getErrorMsg());
        }

        return $options;
    }
}

Ce code pose le problème, mais si je supprime la fonction LOCATE de la requête, cela fonctionne correctement. De toute évidence, je dois conserver la requête initiale, ce qui n’est pas une option.

Pour information, la boîte de sélection est chargée avec les valeurs dans les deux cas, y compris la valeur par défaut, mais même en sélectionnant la valeur par défaut, la chaîne "sélectionner une option" est rétablie:

enter image description here

Des idées de ce qui se passe ici?

3
doovers

Je pense avoir trouvé le problème. Je travaillais sur une de mes propres extensions lorsque le même problème a été soulevé. Vérifiez la sortie HTML et voyez s’il existe deux options avec une valeur 0.

C'est la fonction qui a causé le problème

public function getAdminList()
{
    $db = JFactory::getDbo();
    $query  = $db->getQuery(true);

    $query->select('DISTINCT notify.admin_to_notify AS id');
    $query->from('#__babelu_exams_notification_profiles AS notify');

    $query->select('admin.name');
    $query->join('LEFT', '#__users AS admin ON admin.id = notify.admin_to_notify');

    $query->order('admin.name');

    $db->setQuery($query);
    return $db->loadObjectList();
}

Comme vous pouvez le constater, nous utilisons tous les deux le sélecteur DISTINCT, qui est probablement à l'origine du problème. Vérification de la sortie HTML, voici à quoi ressemblait la sélection

<select name="filter[admin]" id="filter_admin" class="span12 small chzn-done" onchange="this.form.submit()" style="display: none;">
   <option value="">
       Filter by Administrator
   </option>
   <option value="0" selected="selected">
       Not Assigned
   </option>
   <option value="0" selected="selected"></option>
</select>

J'ai donc légèrement modifié la dernière partie de la fonction getAdminList () pour ajouter un titre à la valeur par défaut avant de l'envoyer à ma vue.

result = $db->loadObjectList();
    if ($result[0]->id == 0)
    {
        $result[0]->name = JText::_('COM_BABELU_EXAMS_RESULTS_NONE_ASSIGNED');
    }
    else
    {
        $notAssigned = new stdClass();
        $notAssigned->name = JText::_('COM_BABELU_EXAMS_RESULTS_NONE_ASSIGNED');
        $notAssigned->id = 0;
        array_unshift($result, $notAssigned);
    }

    return $result;

Et le problème était résolu.

J'espère que ça aide. Heureux Joomla! Ng

2
Mathew Lenning

J'ai pensé que la cause du problème était liée au résultat de la requête; j'ai donc joué un peu avec elle et enlevé toutes les chaînes non numériques qui ont été renvoyées comme suit:

$query->select("DISTINCT LEFT(a.description2, LOCATE('(', a.description2) - 1) AS height");
$query->from('#__cadcam_disc AS a');
$query->where("LEFT(a.description2, LOCATE('(', a.description2) - 1) > 0");
$query->order("LEFT(a.description2, LOCATE('(', a.description2) - 1) + 0");

Et cela a rectifié la situation.

Je ne comprends toujours pas la cause du problème mais au moins, il est corrigé maintenant.

1
doovers

Vous ne mentionnez pas la version de Joomla avec laquelle vous travaillez mais:

1) Si vous voulez "- Sélectionnez Height -" Je ne suis pas sûr de savoir pourquoi vous l'enroulez dans une fonction JText::_() appelez en premier. JText::_() est utilisé pour traduire une clé à partir d'un fichier de langue, par exemple. si vous aviez ceci dans un fichier de langue anglaise dans /components/com_mycomponent/language/en-GB/en-GB.com_mycomponent.ini contenant cette ligne (avec beaucoup d'autres)

 COM_MYCOMPONENT_PLACEHOLDER_SELECT_HEIGHT="- Select Height -"

Notez que la clé à gauche du = Ne contient aucun espace et est définie par le composant. Par défaut, si la clé n'est pas trouvée, vous devriez récupérer le texte transmis à la fonction. Toutefois, en supprimant l'appel JText::_(), vous pouvez éliminer ce problème.

2) Vous aurez besoin d'ajouter le code de votre JFormField, qui est normalement l'emplacement du premier élément, afin que nous puissions voir quel est le problème.

Une print_r($heightOptions) pourrait également nous éclairer sur ce qui se passe.

Auparavant, dans un JFormFieldList étendu, nous ajoutons le premier élément à $options Créé à partir de la base de données, par exemple:

$noneSelected = new stdClass;
$noneSelected->value = '';
$noneSelected->text = '- ' . JText::_('COM_MYCOMPONENT_PLACEHOLDER_SELECT_HEIGHT') . ' -';
array_splice($options, 0, 0, array($noneSelected));
0
Craig

Pour montrer quelques améliorations/meilleures pratiques, je vais aborder la solution publiée de @ doovers.

$query = $db->getQuery(true)
    ->select("DISTINCT SUBSTRING_INDEX(description2, '(', 1) AS height");
    ->from("#__cadcam_disc");
    ->where("LOCATE('(', description2) > 0")
    ->order("height");
  • SUBSTRING_INDEX() est l'appel d'une fonction équivalent à LEFT(LOCATE())
  • Un alias de table (a) n'est pas nécessaire car une seule table est interrogée (aucune ambiguïté à résoudre).
  • Lorsque vous filtrez les valeurs qui n'ont pas de ( Dans votre clause WHERE, vous pouvez simplement rechercher une valeur positive de LOCATE() (le premier caractère serait à la position 0, mais la logique de votre tâche signifie que nous n'avons pas besoin de vérifier si > -1, ergo > 0 fera l'affaire.
  • La manipulation de chaîne dans la clause SELECT à laquelle est attribué un alias de colonne de height peut être mentionnée dans la clause ORDER BY. C'est beaucoup plus facile pour les yeux.

Voici un terrain de jeu pour quiconque souhaite mieux connaître ces fonctions.

https://www.db-fiddle.com/f/ci6ZfAQAPkbMKtak4T5kbm/

0
mickmackusa