web-dev-qa-db-fra.com

utiliser router.php dans un composant simple

J'ai un composant simple, essentiellement une vue de liste et une vue unique. Je veux des URL sympas donc je copie et colle le router.php de com_content comme ceci:

class BookstoreRouter extends JComponentRouterView
{
    public function __construct($app = null, $menu = null)
    {
        $books = new JComponentRouterViewconfiguration('books');
        $books->setNestable();
        $this->registerView($books);

        $book = new JComponentRouterViewconfiguration('book');
        $book->setKey('id')->setParent($books);
        $this->registerView($book);

        parent::__construct($app, $menu);

        $this->attachRule(new JComponentRouterRulesMenu($this));
        $this->attachRule(new JComponentRouterRulesStandard($this));
        $this->attachRule(new JComponentRouterRulesNomenu($this));
    }

    public function getBookSegment($id, $query)
    {
        if (!strpos($id, ':'))
        {
            $db = JFactory::getDbo();
            $dbquery = $db->getQuery(true);
            $dbquery->select($dbquery->qn('alias'))
                ->from($dbquery->qn('#__bookstore_books'))
                ->where('id = ' . $dbquery->q($id));
            $db->setQuery($dbquery);

            $id .= ':' . $db->loadResult();
        }

        return array((int) $id => $id);
    }

    public function getBookId($segment, $query)
    {
       return (int) $segment;
    }
}

Il semble y avoir quelques problèmes avec cela et je ne peux pas comprendre ce que c'est. Les liens générés dans la vue liste semblent corrects mais j'obtiens ces erreurs:

  1. Warning: array_reverse() expects parameter 1 to be array, boolean given in /var/www/public/libraries/src/Component/Router/Rules/StandardRules.php on line 279

Je ne définit pas de clé pour la vue parent mais il n'y a pas de clé à utiliser pour autant que je le comprenne. Lorsque vous définissez une clé aléatoire 'foo', l'avertissement disparaît mais cette solution semble étrange.

  1. Lorsque vous appelez Host\{booklist-menu-alias}\{item-title}, La vue de liste s'affiche au lieu de la vue unique.

Tout conseil utile est très apprécié, merci.

Mettre à jour

Le problème semble être que mes parents n'ont aucun identifiant, donc je reçois cet avertissement. Je peux router vers l'élément de menu, qui est ma vue de liste. De là, j'ai un dilemme. Je peux enregistrer la vue des livres, ce qui entraînera un dysfonctionnement des liens vers mes articles. Ou je ne peux enregistrer que la vue du livre et ne pas avoir du tout de liens dans ma vue des livres.

J'ai créé un legacyrouter.php comme celui que com_content utilise qui fonctionne très bien. Mais comme il est marqué comme obsolète, je veux vraiment le faire fonctionner avec JComponentRouterView.

1
Tom

Après avoir essayé de toutes les manières possibles, je pouvais imaginer avoir finalement trouvé la solution et j'ai été assez proche de la version que j'ai mentionnée dans cet article.

class BookstoreRouter extends JComponentRouterView
{
    public function __construct($app = null, $menu = null)
    {
        $books = new JComponentRouterViewconfiguration('books');
        $this->registerView($books);

        $book = new JComponentRouterViewconfiguration('book');
        $book->setKey('id')->setParent($books);
        $this->registerView($book);

        parent::__construct($app, $menu);

        $this->attachRule(new JComponentRouterRulesMenu($this));
        $this->attachRule(new JComponentRouterRulesStandard($this));
        $this->attachRule(new JComponentRouterRulesNomenu($this));
    }

    public function getBookSegment($id, $query)
    {
        if (strpos($query['id'], ':') === false) {
            $db = JFactory::getDbo();
            $dbquery = $db->getQuery(true);
            $dbquery->select($db->quoteName('alias'))
                ->from($db->quoteName('#__bookstore_books'))
                ->where('id = ' . $db->quote($id));
            $db->setQuery($dbquery);

            $id .= ':' . $db->loadResult();
        }

        return array((int)$id => $id);
    }

    public function getBookId($segment, $query)
    {
        return (int)$segment;
    }
}

À ma connaissance, Nestable était nécessaire pour Parent. Il semble que je me sois trompé. ça fonctionne parfaitement maintenant.

0
Tom

Je ne prétendrai pas croire que cette réponse résoudra complètement votre problème, mais je vois quelques choses à corriger.

  1. if (!strpos($id, ':')) n'est pas pratique recommandée même si elle fait ce que vous avez l'intention de faire. Pour vérifier si une sous-chaîne existe dans une chaîne, vous devez effectuer une vérification booléenne stricte sur false (!== Ou ===)

    if (strpos($id, ':') === false)
    
  2. Vous avez des fautes de frappe dans votre bloc de requête. Vous avez écrit $dbquery->qn() mais qn() doit être chaîné à votre objet de base de données, pas à votre objet de requête.

    $db = JFactory::getDbo();
    $dbquery = $db->getQuery(true)
        ->select($db->qn('alias'))
        ->from($db->qn('#__bookstore_books'))
        ->where('id = ' . $db->q($id));
    $db->setQuery($dbquery);
    
    $id .= ':' . $db->loadResult();
    
  3. Je pense qu'il est étrange que vous jetiez la clé de chaîne de votre tableau de retour sous forme d'entier. Je ne sais pas ce qui est attendu, mais cela semble être un choix étrange. (return array((int) $id => $id);Basé sur la note de Pe7er à regarder https://docs.joomla.org/J3.x:Supporting_SEF_URLs_in_your_component#A_more_complex_Example , je pense que vous voulez renvoyer une valeur (pas une clé) qui est convertie en un entier.

    return array('id' => (int)$id);
    

    ... alors que la technique de conversion du $id en entier réduira suffisamment les caractères non numériques de votre chaîne, peut-être qu'un appel de fonction plus intuitif (à d'autres développeurs qui comprennent la fonction) pourrait ressembler à ( https://3v4l.org/1ljNP ):

    return array(ltrim($id, 'a..z:') => $id);
    

    ou une version plus stable qui recherche explicitement les deux points:

    return array(explode(':', $id)[1] => $id);
    

    Oui, ces techniques auront plus de frais généraux (mais pas de manière notable; et oui, il y a d'autres façons de faire la même chose, mais je ne les taperai pas toutes), mais votre script sera plus informatif sur ce qu'il a l'intention de faire faire.

Veuillez comprendre qu'il s'agit d'une révision superficielle du code et que je n'ai pas eu le temps de rechercher votre problème en profondeur.

1
mickmackusa