Yii2 create user friendly URL with parameters - yii2

Hi I've to create user friendly URL but when using with parameters it's not working.
Url:
Url::to(['site/index', 'id' => 1]);
url looks like :
localhost/testApplication/frontend/web/index.php/site/index?id=1
/forntend/config/main.php
'urlManager' => [
'class' => 'yii\web\UrlManager',
'enablePrettyUrl' => true,
//'showScriptName' => false,
'rules' => [
],
],
I want a output like
localhost/testApplication/frontend/web/index.php/site/index/id/1
and after that how to access id value in controller.

'rules' => [
'site/index/id/<id:\d+>' => 'site/index'
//'site/index/<id:\d+>' => 'site/index' Better solution
//'<controller>/<action>/<id:\d+>' => '<controller>/<action>' Will be applied for all controllers and actions
],
Routing Doc.
And after in your action :
public function actionIndex($id)
{
...
}

Is really strange, for me using the parameter 'id' always show errors, I needed to change the parameter to 'user_id', but in other parts of the code I could use, really don't know why, but try to rename the parameter.

Related

Yii2 Pagination + PrettyURL Cannot Find site/index

I have pagination setup in site/index, with pretty url working. But my site/index is hidden by either the rewrite engine of Apache, or by UrlManager. In any case, my index page address is simply "X.COM' and pagination wishes to redirect a page change to "X.COM/index?PAGINATIONQUERY", so it always returns a 404.
Example Pagination Request (Returns 404):
x.com/index?page=2&per-page=12
Here is my UrlManager
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
// '<alias:\w+>' => 'site/<alias>',
'<action:\w+>' => 'site/<action>',
],
],
How would I either remove the 'index' portion from pagination requests, or allow myself to see /index in Url again?
Thank you!
Edit:
This is my Index action
public function actionIndex()
{
$query = Shout::find()->orderBy(['id' => SORT_DESC]);
$countQuery = $query->count();
$pagination = new Pagination(['totalCount' => $countQuery, 'pageSize' => 12]);
$shouts = $query->offset($pagination->offset)
->limit($pagination->limit)
->all();
return $this->render('index', [
'shouts' => $shouts,
'pagination' => $pagination,
]);
}
Use Yii2 Gii for Generating Crud Modules with Inbuilt Pagination & Searching.
Yii2 Gii - https://www.yiiframework.com/doc/guide/2.0/en/start-gii
Make Sure Pjax enable when create crud with Gii.

How can I directly go to an action in the browser?

I have a custom contorller called A1Controller which has an action called actionGetdetails. How do I go to this action in the browser? I tried http://localhost/Yii2basicapp/web/a1/getdetails, but it doesn't work.
This is my setting in the web.php file
`'urlManager' => [
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => false,
'rules' => [
['class' => 'yii\rest\UrlRule', 'controller' => 'a1'],
],
],`
Yii expects camelcase actions to be rendered with dashes, so you should access it like http://localhost/Yii2basicapp/web/a1/get-details
You need to use a rest full browser add on to access the rest controller action to work as rest client for You
I use Rest Client Firefox for Firefox You can search for alternative for Your favorite browser

yii2 SluggableBehavior is applied to only emty slug field

I am using SluggableBehavior in such way
public function behaviors()
{
return [
[
'class' => SluggableBehavior::className(),
'attribute' => 'name',
'slugAttribute' => 'alias',
],
];
}
It works nice If field 'alias' in form is empty.
How to ignore this behaviors If field alias is not empty on form submitting ?
thanks in advance !
Add 'immutable'=>true in the behavour config.
The behaviour works in such way, that if the slugAttribute is not empty when immutable is on, that attribute will not be changed.
Try something like:
Configure this behavior with specific name:
return [
'slug' => [
'class' => SluggableBehavior::className(),
'attribute' => 'name',
'slugAttribute' => 'alias',
],
];
In controller load attributes from the form (before validation).
Check if alias attribute is empty.
If it is not - detach this behavior ($this->detachBehavior('slug')).
Validate model.

yii2 routing - pass parameter to route in rules

When a user accesses domain/page, I need to route them to controller/action/100.
I don't want to pass any parameter through the URL, but want to add it in url rules.
I added the code below to my config file.
'urlManager' => [
'rules' => [
'login' => 'site/login', // working
'about' => 'cms/page/10' // Not Working
'about' => 'cms/page?id=10' // Not Working
],
],
The first rule is working fine.
Can I pass the parameter for the route in url rules?
You need to use defaults and declare the rule explicitly:
'urlManager' => [
'rules' => [
'login' => 'site/login',
[
'pattern' => 'about',
'route' => 'cms/page',
'defaults' => ['id' => 10],
]
],
],
Add 'mode' => \yii\web\UrlRule::PARSING_ONLY to this rule if you want to prevent the transformation when you create a URL with the UrlManager (e.g. Url::to() uses the UrlManager and its rules and works in the opposite direction, that is Url::to(['cms/page', 'id' => 10]) will generate a link about)
Also consider to configure a redirect at your web server instead.

Displaying subdirectory name in the url in Yii2 for static pages

Iam creating static pages for a client using Yii2. I am using yii2 because the client has some other requirements to scale up the web later. I use Yii2 Basic app. The yii2 basic has default pages like about, contact etc.
The url for those pages after enabling pretty url is
www.example.com/about
etc
Now i need to create pages
"xyz.php"
under a sub directory like
"abc"
. So i need my url to be www.example.com/abc/xyz
How do i achieve this? to be informed iam a learner, I followed url rules, helpers but did not find a strong solution.
create a controller like StaticController.php and use the yii\web\ViewAction
http://www.yiiframework.com/doc-2.0/yii-web-viewaction.html
As an example:
namespace app\controllers;
use Yii;
use yii\web\Controller;
use yii\filters\AccessControl;
/**
* StaticController is only for displaying static pages.
*/
class StaticController extends Controller
{
public $defaultAction = 'page';
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'rules' => [
[
'actions' => ['page'],
'allow' => true,
'roles' => ['#'],
],
],
],
];
}
public function actions()
{
return [
'page'=>array(
'class'=>'yii\web\ViewAction',
'viewPrefix'=>null, // or set a specific directory e.g. 'static-pages' if you want to store the static pages in a subdirectory
),
];
}
}
And add this Rule to your UrlManager (where static is your controller name)
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
'<controller:static>/<view:.*>' => '<controller>',
...
]
]
Now you can store your static pages in the directory /view/static/
e.g. index.php, test.php or even in subdirectories /sub/test2.php
The urls would be like /static (or /static/index), /static/test1, /static/sub/test2
The 1st pathname is of course the controller name, but you can also change the url rule to something else or rename the controller.
config/web.php
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
'abc/<view:\S+>' => 'site/page',
]
]
I had a situation where I wanted the URL to indicate a sub page (like 'website/page/sub-page) but I didn't think it made sense to have a separate controller. (At the moment I just have one controller; SiteController.php.)
I am recreating the site structure of an existing site in a new Yii2 Basic site.
Client has a page called 'laptop-repair' in their existing site with a number of pages linked from it, e.g. 'laptop-overheating'. So the URI needed to look like 'laptop-repair/laptop-overheating'.
The solution:
In urlManager in config>web.php I add a new rule (Nb. the order of rules is important, the earlier rules are prioritised):
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
'/' => 'site/index',
[
'pattern' => 'laptop-repair/<page:.*>',
'route' => 'site/laptop-repair',
'defaults' => ['page' => 'index'],
],
...
],
],
In SiteController.php I already had an action for the page which I wanted to make into a parent page:
public function actionLaptopRepair()
{
return $this->render('laptop-repair');
}
which I replaced with:
public function actionLaptopRepair($page)
{
return $this->render("/site/laptop-repair/$page");
}
The leading slash is necessary to override the default behaviour of the Yii application, which is to look for the view in 'views>{controllerName}'. For example with render('laptop-repair'); the view file laptop-repair.php would need to be in 'views>site' since the name of the controller is SiteController, whereas render("/site/laptop-repair/$page"); corresponds to a view file ($page) in 'views>site>laptop-repair'. This allows you to organise your views in subdirectories.
I created a new folder called 'laptop-repair' in 'views>site', moved the view for the parent page (laptop-repair.php) into the new directory and renamed it index.php. I put the new sub pages' view files in that new directory ('views>site>laptop-repair'), alongside the parent view (index.php).
Everything worked except for the URL creation in my nav widget. Where the following worked fine before, the 'laptop-repair' link broke after I implemented the above:
echo Nav::widget([
'options' => ['class' => 'navbar-nav ml-auto'],
'items' => [
['label' => 'Home', 'url' => ['/site/index']],
[
'label' => 'Repair Services',
'items' => [
['label' => 'Desktop PC Repairs', 'url' => ['/site/pc-repair']],
['label' => 'Laptop Repairs', 'url' => ['site/laptop-repair']],
['label' => 'Mobile Phone Repairs', 'url' => ['/site/mobile-phone-repair']],
...
The fix was simply changing the relevant line to:
['label' => 'Laptop Repairs', 'url' => ['/laptop-repair']],
Creating a link from the parent page to a sub page looks like this:
<?= Html::a('Laptop overheating?', ['laptop-repair/laptop-overheating'], ['class' => '', 'title' => 'Laptop overheating']) ?>
To add a link to the parent page to the breadcrumbs of the sub page, I replaced:
$this->title = 'Laptop Over Heating?';
$this->params['breadcrumbs'][] = $this->title;
with:
$this->title = 'Laptop Over Heating?';
$this->params['breadcrumbs'][] = ['label' => 'Laptop repair', 'url' => ['/laptop-repair']];
$this->params['breadcrumbs'][] = $this->title;
in the view file of the sub page.