Using Sort::links

So I’m using the Sort object and when calling the Sort::links method it generates the link like this


/<module>/<controller>/index?/<module>/<controller>=&sort=title

It should be


/<module>/<controller>?sort=title

Any idea why it’s generating it weirdly?

how are you generating the links use helpers provided by yii


<?= \yii\helpers\Url::to(['module/controller/action', ['sort' => 'title']) ?>

I’m using the Sort object and calling it’s link method

http://www.yiiframework.com/doc-2.0/yii-data-sort.html

ah okay by default Sort uses the current route to generate the url you can overwrite it




$sort = new Sort([

    'route' => ['/module/controller/action']

    // ...

]);


$sort->link('title');



also make sure the attribute you using to generate the link its in the attributes array

Well… I tried that, but omitting the action, and I still got the same URL (minus the action).


/<module>/<controller>?/<module>/<controller>=&sort=title

Please share your code in which you are configuring the Sort object and calling its link method, otherwise no one could be able to debug it. :)

Yeah, might be a little helpful. :lol:


$sort = new Sort([

	'attributes' => [

		'title',

		'rating',

		'category' => [

			'asc' => ['category_id' => SORT_ASC],

			'desc' => ['category_id' => SORT_DESC],

			'default' => SORT_ASC,

			'label' => 'Category'

		],

		'template',

		'status' => [

			'asc' => ['is_published' => SORT_DESC],

			'desc' => ['is_published' => SORT_ASC],

			'default' => SORT_ASC,

			'label' => 'Status'

		],

		'updated' => [

			'asc' => ['last_updated_on' => SORT_ASC],

			'desc' => ['last_updated_on' => SORT_DESC],

			'default' => SORT_ASC,

			'label' => 'Updated'

		],

	],

]);

Then in the view I’ve tried calling


<?= $sort->link('title') ?>

And that’s where it gives me the bad URL

Nothing suspicious so far. :(

Why don’t you set a break point here and see what’s happening?

[s]In the createUrl on line 411 it has


 $params[0] = $this->route === null ? Yii::$app->controller->getRoute() : $this->route;

[/s]

Edit: Actually it seems the first value is being used, not the one being injected at the 0 index.

Which is getting the route and using it as a query parameter with no value when passing it to the ‘urlManager->createUrl’ method.

Something else I noticed, when using a forward slash in front of the URL for the route property of the Sort object it doesn’t resolve it to an absolute URL. The Sort object’s createUrl takes two arguements, the second being an optional absolute argument. However, when calling the Sort::link method it only passes the sort attribute. So a route could never be absolute.

To note, I commented out line 408 in the createUrl of the Sort object




//             $params = $request instanceof Request ? $request->getQueryParams() : [];

and looks to have resolved the issue. I’m not sure what other components that use the Sort object might use this, though.

For the time being I’m going to just extend the Sort object and override that method since that solves the issue I’m having.

So the $_GET parameter has the route as an array value that the yii\web\Request object is returning.

I assume that the route on the $_GET array is suppose to happen as part of normalizing it?

Well, I couldn’t reproduce the issue.

The following code worked as expected.




    public function actionIndex()

    {

        $searchModel = new MailAddressSearch();

        $dataProvider = $searchModel->search(Yii::$app->request->queryParams);

        $sort = new Sort([

            'attributes' => [

                'account',

            ],

        ]);


        if (Yii::$app->request->isPjax) {

            return $this->renderPartial('index', [

                'searchModel' => $searchModel,

                'dataProvider' => $dataProvider,

                'sort' => $sort,

            ]);

        } else {

            return $this->render('index', [

                'searchModel' => $searchModel,

                'dataProvider' => $dataProvider,

                'sort' => $sort,

            ]);

        }

    }






    <?php Pjax::begin(); ?>

    <?= $sort->link('account') ?>

    <?= GridView::widget([

        'dataProvider' => $dataProvider,

        'columns' => [

            ['class' => 'yii\grid\SerialColumn'],


            [

                'attribute' => 'account',

            ],

            ...

        ],

    ]); ?>

    <?php Pjax::end(); ?>



<?= $sort->link(‘account’) ?> produces exactly the same link in the gridview header for ‘account’ column, e.g. “http://my.host.com/maint/mail-address/index?sort=account”.

I guess your issue may not be in Sort class, but in the way the url manager creates the url for that link.

Do you have some special rules for the current action?

I was wondering if it was the URL manager after I added pagination and noticed that it was doing the same thing.

For that route, I do not have a special route for it — to check to see if routing was an issue at all I commented out all routes and it still yielded the same results.

and I have a basic config for the URL manager


'urlManager' => [

	'enablePrettyUrl' => true,

	'showScriptName' => false,

	'rules' => require(__DIR__ . '/routes.php')

],

What rules do you have in ‘routes.php’?

And what is the current route that has the problem?

And, did you try to see what would happen when you set ‘enablePrettyUrl’ to false?

Yep. It seems to be an issue when using pretty URLs. I turned it off and the URL manager generated the URL with the route parameter set to the route without having the route as its own parameter with no value.

I’m just adding another example that I’ve encountered.

I have a URL like this:


/themes/item/<item-slug>/reviews

It uses this route


[	// theme/item/test-one

	'pattern' => '<module:themes>/<controller:item>/<slug:[\w-]+>/<action>',

	'route' => '<module>/<controller>/<action>',

],

URLs produced from Pagination end up like this:


/themes/item/<item-slug>/reviews?slug=<item-slug>&/themes/item/<item-slug>/reviews=&page=2

they are on the $_GET parameter that is returned by the Request::getQueryParams method, which is passed to the URL manager to create the URLs.

This is only an issue when using pretty URLs.

I think that there are 2 possible causes for this issue.

  1. There might be a rule that you have overlooked which will match the route and the parameters for the links for sort and/or pagination. When it is defined prior to the one that you intend to apply to the links, then something strange may happen.

I would check all the rules one by one, from top to bottom, whether it can unintentionally match the route and the parameters for the links for sort and/or pagination.

  1. There might be a bug in the url manager of the framework.

I said above with the other one that doesn’t have a special rule, it follows the normal module/controller/action structure and I also commented out all of my rules when testing the first one and it yielded the same results. So I think the issue lies with the URL manager.

Here are my routes, but I’m confident that they’re not causing the issue.

[spoiler]


[

	'<url:.+/>' => 'site/redirect', // remove trailing slashes

	[	// backwards compatibility: themes/view/123/test-one

		'pattern' => 'themes/view/<id:\d+>/<slug:.+>',

		'route' => 'themes/item/index'

	],

	[

		'pattern' => '<module:themes>/<controller:composer>',

		'route' => '<module>/<controller>'

	],

	[

		'pattern' => '<module:themes>/<action:browse>',

		'route' => '<module>/library/<action>'

	],

	[

		'pattern' => '<module:themes>/<category:[\w-]+>',

		'route' => '<module>/library/category'

	],

	[	// theme/item/test-one

		'pattern' => '<module:themes>/<controller:item>/<slug:[\w-]+>',

		'route' => '<module>/<controller>/index',

	],

	[	// theme/item/test-one

		'pattern' => '<module:themes>/<controller:item>/<slug:[\w-]+>/<action>',

		'route' => '<module>/<controller>/<action>',

	],

	[

		'pattern' => '<module:themes>/<controller:editor>/<action:preview>/<template:classic|current>',

		'route' => '<module>/<controller>/<action>'

	],

	[	// submissions/themes/test-one/edit|delete

		'pattern' => '<module:submissions>/<controller:\w+>/<slug:[\w-]+>/<action:\w+>',

		'route' => '<module>/<controller>/<action>',

	],

	[

		'pattern' => 'randimg/create',

		'route' => 'randimg/randimg/create',

	],

	[

		// list all of a user's random image collections

		'pattern' => '<controller:randimg>/<user:(?!create)[a-z0-9-_]+>',

		'route' => 'randimg/<controller>/show-all',

	],

	[

		// view a user's random image collection

		'pattern' => '<controller:randimg>/<user:[a-z0-9-_]+>/<slug:[a-z0-9-_]+>',

		'route' => 'randimg/<controller>/display',

		

	],

	[

		// random image collection actions

		'pattern' => '<controller:randimg>/<user:[a-z0-9-_]+>/<slug:[a-z0-9-_]+>/<image:.{6}>/<action:(edit|delete)-image>',

		'route' => 'randimg/<controller>/<action>',

	],

	[

		// random image collection actions

		'pattern' => '<controller:randimg>/<user:[a-z0-9-_]+>/<slug:[a-z0-9-_]+>/<action>',

		'route' => 'randimg/<controller>/<action>-set',

	],

	[

		// backwards compatibility

		'pattern' => 'rig/get/<id:\d+>',

		'route' => 'randimg/get'

	],

	[

		'pattern' => '<action:about>',

		'route' => 'site/<action>'

	],

	[

		// catch-all for passing an table row ID to a controller

		'pattern' => '<controller:\w+>/<action:\w+>/<id:\d+>',

		'route' => '<controller>/<action>'

	],

];

[/spoiler]

Would you like me to submit the bug on the Github page?

Yes, I think you should open an issue in Github, with a minimum set of code that reproduces the problem.

I just… I can’t man… So, I was about to submit the issue on Github and was looking through everything, I noticed something and decided to check one more thing.

It was the .htaccess rewrite rule causing


RewriteRule ^(.*)$ index.php?$1 [QSA,L]

Specifically the ?$1 That was a config carried over and since the rest of the site was working fine up to adding Pagination and Sort it went completely unnoticed.

[s]That said, resolving the previous issue with the path as a query string, there’s still something I see as a bug. Having a custom route, where there’s a slug that gets passed as an argument to the action, the URL manager appends that to the URL.

So a route like this


[	// /theme/item/test-1/reviews

	'pattern' => '<module:themes>/<controller:item>/<slug:[\w-]+>/<action>',

	'route' => '<module>/<controller>/<action>',

],

with this Pagination config


$pages = new Pagination([

'totalCount' => $countQuery->count(),

'route' => "/themes/item/{$theme->slug}/reviews"

]);

Has URLs generated as


/themes/item/theme-2/reviews?slug=theme-2&page=2&per-page=1

So I’ll still submit the issue on Github.[/s]

Just R.I.P. me…

Removing the route property passed to the Pagination config resolved the issue.