phproutesyii2yii2-advanced-app

Yii2 routing with get parameters only ( hidden controller and action )


I saw routing where the controller and the action are hidden and url is constructed like www.domain.com/en/page-33/category-28/product-89?param=some_param. In this routing when I try to get the parameters with var_dump(Yii::$app->getRequest()->getQueryParams()) I got array like so :

array(4) { ["first_step"]=> string(7) "page-33" ["second_step"]=> string(11) "category-28" ['product']=> string(10) "product-89" ['param']=> string(10) "some_param"}

How can I do that ? I saw the rules and they are

'<first_step>/<second_step>/<product>/<test>/<test2>/<test3>/<test4>' => 'page/index',
                '<first_step>/<second_step>/<product>/<test>/<test2>/<test3>' => 'page/index',
                '<first_step>/<second_step>/<product>/<test>/<test2>' => 'page/index',
                '<first_step>/<second_step>/<product>/<test>' => 'page/index',
                '<first_step>/<second_step>/<product>' => 'page/index'
                '<first_step>//<product>' => 'page/index', 
                '<first_step>/<second_step>' => 'page/index',
                '<first_step>' => 'page/index'

I tried to make it this way at home but when I dump the Yii::$app->getRequest()->getQueryParams() it is an empty array. How this url is made like a GET parameters ( if I understood right ). I red articles about how to hide the controller and action in the url but how can I make it this way ? Thank you in advance! P.S. page-33 - first part e.g page is the title of the page stored in db and the second one e.g. 33 is the id.


Solution

  • I will give an example, and i hope you will see the pattern from it how to make it work in your specific case.

    Let's say you want to implement a simple search. There is your searchform, you submit the params for an action, to the SearchController::actionIndex(). Here you can process your parameters what was sent to it.

    public function actionIndex()
    {
        $searchForm = new SearchForm();
    
        if (Yii::$app->request->post()) {
    
            $searchForm->load(Yii::$app->request->post());
            $productType = $searchForm->productType;
            $productName = $searchForm->productName;
    
            $searchAttributes = $searchForm->attributes;
    
            unset($searchAttributes['productName']); //unset what you want to be a nicely formatted part of the url, like domain.eu/productType/productName
            unset($searchAttributes['productType']);
            foreach ($searchAttributes as $key => $value) {
                if (empty($value)) {
                    unset($searchAttributes[$key]);
                }
            }
    
            $this->redirect(
                array_merge(
                    ['/search/list', 'type' => $producType, 'name' => $productName, 
                    $searchAttributes //this variable will contain all other parameters as regualer get parameters
                )
            );
    }
    

    After this, set your url rules in a url-manager config file like this:

    return [
    'class' => 'yii\web\UrlManager',
    'enablePrettyUrl' => true,
    'showScriptName' => false,
    'enableStrictParsing' => false,
    'rules' => [
        [
            // /productType/productName
            'pattern' => '<type>/<name>',
            'route' => 'search/list',
            'encodeParams' => false,
            'defaults' => ['type' => null, 'name' => null],
        ],
         //add other rules as you need
    ]
    

    So this way if your application recognizes a rule, it will parse it and send the request to the right route.

    You will need another action in your SearchController:

    public function actionList($type = null, $name = null) {
    //do the search or anything you want to do here
        $get = Yii::$app->request->get();
        var_dump($get);
        var_dump($type); 
        var_dump($name);
     }