Pretty URL in Yii2 LinkPager with custom params - yii2

I need LinkPager to create page URL like /site/page/1/job/2/order-price/3/order-exp/4/.
The route works fine with the URL manager, but LinkPager ignores this route and creates URL with ?foo=bar parameters.
$rules = [
'site/page/<page:\d+>/job/<job_id:\d+>/order-price/<min_price:\d+>/order-exp/<experience:\d+>/' => 'site/index'
];
'components' => [
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'suffix' => '/',
'rules' => $rules,
],
]
$pagination = [
'pageSize' => 1,
'forcePageParam' => true,
'pageSizeParam' => false,
'params' => [
'page' => $this->page,
'job' => $this->job_id,
'order-price' => $this->min_price,
'order-exp' => $this->experience
],
];

You're using incorrect parameters names. If your pattern is site/page/<page:\d+>/job/<job_id:\d+>/order-price/<min_price:\d+>/order-exp/<experience:\d+>/ then parameter names are:
page,
job_id,
min_price,
experience.
You should either change your rule to:
site/page/<page:\d+>/job/<job:\d+>/order-price/<order-price:\d+>/order-exp/<order-exp:\d+>/
Or adjust param names in pagination config:
[
'pageSize' => 1,
'forcePageParam' => true,
'pageSizeParam' => false,
'params' => [
'page' => $this->page,
'job_id' => $this->job_id,
'min_price' => $this->min_price,
'experience' => $this->experience,
],
];

Related

yii2, how to change structure from controller/view?id= to controller/view/username

how can i change structure URL from
http://localhost:8888/traitor/?id=24
to
http://localhost:8888/traitor/JohnRichmond (FirstName + LastName)
configure the urlManager component in the application configuration like the following: web.php
[
'components' => [
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'enableStrictParsing' => false,
'rules' => [
'traitor/<name:[A-Za-z]+>' => 'traitor/action',
// ...
],
],
],
]
URL from:
http://localhost:8888/traitor/?name=JohnRichmond
To:
http://localhost:8888/traitor/JohnRichmond
You must configure as above.
Then, if you need queryStrings(FirstName & LastName), separate them with php. Example:
$str= 'JohnRichmond';
$array = preg_split('/(?=[A-Z])/', $str);
In my opinion the following is better:
URL from:
http://localhost:8888/traitor/?first=John&last=Richmond
To:
http://localhost:8888/traitor/John/Richmond
'rules' => [
'traitor/<first:[A-Za-z]+>/<last:[A-Za-z]+>' => 'traitor/action',
// 'traitor/<first:\w+>/<last:\w+>' => 'traitor/action', // \w+: [a-zA-Z0-9_]
],
check:
Url::toRoute(['traitor', 'first' => 'John', 'last' => 'Richmond'])
Good luck.

RBAC Routes add default route of module to all the routes of project?

If I add this configuration of the cms module to the config file
'cms' => [
'class' => 'yii2mod\cms\Module',
'controllerNamespace' => 'backend\controllers',
'defaultRoute' => '',
'froalaEditorOptions' => [
'clientOptions' => [
'heightMin' => 300,
'theme' => 'dark',
'imageUploadURL' => 'upload-image',
'imageManagerDeleteURL' => 'delete-image',
'imageManagerDeleteMethod' => 'POST',
'imageManagerLoadURL' => 'images'
],
'excludedPlugins' => [
'file',
'emoticons'
]
],
'enableMarkdown' => false
]
It adds the default route of this module to all the routes like this
/cms/site/login /cms/site/index /cms/site/error. Why this is happening and how i can remove this?
If you want to remove the /cms module prefix by default, you can add a global route to backend/config/main.php(If you use advanced templates): '<controller:[\w-]+>/<action:[\w-]+>' =>'cms/<controller>/<action>'.
for example:
// backend/config/main.php
return [
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
'<controller:[\w-]+>/<action:[\w-]+>' =>'cms/<controller>/<action>'
],
],
];
Access in your bowser: www.xxx.com/site/index, it is forwarded to: /cms/site/index

ZF3 zend-mvc generic route for many controllers in one module not working

I'm in ZF3, using the zend-mvc-skeleton and trying to configure a generic route that will match as many URLs as possible as I want to be able to create new controllers (including action methods of course), and have them immediately available.
The common approach described in the documentation is to write a route that matches the controller and action (same with ZF2).
Here is my module.config.php
namespace Application;
use Zend\Router\Http\Literal;
use Zend\Router\Http\Segment;
use Zend\ServiceManager\Factory\InvokableFactory;
return [
'router' => [
'routes' => [
'home' => [
'type' => Literal::class,
'options' => [
'route' => '/',
'defaults' => [
'controller' => Controller\IndexController::class,
'action' => 'index',
],
],
],
'default' => [
'type' => Segment::class,
'options' => [
'route' => '/application[/:controller[/:action]]',
'defaults' => [
'controller' => Controller\IndexController::class,
'action' => 'index',
],
'constraints' => [
'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
],
],
],
],
],
'controllers' => [/* ... */],
'view_manager' => [/* ... */],
],
It works like a charm for http://localhost/ and http://localhost/application calling the indexAction() function of the IndexController class inside the /module/Application/src/IndexController.php file.
However, it's not working when I try to get the fooAction() function in the same Controller (i.e. IndexController). It's not resolving correctly http://localhost/application/foo. and I get the following error:
A 404 error occurred
Page not found.
The requested controller could not be mapped to an existing controller class.
Controller:
foo (resolves to invalid controller class or alias: foo)
No Exception available
Same error if I try http://localhost/bar/foo to get the fooAction() in the barController.
Do you have any idea of what's wrong with this? Any help will be appreciated. Many thanks.
The route http://localhost/application/foo won't resolve to fooAction() in the index controller, since /foo in the URL will match the controller not the action. With that route setup you would need to visit http://localhost/application/index/foo.
To get it working you'll also need to make sure you have aliased your controller in the config, e.g. assuming you have:
'controllers' => [
'invokables' => [
'Application\Controller\Index' => \Application\Controller\IndexController::class
]
],
Then alias the controller so it matches the route parameter:
'controllers' => [
'invokables' => [
'Application\Controller\Index' => \Application\Controller\IndexController::class
],
'aliases' => [
'index' => 'Application\Controller\Index'
]
],
You'll need to add aliases that match the route parameter for each controller that isn't registered using the string you want for the route, e.g. a controller Namespace\Controller\BarController should be aliased to bar, etc.
I came here with similar problem. I have created two controllers in
"Application" module, and two in new module "Account" with the same name.
Application/Controller/IndexController
Application/Controller/OverviewController
Account/Controller/IndexController
Account/Controller/OverviewController
here are my modules.config.php
module/Account/config/module.config.php
return [
'router' => [
'routes' => [
'Account-account' => [
'type' => Segment::class,
'options' => [
'route' => '/account[/][:controller[/][:action][/]]',
'defaults' => [
'__NAMESPACE__' => 'Account\Controller',
'controller' => Account\Controller\IndexController::class,
'action' => 'index',
'locale' => 'en_us'
],
],
'may_terminate' => true,
'child_routes' => [
'wildcard' => [
'type' => 'Wildcard'
],
],
],
],
],
'controllers' => [
'factories' => [
Controller\IndexController::class => AccountControllerFactory::class,
Controller\OverviewController::class => AccountControllerFactory::class,
],
'aliases' => [
'index' => IndexController::class,
'overview' => OverviewController::class
]
],
and my
module/Application/config/module.config.php
return [
'router' => [
'routes' => [
'home' => [
'type' => Literal::class,
'options' => [
'route' => '/',
'defaults' => [
'controller' => Controller\IndexController::class,
'action' => 'index',
],
],
],
'Application-application' => [
'type' => Segment::class,
'options' => [
'route' => '/application[/][:controller[/][:action][/]]',
'defaults' => [
'__NAMESPACE__' => 'Application\Controller',
'controller' => Application\Controller\IndexController::class,
'action' => 'index',
'locale' => 'en_US'
],
],
'may_terminate' => true,
'child_routes' => [
'wildcard' => [
'type' => 'Wildcard'
],
],
],
],
],
'controllers' => [
'factories' => [
Controller\IndexController::class => IndexControllerFactory::class,
Controller\OverviewController::class => IndexControllerFactory::class,
],
'aliases' => [
'index' => IndexController::class,
'overview' => OverviewController::class,
]
],
With this configuration if aliases sections are commented there is a error message which says that there is invalid controller or alias (index/overview).
If there are aliases
route: "application/overview/index" goes into Account module.

Get Parameters Not returning correctly when using desired urlformat

I am having a bit of trouble with get params in Yii2. I have code like the following:
Url::to(['support/about', 'id' => 100]);
And this returns the below:
/support/about.php?id=100
Which is exactly what I was after. But when I then try to reverse engineer this by entering that into the address bar and trying to get the value of id using the below:
echo Yii::$app->request->getQueryParam('id');
echo Yii::$app->request->get('id');
echo $_GET['id'];
I get nothing at all.
I do however get the correct value when I use:
/support/about/100.php
My url manager is like below:
'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' => '',
'route' => 'site/index',
'suffix' => '',
],
[
'pattern' => '<action:\w+>',
'route' => 'site/<action>',
'suffix' => '.php',
],
[
'pattern' => '<controller:support>',
'route' => '<controller>/index',
'suffix' => '/',
],
[
'pattern' => '<controller:support>/<action:\w+>',
'route' => '<controller>/<action>',
'suffix' => '.php',
],
[
'pattern' => '<module:\w+>/<action:\w+>',
'route' => '<module>/default/<action>',
'suffix' => '.html',
],
[
'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>',
),
],
Let's narrow down question a bit.
Since you have issue with particular URL we can remove stuff that doesn't matter for the case from URL manager config:
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
[
'pattern' => '<controller:support>',
'route' => '<controller>/index',
'suffix' => '/',
],
[
'pattern' => '<controller:support>/<action:\w+>',
'route' => '<controller>/<action>',
'suffix' => '.php',
],
],
],
I've removed values that are the same by default, rules that never apply and global prefix since you're setting it per
rule anyway.
Now test controller:
<?php
namespace app\controllers;
use yii\web\Controller;
class SupportController extends Controller
{
public function actionIndex()
{
return 'Hello, I am index.';
}
public function actionAbout()
{
echo \yii\helpers\Html::a(\yii\helpers\Url::to(['support/about', 'id' => 10]), ['support/about', 'id' => 10]);
echo '<br>';
echo \yii\helpers\VarDumper::dump(\Yii::$app->request->get(), 10, true);
}
}
Make sure that you webserver rewrite rules are correct for .php that aren't index.php. To verify that you may
change all suffixes to .html. I did since my server is configured to serve .php directly.
When following http://example.com/support/about.html?id=10 I'm getting the following:
/support/about.html?id=10
[
'id' => '10'
]
That means Yii works fine and the problem is about webserver config.

Yii2 kartik typeahead - get number of suggestions

I'm using kartik's typeahead widget for Yii2 in a view:
echo \kartik\typeahead\Typeahead::widget([
'name' => 'serial_product',
'options' => [
'placeholder' => 'Filter as you type ...',
'autofocus' => "autofocus"
],
'scrollable' => TRUE,
'pluginOptions' => [
'highlight' => TRUE,
'minLength' => 3
],
'dataset' => [
[
'remote' => Url::to(['transfers/ajaxgetinventoryitemsnew']) . '?search=%QUERY',
'limit' => 10
]
],
'pluginEvents' => [
"typeahead:selected" => "function(obj, item) { add_item(item.id); return false;}",
],
]);
How can i get the number of loaded suggestions after the remote dataset is retrieved to execute a javascript function like:
displaynumber(NUMBEROFSUGGESTIONS);
After checking through the source of kartiks widget i came up with the following solution:
echo \kartik\typeahead\Typeahead::widget([
'name' => 'serial_product',
'options' => [
'placeholder' => 'Filter as you type ...',
'autofocus' => "autofocus",
'id' => 'serial_product'
],
'scrollable' => TRUE,
'pluginOptions' => [
'highlight' => TRUE,
'minLength' => 3
],
'dataset' => [
[
'remote' => [
'url' => Url::to(['transfers/ajaxgetinventoryitemsnew']) . '?search=%QUERY',
'ajax' => ['complete' => new JsExpression("function(response)
{
jQuery('#serial_product').removeClass('loading');
checkresult(response.responseText);
}")]
],
'limit' => 10
]
],
'pluginEvents' => [
"typeahead:selected" => "function(obj, item) { checkresult2(item); return false;}",
],
]);
where response.responseText is containing the response from server (json).
function checkresult(response) {
var arr = $.parseJSON(response);
console.log(arr.length);
}
With this function i can get then count of suggestions delivered from server.