web-dev-qa-db-fra.com

L'élément de menu charge tout le contenu de l'article lorsque l'ID est transmis à l'URL au lieu d'afficher l'erreur 404

J'ai un problème très étrange où j'ai un élément de menu appelé/foo qui charge l'article Article 1. Maintenant, si je fais/foo/2, je m'attendrais à ce que cela génère une page 404 car je n'ai pas d'élément de sous-menu "2" sous l'élément de menu parent/foo. Pourtant, au lieu d'afficher une page de 404 pages, le contenu de l'article 2 est en cours de chargement sous le même élément de menu.

J'ai vérifié le fichier .htaccess et il ne s'agit que du fichier fourni avec Joomla et je ne comprends pas pourquoi cela pourrait se produire. Si j'essaye de mettre n'importe quel ID d'article qui n'existe pas dans la base de données, alors il affichera le 404. N'importe quel pointeur serait génial!

6
sifu

Ahhh les joies du système de routage actuel dans Joomla. (Je pensais avoir entendu dire que quelqu'un faisait un projet Google Summer of Code pour mettre à jour le système de routage, mais je n'ai rien vu d'autre à ce sujet.)

Donc, si je comprends bien le routage, Joomla essaiera d’analyser autant de la requête uri (c.-à-d. foo/2) à un élément de menu possible. Dans votre cas, cela correspond uniquement à foo.

Ensuite, le reste des pièces est passé à la router.php fichier du composant correspondant à cet élément de menu. Dans votre cas, j'imagine qu'il s'agit du routeur com_content à l'adresse components/com_content/router.php.

Ceci appellera la fonction parse dans cette classe et transmettra les segments (qui dans ce cas seront simplement 2.

Le routeur a un code (que vous pouvez parcourir si vous le souhaitez) pour essayer d’analyser les segments de l’URI en identifiants d’article et autres. La pièce maîtresse qui vous concerne est ce qui se passe s'il n'y a qu'un seul segment:

/*
     * If there is only one segment, then it points to either an article or a category.
     * We test it first to see if it is a category.  If the id and alias match a category,
     * then we assume it is a category.  If they don't we assume it is an article
     */
    if ($count == 1)
    {
        // We check to see if an alias is given.  If not, we assume it is an article
        if (strpos($segments[0], ':') === false)
        {
            $vars['view'] = 'article';
            $vars['id'] = (int) $segments[0];

            return $vars;
        }

        list($id, $alias) = explode(':', $segments[0], 2);

        // First we check if it is a category
        $category = JCategories::getInstance('Content')->get($id);

        if ($category && $category->alias == $alias)
        {
            $vars['view'] = 'category';
            $vars['id'] = $id;

            return $vars;
        }
        else
        {
            $query = $db->getQuery(true)
                ->select($db->quoteName(array('alias', 'catid')))
                ->from($db->quoteName('#__content'))
                ->where($db->quoteName('id') . ' = ' . (int) $id);
            $db->setQuery($query);
            $article = $db->loadObject();

            if ($article)
            {
                if ($article->alias == $alias)
                {
                    $vars['view'] = 'article';
                    $vars['catid'] = (int) $article->catid;
                    $vars['id'] = (int) $id;

                    return $vars;
                }
            }
        }
    }

En gros, il vérifie s'il s'agit d'un identifiant de catégorie ou d'un identifiant d'article. Comme vous avez un article avec l'identifiant 2, il passe et nous passons donc de l'avant avec cet identifiant au lieu de ce que vous avez envoyé dans l'identifiant de menu.

C'est exactement ce que com_content a été codé pour faire, pour le meilleur ou pour le pire ...: /

2
David Fritsch