I have configured Sluggable behavior on my model as follows:
public function behaviors() {
return [
[
'class' => SluggableBehavior::className(),
'attribute' => 'title',
'ensureUnique' => true,
]
];
}
I need to do:
If the user fills a form field called "URL", this should be used instead of the automatic generated slug.
If user changes the title, they will mark a checkbox if they want the slug updated.
I have found that Sluggable Behaviour has an attribute "immutable" but I do not see a method to manipulate it.
Also I do not see a way to stop automatic generation if value is given.
Any ideas?
For such unusual requirements you should probably extend SluggableBehavior and overwrite getValue() and isNewSlugNeeded() methods to feat your needs.
You may also play with $value property and/or change some behavior settings in beforeValidate() of model:
public function beforeValidate() {
$this->getBahavior('my-behavior-name')->immutable = !$this->changeSlugCheckbox;
return parent::beforeValidate();
}
But custom behavior is much more clean solution.
Related
I'm searching for a way to modify the default query that gets executed when Yii 2.0 receives a request on one of the default rules using the ActionController.
I do not want to unset the actions and create new ones, I only want to add some clauses to the query itself.
I found a way to do that with the 'index' route (documented here), but the required property prepareDataProvider is not available for the other routes.
The implementation looks something like this:
public function actions()
{
$actions = parent::actions();
$actions['index']['prepareDataProvider'] = [$this, 'prepareDataProvider'];
return $actions;
}
public function prepareDataProvider() {
return new ActiveDataProvider([
'query' => Regulatory::find()->where(['deleted' => 0])
]);
}
Have I missed a better way to specify the ActiveDataProvider for the other routes? Or is this just not possible for the other routes?
I would appreciate any pointers that might help me solve this problem.
I am having a model class in my Yii2-advanced application which was having some attributes.
public function rules()
{
return [
[['SESSION_TITLE', 'SESSION_DESCRIPTION', 'TRAINER_ID'], 'required'],
[['TRAINER_ID','IS_ACTIVE', 'IS_DELETED'], 'integer'],
];
}
Now, I need to add an attribute TNI_NUMBER in model which I already have added in database table with similar spellings. After adding in model.
public function rules()
{
return [
[['SESSION_TITLE', 'SESSION_DESCRIPTION', 'TRAINER_ID'], 'required'],
[['TRAINER_ID','TNI_NUMBER' ,'IS_ACTIVE', 'IS_DELETED'], 'integer'],
];
}
The form is showing Getting Unknown Property on that specific attribute, on loading the form right after adding this attribute. Note that the data type of attribute in model and in database is not an issue. And the database connection array has set 'enableSchemaCache' => true in it and it can't be set to false.
Yii::$app->cache->flush();
This worked for me, added it before calling model class in controller action.
NOTE: this is for one-time usage only, once page refreshed after adding this line, do remember to comment or remove it.
you need to refresh database schema
Yii::$app->db->schema->refresh();
You only need to run this once
or
you can set 'enableSchemaCache' to false
We have web pages, where user will be redirected to $this->goHome(), if the session timeouts or user logouts. We have to destroy the all the session so, we have to add a function with destroying session. This function should be executed before running any action/controller in Yii2 i.e. similar to hooks in codeigniter. We have tried a helper function with destroying session and we have called the function as HomeHelper::getHelpDocUrlForCurrentPage(); in main.php layout, but the layout will be executed after running action in controller, it should work on running any controller as we have 100+ controllers. How this can be achieved, please suggest us in right way. Thanks in advance.
in
config/main.php
you could try using 'on beforeAction'
return [
'vendorPath' => dirname(dirname(__DIR__)) . '/vendor',
'bootstrap' => [
'log',
....
],
'on beforeAction' => function($event){
// your code ..
} ,
'modules' => [
....
],
...
];
While #ScaisEdge solution would work I believe application config is not proper place to hold application logic.
You should use filters to achieve result you want.
First you need to implement filter with your logic. For example like this:
namespace app\components\filters;
class MyFilter extends yii\base\ActionFilter
{
public function beforeAction() {
// ... your logic ...
// beforeAction method should return bool value.
// If returned value is false the action is not run
return true;
}
}
Then you want to attach this filter as any other behavior to any controller you want to apply this filter on. Or you can attach the filter to application if you want to apply it for each action/controller. You can do that in application config:
return [
'as myFilter1' => \app\components\filters\MyFilter::class,
// ... other configurations ...
];
You might also take a look at existing core filters if some of them can help you.
Here's the code from my AuthController:
public function postRegister(Request $request)
{
$this->validate($request, [
'name' => 'required|min:3',
'email' => 'required|email|unique:users',
'password' => 'required|min:5|max:15',
]);
}
If the validation fails I'm getting redirected to the previous page. Is there a way to pass additional data along with the input and the errors (which are handled by the trait)?
Edit: Actually, the trait does exactly what I want, except the additional data I want to pass. As #CDF suggested in the answers I should modify the buildFailedValidationResponse method which is protected.
Should I create a new custom trait, which will have the same functionality as the ValidatesRequests trait (that comes with Laravel) and edit the buildFailedValidationResponse method to accept one more argument or traits can be easily modified following another approach (if any exists)?
Sure you can, check the example in the documentation:
http://laravel.com/docs/5.1/validation#other-validation-approaches1
Using the fails(); method, you can flash the errors and inputs values in the session and get them back with after redirect. To pass other datas just flash them with the with(); method.
if ($validator->fails()) {
return back()->withErrors($validator)
->withInput()
->with($foo);
}
There are 2 needed functions: set password when registering and change password, if user forgot it. When user signs up, password length must be at least 4 chars; when changes pass - at least 5 chars.
View is common for registration and changing pass. Obviously, also 2 actions exist, in which either scenario 'signup', either 'change' used.
Code snippet in model:
public function rules() {
return [
['password', 'string', 'min' => 4, 'on' => 'signup'],
['password', 'string', 'min' => 5, 'on' => 'change'],
];
}
But I want to do do it via scenarios(). How to do it? I'm a beginner in Yii, so did not understand, when and how to use scenarios(). Thanks.
UPD. I need to use scenarios() for ONE field with ONE rule, but DIFFERENT arguments to this one rule. how to define a scenario in Yii2? - it is NOT my case.
As documentation about scenarios() says: The default implementation of this method will return all scenarios found in the rules() declaration. So generally you do not need to override this method, because it will look for on array keys to set active attributes for current scenario an validate them properly.
So in your case 'on' => 'some scenario' for different validations of the same attribute is exactly what you need.