Yii2: Replace querystring parameter with value using urlManager - yii2

I have a rule in urlManager
'rules' => [
'products/<whatever:[-_0-9a-zA-Z]+>' => 'products/show',
],
and I have controller Products with actionShow()
public function actionShow($name)
{
var_dump($name);
echo 'actionShow is work';
}
But a have an Error: Bad Request (#400) Missing required parameters: name
How to transfer a product's $name to the controller, or how it can be obtained from the URL in the controller?

The CORRECT and COMPLETE answer is that you have to use the rule like below.
'rules' => [
'products/<name:[\-\w]+>' => 'products/show',
],
then in your products controller you don't need to pass $name in the parameter anymore that is why we defined in the rule and you have to use the
Yii::$app->request->queryParams['name']; or Yii::$app->request->get('name') to get the name of the product, your action will look like below
public function actionShow()
{
echo Yii::$app->request->get('name');
}
after doing all the settings above open brower and type
http://yourdomain.com/products/some-product
and it will show you
some-product
When you have to create a link to that page lets say in menu you have under products all products listed and you have to create a link to detail page for all of them i.e actionShow you would do it like below.
<?=Html::a($model->name,
Yii::$app->urlManager->createUrl([
'products/show',
'name'=>$model->slug
])
);
?>

I guess you should specify the name of your variable in the rule. You are calling it whatever, change it to name:
'rules' => [
'products/<name:[-_0-9a-zA-Z]+>' => 'products/show',
],

Related

Yii2 Variables to be passed in URL - rules not working

I have two actions with parameters. I have written two url rules, but only one works at a time. I don't know the issue. These are my acions,
Index action in Site Controller and other one is index action in Product Controller
public function actionIndex($language = null) {
/* some codes */
}
public function actionIndex($id= null) {
/* some codes */
}
'rules' => [
'<language>' => 'site/index',
'<id>' => 'product/index',
]
The above are my url rules.But only the first rule is working. What is the issue?
Your rules are ambiguous. '<language>' pattern will match every URL, so second rule will never be reached. You should either create different URL structure for these two rules:
'rules' => [
'<language>' => 'site/index',
'id/<id>' => 'product/index',
],
Or use different patters (only literal languages and numerical IDs):
'rules' => [
'<language:[a-z]+>' => 'site/index',
'<id:\d+>' => 'product/index',
],

Yii2: Kartik Select2: Initial Value from Model Attribute

I have a Model who has a column (attribute) that stored a comma separated value of IDs.
For Example,
Movie has a column "Genre" that includes more than one genre, e.g.: 40,20,1,3
How can I use Select2 widget to show these values separated when 'multiple' => true
And how can I save them back into comma-separated value as a string. I want a solution that will allow for quick flexibility. I know you can implode and explode the string but seems too much.
Any help appreciated
If I remember correctly pass the default option as part of the $options configuration for the widget:
echo $form->field($model, 'model_attribute_name')->widget(Select2::className(), [
'data' => $data
'options' => [
'class' => 'form-control',
'placeholder' => 'Choose Option...',
'selected' => 40
],
'pluginOptions' => [
'allowClear' => true,
],
])->label('Select2 Form Field');
This is from memory for grain fo salt here. The documentation at http://demos.krajee.com/widget-details/select2 is not very specific about how to do this.
I don't believe you can do that. Select2 sends the data in post as an array, so you would still need to use implode before saving. What i would do instead is in your model class:
class MyModel extends \yii\db\ActiveRecord {
$public myArrayAttribute;
...
public function beforeSave($insert) {
if (parent::beforeSave($insert)) {
$this->myAttribute = implode(',', $this->myArrayAttribute);
return true;
}
return false;
}
public function afterFind() {
parent::afterFind();
$this->myArrayAttribute = explode(',', $this->myAttribute);
}
}
This way myArrayAttribute will hold the values from the comma separated field as an array. Of course you will need to add validation rules for it and use it instead of your other attribute in create and update forms.
if you're displaying a form with already populated fields, maybe you want to update an already existing object, and you want to display the already saved value for the Select2 field, use 'data' => [ 1 => 'Some value' ], where 1 is the value, associated to the value displayed in the form. You can retrieve stuff to put in data from DB beforehand.
Source: https://github.com/kartik-v/yii2-widget-select2/issues/37

Pass dynamic params in the ajax call of yii2-grid EditableColum widget

the \kartik\grid\EditableColumn widget has a parameter called ajaxSettings where you may override the parameters passed with the ajax request to the server. What i want to do is to dynamically pass the selected rows ids together with the value coming from the popover to the server. I manage to do that passing static parameter coming from a php array in compile time like so
Editable::widget(['name' => 'publishDate', 'ajaxSettings' => ['ids' => [1,2,3]]])
but It seems that i cannot use a jquery selector there to grab the ids of the selected columns like so
Editable::widget([
'name' => 'publishDate',
'ajaxSettings' => [
'ids' => '$("#books-grid").yiiGridView("getSelectedRows")'
]
])
Maybe you want to try creating a variable outside the Editable::widget([ like this:
var arrayIds = $("#books-grid").yiiGridView("getSelectedRows");
And then assign it to the widget:
Editable::widget([
'name' => 'publishDate',
'ajaxSettings' => [
'ids' => arrayIds
]
])
Hope this helps,
Leo.

Yii2 Behaviors / Scenarios Modify Attribute

I have a model "Product" that I would like to modify or "mutate" one of its attributes for, but only in specific instances.
I store attribute, price as an integer. So $1.99 gets stored as 199.
I would like to incorporate this with the activeForm in such a way that when getting the price it converts to "1.99" in the field (visually). But when I submit the form, before validation, it modifies the price from "1.99" to "199".
I'm assuming this will require Behaviors, and specifically attaching a behavior to the model before creating the active form. However, I'm still confused on how to set this up. I see there is an AttributeBehavior class or I can make my own Behavior class, but I've been having trouble figuring out implementation in this case.
The situation:
foreach ($store_item->storeProducts as $i=>$product) {
?>
<tr>
<td>
<?= $form->field($product, '['.$i.']price')->label(false); ?>
</td>
</tr>
<?php
$i++;
}
?>
Here is a scenario where I check for empty attribute and assign value before saving. Note owner returns the Model so that you can access model attributes and functions that are public. Let me know if I can explain anything further
public function behaviors()
{
return [
[
'class' => AttributeBehavior::className(),
'attributes' => [
ActiveRecord::EVENT_BEFORE_INSERT => 'yourAttrib',
],
'value' => function ($event) {
$code = "N/A";
if(!empty($this->owner->yourAttrib))
{
$code = $this->owner->yourAttrib; //here change your attribute accordingly
}
return $code;
},
],
//other behaviors
];
}
You could simply use a getter/setter, e.g. :
public function getRealPrice()
{
return $this->price/100;
}
public function setRealPrice($value)
{
$this->price = $value*100;
}
And don't forget to :
add realPrice in your model's rules,
use realPrice in your form (instead of price).

how to pass alphanumeric parameter in yii2 controller action

My code is
class WorkshopsController extends Controller
{
public $layout = false;
public function actionIndex($address)
{
echo $address;
return $this->render('workshops.twig');
}
}
I want to pass any place address to above given action. how can i do that in Yii2. Address can be like "Mazyad Road, Mazyad - Al Ain - أبو ظبي - United Arab Emirates"
You need to request you workshops/index page with address query parameter example.com/workshops/index?address=some address. Yii will automaticaly call your action and pass query params into it.
EDIT
If you wish to use pretty url, you must specify urlManager rules for it. E.g.
rules => [
'workshops/<address>' => 'workshops/index',
],
Also if you wish your page open when addess parameter not specified you can define rules like this:
[
'pattern' => 'workshops/<address>',
'route' => 'workshops/index',
'defaults' => ['address' => ''],
]