Yii2 URL manager doesn't parse the rule - php

I'm trying to use Yii URL manager to rewrite URLs like /site/about?tab=value to site/about/value or site/value.
My rule /<tab:\w+>' => 'site/about doesn't work. Here is the full URL manager code:
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' =>
[
'/' => 'site/index',
'/deals' => '/deal/deals',
'/<tab:\w+>' => 'site/about', //my rule
'/about' => 'site/about',
'/<action:[\-\w]+>' => 'site/<action>',
'/<module:\w+>' => '<module>/default/index',
'/<module:\w+>/<controller:\w+>/<id:\d+>' => '/<module>/<controller>/view',
'/<module:\w+>/<controller:\w+>/<id:\d+>/<action:[\-\w]+>/<entity_id:\d+>' => '/<module>/<controller>/<action>',
'/<module:\w+>/<controller:\w+>/<id:\d+>/<action:[\-\w]+>' => '/<module>/<controller>/<action>',
'/<controller:\w+>/<id:\d+>' => '<controller>/view',
'/<controller:\w+>/<id:\d+>/<action:[\-\w]+>/<entity_id:\d+>' => '<controller>/<action>',
'/<controller:\w+>/<id:\d+>/<action:[\-\w]+>' => '<controller>/<action>',
'/<controller:\w+>/<action:[\-\w]+>' => '<controller>/<action>',
'/<module:\w+>/<action:[\-\w]+>' => '<module>/default/<action>',
'/<module:\w+>/<controller:\w+>' => '<module>/<controller>/index',
],
And here is the widget code:
echo Nav::widget([
'items' => [
['label' => '1', 'url' => ['/site/about', 'tab' => '']],
['label' => '2', 'url' => ['/site/about', 'tab' => 'value']],
['label' => '3', 'url' => ['site/about', 'tab' => 'tariffs']],
['label' => '4', 'url' => ['site/about', 'tab' => 'team']],
['label' => '5', 'url' => ['site/about', 'tab' => 'documents']],
],
'options' => ['class' =>'nav-pills nav-stacked c-nav'],
]);

You should use named parameters, but you are naming the module/controller part.
You can only use these 3 reserved words:
module, controller, action
like the docs examples:
[
'<controller:(post|comment)>/<id:\d+>/<action:(create|update|delete)>' => '<controller>/<action>',
'<controller:(post|comment)>/<id:\d+>' => '<controller>/view',
'<controller:(post|comment)>s' => '<controller>/index',
]
But you are using <tab:\w+> that doesn't means anything for the rules section
Probably you could use:
'/site/about/<tab:\w+>' => 'site/about',
to catch URLs like:
web.com/site/about/bla
And then in the controller you could use the $tab variable like
namespace app\controllers;
class SiteController extends \yii\web\Controller {
public function actionAbout($tab)
{
return $this->renderContent("Hello $tab");
}
}
Hope this helps.

The problem was that some rules like /<controller:\w+>/<action:[\-\w]+>' => '<controller>/<action> and /<action:[\-\w]+>' => 'site/<action> were parsed earlier than mine, so I changed them.
Here is my solution:
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' =>
[
'/' => 'site/index',
'<tab:(about)>' => 'site/about',
'/about/<tab:(about|value|documents|tariffs|team)>' => 'site/about',
'/<action:(index|login|logout|contact|signup|request-password-reset|reset-password|thank-for-register|connect-inviteduser)>' => 'site/<action>',
'/<controller:(deal)>/<action:\w>' => 'deal/<action>',
'/<module:(trades)>' => '<module>/default/index',
'/<module:(trades)>/<controller:\w+>/<id:\d+>' => '/<module>/<controller>/view',
'/<module:(trades)>/<controller:\w+>/<id:\d+>/<action:[\-\w]+>/<entity_id:\d+>' => '/<module>/<controller>/<action>',
'/<module:(trades)>/<controller:\w+>/<id:\d+>/<action:[\-\w]+>' => '/<module>/<controller>/<action>',
'/<controller:\w+>/<id:\d+>' => '<controller>/view',
'/<controller:\w+>/<id:\d+>/<action:[\-\w]+>/<entity_id:\d+>' => '<controller>/<action>',
'/<controller:\w+>/<id:\d+>/<action:[\-\w]+>' => '<controller>/<action>',
'/<module:(trades)>/<action:[\-\w]+>' => '<module>/default/<action>',
'/<module:(trades)>/<controller:\w+>' => '<module>/<controller>/index',
],
],
The widget code:
<?php
echo Nav::widget([
'items' => [
['label' => 'О проекте', 'url' => ['/site/about', 'tab' => 'about']],
['label' => '5 причин работать через портал', 'url' => ['/site/about', 'tab' => 'value']],
['label' => 'Продвижение и тарификация', 'url' => ['site/about', 'tab' => 'tariffs']],
['label' => 'Проектная команда', 'url' => ['site/about', 'tab' => 'team']],
['label' => 'Документы', 'url' => ['site/about', 'tab' => 'documents']],
],
'options' => ['class' =>'nav-pills nav-stacked c-nav'],
]);
?>
And the action code:
public function actionAbout($tab = 'about')
{
$this->layout = '/about';
$tab = $tab == 'about' ? 'index' : $tab;
if (Yii::$app->request->isAjax)
return $this->renderPartial('about/' . $tab);
else
return $this->render('about/' .$tab);
}

Related

The 'pluginOptions["url"]' property has not been set

I have a problem with Kartik/DepDrop. I have used it many times in the past but are now having an issue
My view
'contentBefore'=>'<legend class="text-info"><small>Client Info</small></legend>',
'attributes'=>[ // 2 column layout
'model'=>['type'=>Form::INPUT_DROPDOWN_LIST, 'items'=>ArrayHelper::map(\app\models\Models::find()->All(), 'id','name'), 'options'=>['prompt'=>'Please Select..','id'=>'model']],
'field'=>[
'type'=>Form::INPUT_WIDGET,
'widgetClass'=>DepDrop::classname(),
'options' => ['id'=>'field'],
'pluginOptions' => [
'depends' => ['model'],
'placeholder' => 'select ...',
'url' => Url::to(['dd-field'])
],
],
'related_value'=>['type'=>Form::INPUT_TEXT, 'options'=>['placeholder'=>'Enter Value...']],
]
And the error shows this
_form.php at line 49 – yii\base\Widget::widget(['model' => app\models\RelatedFields, 'form' => kartik\form\ActiveForm, 'autoGenerateColumns' => true, 'rows' => [['contentBefore' => '<legend class="text-info"><small...', 'attributes' => ['model' => ['type' => 'dropdownList', 'items' => [1 => 'Clients', 2 => 'InvoiceItems', 3 => 'Invoices', 4 => 'Notes', ...], 'options' => ['prompt' => 'Please Select..', 'id' => 'model']], 'field' => ['type' => 'widget', 'widgetClass' => 'kartik\depdrop\DepDrop', 'options' => ['id' => 'field'], 'pluginOptions' => ['depends' => ['model'], 'placeholder' => 'select ...', 'url' => '/related-fields/dd-field']], 'related_value' => ['type' => 'textInput', 'options' => ['placeholder' => 'Enter Value...']]]], ['attributes' => ['actions' => ['type' => 'raw', 'value' => '<div style="text-align: right; m...']]]], ...])
If you look at the plugin options it is being passed
'pluginOptions' => ['depends' => ['model'], 'placeholder' => 'select ...', 'url' => '/related-fields/dd-field']
Any ideas anyone.
Found the issue, as i am using FormGrid, the pluginOptions and htmlOptions all need to be inside an options array like this
'field'=>[
'type'=>Form::INPUT_WIDGET,
'widgetClass'=>DepDrop::classname(),
'options' => [
'options'=> ['id' => 'field'],
'pluginOptions' => [
'depends' => ['model'],
'placeholder' => 'select ...',
'url' => '/related-fields/dd-field'
],
],
],

Yii2: yii\web\UrlManager does'nt make user-friendly urls

Here's urlManager configs:
return [
'class' => \yii\web\UrlManager::class,
'enablePrettyUrl' => true,
'showScriptName' => false,
'baseUrl' => '',
'rules' => [
'page/<id:[\\w-_]+>' => 'page/index',
],
];
Here's urlManager using:
$menuItems = [
[
'label' => 'Home',
'url' => Yii::$app->urlManager->createAbsoluteUrl(['/page']),
],
[
'label' => 'About',
'url' => Yii::$app->urlManager->createAbsoluteUrl(['/page', 'id' => 'about']),
],
[
'label' => 'Contact',
'url' => Yii::$app->urlManager->createAbsoluteUrl(['/page', 'id' => 'contact']),
],
];
And here's results from browser:
http://localhost/page?id=about
http://localhost/page?id=contact
What's wrong in my code?
You need to use exact route when creating URLs:
$menuItems = [
[
'label' => 'Home',
'url' => Yii::$app->urlManager->createAbsoluteUrl(['/page']),
],
[
'label' => 'About',
'url' => Yii::$app->urlManager->createAbsoluteUrl(['/page/index', 'id' => 'about']),
],
[
'label' => 'Contact',
'url' => Yii::$app->urlManager->createAbsoluteUrl(['/page/index', 'id' => 'contact']),
],
];

yii2: working with yii2-sitemap-module

i used https://github.com/himiklab/yii2-sitemap-module in my yii2 project
this is my console :
return [
'id' => 'basic-console',
'language' => 'fa-IR',
'basePath' => dirname(__DIR__),
'bootstrap' => ['log', 'gii'],
'controllerNamespace' => 'app\commands',
'modules' => [
'gii' => 'yii\gii\Module',
'user' => [
'class' => 'dektrium\user\Module',
'sourceLanguage' => 'en-US',
'languages' => 'fa-IR'
],
'sitemap' => [
'class' => 'himiklab\sitemap\Sitemap',
'models' => [
// your models
'app\modules\news\models\News',
// or configuration for creating a behavior
[
'class' => 'app\modules\news\models\News',
'behaviors' => [
'sitemap' => [
'class' => SitemapBehavior::className(),
'scope' => function ($model) {
/** #var \yii\db\ActiveQuery $model */
$model->select(['url', 'lastmod']);
$model->andWhere(['is_deleted' => 0]);
},
'dataClosure' => function ($model) {
/** #var self $model */
return [
'loc' => Url::to($model->url, true),
'lastmod' => strtotime($model->lastmod),
'changefreq' => SitemapBehavior::CHANGEFREQ_DAILY,
'priority' => 0.8
];
}
],
],
],
],
'urls' => [
// your additional urls
[
'loc' => '/news/all',
'changefreq' => \himiklab\sitemap\behaviors\SitemapBehavior::CHANGEFREQ_DAILY,
'priority' => 0.8,
'news' => [
'publication' => [
'name' => 'Example Blog',
'language' => 'fa',
],
'access' => 'Subscription',
'genres' => 'Blog, UserGenerated',
'publication_date' => 'YYYY-MM-DDThh:mm:ssTZD',
'title' => 'Example Title',
'keywords' => 'example, keywords, comma-separated',
'stock_tickers' => 'NASDAQ:A, NASDAQ:B',
],
'images' => [
[
'loc' => 'http://example.com/image.jpg',
'caption' => 'This is an example of a caption of an image',
'geo_location' => 'City, State',
'title' => 'Example image',
'license' => 'http://example.com/license',
],
],
],
],
'enableGzip' => true, // default is false
'cacheExpire' => 1, // 1 second. Default is 24 hours
],
],
'components' => [
'cache' => [
'class' => 'yii\caching\FileCache',
],
'log' => [
'targets' => [
[
'class' => 'yii\log\FileTarget',
'levels' => ['error', 'warning'],
],
],
],
'db' => $db,
],
'params' => $params,
];
this is my web.php:
'urlManager' => [
'enablePrettyUrl' => TRUE,
'showScriptName' => TRUE,
'enableStrictParsing' => FALSE,
'rules' => [
['pattern' => 'sitemap', 'route' => 'sitemap/default/index', 'suffix' => '.xml'],
// ...
],
],
'request' => [
// !!! insert a secret key in the following (if it is empty) - this is required by cookie validation
'cookieValidationKey' => 'salt',
],
'cache' => [
'class' => 'yii\caching\FileCache',
],
this is my news controller :
use himiklab\sitemap\behaviors\SitemapBehavior;
public function behaviors() {
return [
'sitemap' => [
'class' => SitemapBehavior::className(),
'scope' => function ($model) {
/** #var \yii\db\ActiveQuery $model */
$model->select(['id']);
// $model->andWhere(['is_deleted' => 0]);
},
'dataClosure' => function ($model) {
/** #var self $model */
return [
'loc' => Url::to($model->url, true),
'lastmod' => strtotime($model->lastmod),
'changefreq' => SitemapBehavior::CHANGEFREQ_DAILY,
'priority' => 0.8
];
}
],
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'delete' => ['get'],
],
],
];
}
Where is my xml file(url)??
What change should I do in my code?
If your controller (sitemap/default/index) is work well.
Your sitemap must be created in root directory via sitemap.xml file name, and accessible from http://your-domain/sitemap.xml URL.
For change it refer to this your code:
'rules' => [
['pattern' => 'sitemap', 'route' => 'sitemap/default/index', 'suffix' => '.xml'],
],
A shorter version of the routing that you can use:
'rules' => [
'sitemap.xml' => 'sitemap/default/index',
And relative to this route url in web: http://website/sitemap.xml
However, you can generate a sitemap without any extensions, which simplifies your work and does not need to understand other people's code. To do this, simply create the controller as in my working example:
<?php
namespace frontend\controllers;
use frontend\models\blog\articles\BlogArticles;
use frontend\models\blog\categories\BlogCategories;
use frontend\models\blog\series\BlogSeries;
use frontend\models\blog\tags\BlogTags;
use yii\web\Controller;
use yii\db\Query;
use Yii;
class SitemapController extends Controller
{
public function actionIndex()
{
//if You want delete cache
// Yii::$app->cache->delete('sitemap');
if (!$xml_sitemap = Yii::$app->cache->get('sitemap')) { // if has cache sitemap
$urls = array();
// all my categories
$articles = BlogArticles::find()->active()->orderCreatedAt()->all();
foreach ($articles as $article) {
$urls[] = array(
'loc' => $article->url,
'lastmod' => date( DATE_W3C, strtotime($article->lastMod) ),
'changefreq' => 'daily',
'priority' => 1.0
);
}
$categories = BlogCategories::find()->orderId()->all();
foreach ($categories as $category) {
$urls[] = array(
'loc' => $category->url,
'changefreq' => 'weekly',
'priority' => 0.8
);
}
$series = BlogSeries::find()->orderId()->all();
foreach ($series as $sery) {
$urls[] = array(
'loc' => $sery->url,
'changefreq' => 'weekly',
'priority' => 0.5
);
}
$tags = BlogTags::find()->orderId()->all();
foreach ($tags as $tag) {
$urls[] = array(
'loc' => $tag->url,
'changefreq' => 'weekly',
'priority' => 0.4
);
}
$xml_sitemap = $this->renderPartial('index', array(
'host' => Yii::$app->request->hostInfo, // your current domain
'urls' => $urls, // с generate urls for sitemap
));
Yii::$app->cache->set('sitemap', $xml_sitemap, 60*60*12); //cache 12 h
}
Yii::$app->response->format = \yii\web\Response::FORMAT_XML;
echo $xml_sitemap;
}
}
And You can see result in live site: https://coderius.biz.ua/sitemap.xml

YII2: How can I create a link/url in a Menu item to point to an external webpage instead of an action or view of my application

I am using the YII2 Menu Widget and did not find the solution to add attribute options like class , target on created link.
My code is below:
echo Menu::widget(
[
'options' => [
'class' => 'sidebar-menu'
],
'items' => [
[
'label' => Yii::t('backend', 'Admin'),
'url' => Yii::$app->homeUrl,
'icon' => 'fa-list-alt',
'options' => [
'class' => 'treeview',
],
'items' => [
[
'label' => Yii::t('backend', 'External link'),
'url' => 'http://google.com',
'icon' => 'fa-list-alt',
'options' => [
'target' => '_blank',
],
],
]
],
]
]
);
Option target is not added on generated link.
add the target like below through the template setting. The Options you have set in your code are the Html Options of the li element and not the link options.
'items' => [
[
'label' => Yii::t('backend', 'External link'),
'url' => 'http://google.com',
'icon' => 'fa-list-alt',
'template'=> '{label}',
],
]
Suggestions above do not seem to be working (in my case), an alternative solution is:
'linkOptions' => ['target' => '_blank']
For example
[
'url' => \Yii::$app->user->identity->getBlogLink(),
'linkOptions' => ['target' => '_blank'] ,
'label' => \Yii::t('app', 'Blog')
]
If you want to keep the icon in your menu:
'template'=> '{icon}{label}'
As regards the class you must specify it in the options key:
[
'label' => 'Debug',
'icon' => 'fa fa-dashboard',
'url' => ['/debug'],
'options' => ['class' => 'special'],
'template'=> '{icon}{label}',
],
gives the following menu:
<li class="special">
<a target="_blank" href="your_site_url_here/index.php?r=debug">
<i class="fa fa-dashboard"></i>
<span>Debug</span>
</a>
</li>
You can add any url. For Example,
echo Menu::widget([
'items' => [
['label' => 'Home', 'url' => ['http://www.google.com']],
['label' => 'About', 'url' => ['site/about']],
['label' => 'Contact', 'url' => ['site/contact']],
],
'options' => [
'class' => 'navbar-nav nav',
'id'=>'navbar-id',
'style'=>'font-size: 14px;',
'data-tag'=>'yii2-menu',
],
]);

As in Yii 2.0 (Menu :: Widget ) use the span?

When I use the following code, the end result is " TEST " and should be "TEST" in the tags .
echo Menu::widget([
'options' => ['id' => 'navigate'],
'items' => [
[
'label' => '<span>TEST</span>',
'url' => ['#'],
],
['label' => '<span>TEST2</span>', 'url' => ['#']],
],
]);
I know I should use encodeLabel but does not work and returns an error. Can you do to help?
It works fine for me:
echo Menu::widget([
'options' => ['id' => 'navigate'],
'encodeLabels' => false,
'items' => [
[
'label' => '<span>TEST</span>',
'url' => ['#'],
],
['label' => '<span>TEST2</span>', 'url' => ['#']],
],
]);

Categories