web-dev-qa-db-ja.com

シンプルなコンポーネントでrouter.phpを使用する

私は単純なコンポーネント、基本的にはリストビューと単一のビューを持っています。ニースURLにしたいので、次のようにcom_contentからrouter.phpをコピーして貼り付け、変更します。

_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;
    }
}
_

これにはいくつか問題があるようで、それが何なのかわかりません。リストビューで生成されたリンクは問題ないようですが、次のエラーが発生します。

  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

親ビューにキーを設定していませんが、理解できる範囲で使用するキーはありません。ランダムなキー「foo」を設定すると警告は消えますが、その解決策は奇妙に見えます。

  1. _Host\{booklist-menu-alias}\{item-title}_を呼び出すと、単一のビューの代わりにリストビューが表示されます。

役立つアドバイスをいただければ幸いです。

更新

問題は私の親になんらかのIDがないため、この警告が表示されるようです。私のリストビューであるメニュー項目にルーティングできます。そこから私はジレンマを抱えています。書籍ビューを登録できるので、完全に正しいアイテムリンクが機能しなくなります。または、ブックビューのみを登録し、ブックビューにリンクを作成しないこともできます。

私はcom_contentが使用するものと同じように機能するlegacyrouter.phpをビルドしました。しかし、非推奨としてマークされているので、JComponentRouterViewで実際に機能させたいと思っています。

1
Tom

私が想像できるすべての方法を試した後、私は最終的に解決策を見つけ、この投稿で言及したバージョンにかなり近づいています。

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;
    }
}

私の理解では、Nesttableは親にとって必要でした。私はそれをすべて間違っているようです。今は魅力のように動作します。

0
Tom

この回答で問題が完全に解決されるとは思っていませんが、いくつか修正すべき点があると思います。

  1. if (!strpos($id, ':'))推奨されるプラクティス ではありません。文字列内に部分文字列が存在するかどうかを確認するには、false(_!==_または_===_のいずれか)に対して厳密なブール値チェックを実行する必要があります

    _if (strpos($id, ':') === false)
    _
  2. クエリブロックにタイプミスがあります。 $dbquery->qn()を作成しましたが、qn()はクエリオブジェクトではなく、データベースオブジェクトにチェーンする必要があります。

    _$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. 返り値配列の文字列キーを整数としてキャストしているのは奇妙だと思います。何が期待されているかはわかりませんが、奇妙な選択のようです。 (return array((int) $id => $id);) 参照するPe7erのメモに基づいて https://docs.joomla.org/J3.x:Supporting_SEF_URLs_in_your_component#A_more_complex_Example 、に変換される値(キーではなく)を返すことを意味していると思います整数。

    _return array('id' => (int)$id);
    _

    ..._$id_を整数としてキャストする手法は、文字列から非デジタル文字を十分にトリミングしますが、(関数を理解している他の開発者への)より直感的な関数呼び出しは、(- https://3v4l.org/1ljNP ):

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

    または明示的にコロンを探すより安定したバージョン:

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

    はい、これらの手法はオーバーヘッドが大きくなります(ただし、目立つ方法ではありません。同じことを実行する他の方法はありますが、すべて入力することはしません)が、スクリプトは意図することについてより情報を提供します。行う。

これは表面的なコードレビューであり、私はあなたの問題を詳細に調査する時間がないことを理解してください。

1
mickmackusa