Yii2: how to build right pattern with pagination for the UrlManager? - php

I have following conditions:
1) expected request is /a1,a2,aN[/.../n1,n2,nN][?range=xxx-yyyy[&search=string]]
(square brackets contain optional parts)
2) action method signature is public function actionIndex(string $alias = '', string $range = '', string $search = ''): string
3) so I used a rule for this:
[
'pattern' => '<alias:[\\w-,\\/]+>',
'route' => 'shop/products/index',
'encodeParams' => false,
],
It works properly until I try to add pagination, LinkPager ignores a rule I wrote:
[
'pattern' => '<alias:[\\w-,\\/]+>/<page:\d+>',
'route' => 'shop/products/index',
'encodeParams' => false,
],
and displays the alias and page params as GET variables.
What is a right rule adding the page number in the end of request URI like
/a1,a2,aN/n1,n2,nN/2 and ignoring if the number is 1?
UPD: I found a reason, this is a rule I defined before:
'/shop' => 'shop/products/index', //it breaks following rules
[
'pattern' => '<alias:[\\w-,\\/]+>/<page:\d+>',
'route' => 'shop/products/index',
'encodeParams' => false,
],
[
'pattern' => '<alias:[\\w-,\\/]+>',
'route' => 'shop/products/index',
'encodeParams' => false,
],
So, how I to make all these rules work together?

Solution 1: To make another action method which works without alias argument and calls actionIndex with empty one.
Solution 2: To make same rules with different mode in special order:
[
'name' => 'This rule is first when we create a link',
'pattern' => '<alias:[\\w-,\\/]+>/<page:\d+>',
'route' => 'shop/products/index',
'encodeParams' => false,
'mode' => \yii\web\UrlRule::CREATION_ONLY,
],
[
'name' => 'This rule is first when we parse a request',
//
'pattern' => 'shop/<page:\d+>',
'route' => 'shop/products/index',
],
[
'name' => 'Used for parsing when previous rule does not match',
'pattern' => '<alias:[\\w-,\\/]+>/<page:\d+>',
'route' => 'shop/products/index',
'encodeParams' => false,
'mode' => \yii\web\UrlRule::PARSING_ONLY,
],
[
'name' => 'Same as first but when link has no page number',
'pattern' => '<alias:[\\w-,\\/]+>',
'route' => 'shop/products/index',
'encodeParams' => false,
'mode' => \yii\web\UrlRule::CREATION_ONLY,
],
[
'name' => 'First when parsing request with no page number',
'pattern' => 'shop',
'route' => 'shop/products/index',
],
[
'name' => 'Used for parsing when previous rule does not match',
'pattern' => '<alias:[\\w-,\\/]+>',
'route' => 'shop/products/index',
'encodeParams' => false,
'mode' => \yii\web\UrlRule::PARSING_ONLY,
],
If you know a better solution with one action I'll be glad to see it.

Related

Yii2 pretty urls returning 404

I am using nginx and yii2 trying to create a little sample crud rest API, and whenever I enable pretty urls I can't access my routes anmymore.
My config is as follows :
'urlManager' => [
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => false,
'rules' => [
[
'class' => 'yii\rest\UrlRule',
'controller' => 'user',
'only' => ['delete', 'create', 'update', 'get'],
'patterns' => [
'PUT users/<id:\d+>' => 'user/update',
'DELETE users/<id:\d+>' => 'user/delete',
'GET users/<id:\d+>' => 'user/get',
'POST users' => 'user/create',
]
],
[
'class' => 'yii\rest\UrlRule',
'controller' => 'campaign',
'only' => ['delete', 'create', 'update', 'get'],
'patterns' => [
'PUT campaigns/<id:\d+>' => 'campaign/update',
'DELETE campaigns/<id:\d+>' => 'campaign/delete',
'GET campaigns/<id:\d+>' => 'campaign/get',
'POST campaigns' => 'campaign/create',
]
],
],
],
Note that when enabling this, I can access gii without any issue at /gii instead of /index.php?r=gii
When disabled, my routes work fine using index parameters. Also it's yii giving me 404 and not directly nginx.
EDIT: This url works /user/get?id=1
However this one does not /users/get/1, nor /user/get/1
A POST on /users will work, but not any of the other http requests

zend framework 3 Select tag validation

I am getting the error:
The input was not found in the haystack
After form post. Please see the selection tag code lines below:
// Add "roles" field
$this->add([
'type' => 'select',
'name' => 'roles',
'attributes' => [
'multiple' => 'multiple',
'options'=>$this->role_desc,
'inarrayvalidator' => false,
'class'=>'form-control'
],
'options' => [
'label' => 'Role(s)',
],
]);
// Add input for "roles" field
$inputFilter->add([
'class' => ArrayInput::class,
'name' => 'roles',
'required' => true,
'haystack'=>$this->role_ids,
'filters' => [
['name' => 'ToInt'],
],
'validators' => [
['name'=>'GreaterThan', 'options'=>['min'=>1]],
['name'=>'InArray', 'options'=>['haystack'=>$this-
>role_ids]]
],
]);
The InArray seems to be validating well, lm just no sure what is bringing up the exception. Thank you in advance.
Actually , your issue is similar to link
To solve this, change your validators definition to:
'validators' => [
['name'=>'GreaterThan', 'options'=>['min'=>1]],
[
'name' => 'Explode',
'options' => array(
'validator' => [
'name'=>'InArray',
'options'=> [
'haystack'=>$this->role_ids
]
]
)
]
],
Unfortunately, I do not think there is a "cleaner" way to do this.
Alternately, Maybe you could use the MultiCheckbox.

How to do URL routing settings in Yii1?

I've problem with url in Yii.
when I enter URL like this,
http://localhost/yii_project/index.php/gii/default/login
it doesn't opens that page and it redirects to home page.
But when I enter url like this,
http://localhost/yii_project/index.php?r=gii/default/login
it open successfully.
I don't want to use index.php?r=. I want to display it index.php/gii/..
Change /protected/config/main.php as
'urlManager' => array(
'urlFormat' => 'path',
'showScriptName' => false,
'rules' => array(
'search/<action:\w+>/'=>'dashboard/search/<action>',
'view/<action:\w+>/'=>'dashboard/view/<action>',
),
for more Info Hide index.php in yii
This is Yii1 or Yii2 you are using ?
For Yii2 Basic App (current version), open #app/config/web.php and add the following code:
This will result in this:
http://localhost/yii_project/gii/default/login
If you wanted the index.php included also then change a line to 'showScriptName' => true,
return [
... ,
'components' => [
.... ,
// below is the new section to include:
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'enableStrictParsing' => false,
//'suffix' => '.php',
//'cache' => 'cache',
//'scriptUrl' => '',
//'baseUrl' => '/',
//'hostInfo' => 'http://www.yourhost.com.au',
//'routeParam' => 'r',
'ruleConfig' => [
'class' => 'yii\web\UrlRule'
],
'rules' => array(
[
'pattern' => 'gii',
'route' => 'gii',
'suffix' => '',
],
[
'pattern' => '/<controller:\w+>/<action:\w+>',
'route' => 'gii/<controller>/<action>',
'suffix' => '',
],
'<controller:\w+>/<id:\d+>' => '<controller>/view',
'<controller:\w+>/<action:\w+>/<id:\d+>' => '<controller>/<action>',
'<controller:\w+>/<action:\w+>' => '<controller>/<action>',
),
],
... ,
],
];

Yii2 stripping ending slash in Url::to() route when using params

I'm using Yii2 and have been using the Url::to method without any issue. Now I just tried it with params for the first time and it strips the ending slash from my route.
So normally, say I would do this:
Url::to('/my/route/', true);
// http://www.example.com/my/route/
But if I want to pass params, such as:
Url::to('['/my/route/', 'id' => 123, 'name' => 'larry']', true);
// http://www.example.com/my/route?id=123&name=larry
Is there any way to stop it doing this, if not, do I have any other options to get what I want?
My UrlManager rule:
'rules' => [
[
'pattern' => 'foo/<name:[0-9a-zA-Z\-]+>.<some_id:\d+>',
'route' => 'foo/index',
'suffix' => '/',
],
//.........
],
1) You can achieve that by adding suffix to corresponding url rule containing that route:
'components' => [
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
[
'pattern' => 'my/route',
'route' => 'my/route',
'suffix' => '/',
],
],
],
],
2) Globally it's available through urlManager property with the same name suffix.
'components' => [
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'suffix' => '/',
],
],
3) Alternative way of setting through component:
Yii::$app->urlManager->suffix = '/';
This one works for specific routes too, just add this line before calling Url::to();

ZF2 optional route constraints in child routes

I'm having an issue with an optional constraint in a route that is non-optional in it's children. My routing structure is as follows:
'profile' => [
'type' => 'segment',
'options' => [
'route' => '/profile[/:id]',
'constraints' => ['id' => '[0-9]*'],
'defaults' => [
'controller' => 'User\Controller\User',
'action' => 'profile'
]
],
'may_terminate' => true,
'child_routes' => [
'sessions' => [
'type' => 'literal',
'options' => [
'route' => '/sessions',
'defaults' => ['action' => 'sessions']
]
]
]
]
Which to my mind should give me the following routes:
/profile - works
/profile/123 - works
/profile/sessions - doesn't work
/profile/123/sessions - works
When I use route 3 in the URL view helper I get the following error:
$this->url('profile/sessions');
Zend\Mvc\Router\Exception\InvalidArgumentException: Missing parameter "id"
I originally had [0-9]+ as my constraint but making it optional (*) doesn't seem to have helped. Has anyone experienced this case before?
Add it to your parent route.
'profile' => [
'type' => 'segment',
'options' => [ // ↓
'route' => '/profile[/:id][/:action]',
'constraints' => [ 'id' => '[0-9]*', 'action' => '[a-zA-Z][a-zA-Z0-9_-]*' ],
'defaults' => [
'controller' => 'User\Controller\User',
'action' => 'profile',
],
],
]
This will make it optional to have id and/or action.
At least in theory it should make all your listed routes possible, there have been some issues with this.
I had the same issue once, the only solution I found was to create a separate route (in your case for /profile/sessions) as the optional parameter for the base route, seems to become obligatory when accessing a child route.

Categories