How to manually add custom data to behaviors - yii

I've use BlameableBehavior but in some of my controller I want to manually set the user created value but it can't work.
public function behaviors()
{
return [
BlameableBehavior::className(),
];
}
this not work.
$model->createdBy = 1;
$model->save();
it try to use the BlameableBehavior.
how can I manually add it.
Thanks.

Try to use named behavior and detach it before saving model:
public function behaviors()
{
return [
'blameable' => BlameableBehavior::className(),
];
}
And then:
$model->detachBehavior('blameable');
$model->createdBy = 1;
$model->save();

Related

Laravel 8 factory class is not overriding the parameters while creating the factories

I am developing a web application using Laravel 8. I have noticed that quite a lot of things have changed in Laravel 8 including factories.
I have a factory class MenuCategoryFactory for my MenuCategory model class with the following definition.
<?php
namespace Database\Factories;
use App\Models\Menu;
use App\Models\MenuCategory;
use Illuminate\Database\Eloquent\Factories\Factory;
class MenuCategoryFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* #var string
*/
protected $model = MenuCategory::class;
/**
* Define the model's default state.
*
* #return array
*/
public function definition()
{
return [
'name' => $this->faker->name,
'menu_id' => Menu::factory()->create(),
];
}
}
In my code (database seeder class), I am trying to override the menu_id as follow while I am creating the factories.
$restaurant = Restaurant::first();
MenuCategory::factory()->create([
'menu_id' => $restaurant->menu->id
]);
But it is not using the value I passed, $restaurant->menu->id. Instead, it is creating a new menu. What is wrong missing in my code and how can I fix it?
In your factory definition, don't call ->create(), instead set it up like this:
public function definition()
{
return [
'name' => $this->faker->name,
'menu_id' => Menu::factory(),
];
}
Then you you should be able to set up related models (assuming you the relationships setup in the model) like this:
$restaurant = Restaurant::first();
MenuCategory::factory()->for($restaurant)->create();
Change the definition to
public function definition()
{
return [
'name' => $this->faker->name,
'menu_id' => function() {
Menu::factory()->create()->id,
}
];
}
then you can replace the value

How to validate two dimensional array in Yii2

How to validate two dimensional array in Yii2.
passenger[0][name] = bell
passenger[0][email] = myemail#test.com
passenger[1][name] = carson123
passenger[1][email] = carson###test.com
how to validate the name and email in this array
Thanks
Probably the most clean solution for validating 2-dimensional array is treating this as array of models. So each array with set of email and name data should be validated separately.
class Passenger extends ActiveRecord {
public function rules() {
return [
[['email', 'name'], 'required'],
[['email'], 'email'],
];
}
}
class PassengersForm extends Model {
/**
* #var Passenger[]
*/
private $passengersModels = [];
public function loadPassengersData($passengersData) {
$this->passengersModels = [];
foreach ($passengersData as $passengerData) {
$model = new Passenger();
$model->setAttributes($passengerData);
$this->passengersModels[] = $model;
}
return !empty($this->passengers);
}
public function validatePassengers() {
foreach ($this->passengersModels as $passenger) {
if (!$passenger->validate()) {
$this->addErrors($passenger->getErrors());
return false;
}
}
return true;
}
}
And in controller:
$model = new PassengersForm();
$model->loadPassengersData(\Yii::$app->request->post('passenger', []));
$isValid = $model->validatePassengers();
You may also use DynamicModel instead of creating Passanger model if you're using it only for validation.
Alternatively you could just create your own validator and use it for each element of array:
public function rules() {
return [
[['passengers'], 'each', 'rule' => [PassengerDataValidator::class]],
];
}
You may also want to read Collecting tabular input section in guide (unfortunately it is still incomplete).

Yii2 - loadMultiple with form model

I have a very simple scenario where I'm receiving a list of Variance Positions from the end user. To be able to validate the structure of the input, I created the following model for the single item that I should receive:
class VariancePositionsForm extends Model{
public $id;
public $position;
public function rules()
{
return [
[['id','position'], 'required'],
[['id', 'position'], 'integer'],
];
}
}
And in the controller, I have the following:
$variancePositions = [];
for($i=0;$i<sizeof(Yii::$app->request->post());$i++)
{
$variancePositions[] = new VariancePositionsForm();
}
VariancePositionsForm::loadMultiple($variancePositions, Yii::$app->request->post());
When I try to var_dump($variancePositions) however, I'm finding that its empty. In other words, loadMultiple() is not loading the models. What am I doing wrong?
Because you don't load the model from the form, only from json you have to add an empty string into the last parameter in this function:
VariancePositionsForm::loadMultiple($variancePositions, Yii::$app->request->post(), '');
look here:
https://github.com/yiisoft/yii2/blob/master/framework/base/Model.php#L884

yii2 How to change user password via actionUpdate?

I have advanced app. I create CRUD for User model. So i got update action. I tried to update password by adding
<?= $form->field($model, 'password')->passwordInput() ?>
But it call error, something like "password is write-only variable"
I tried to use field
<?= $form->field($model, 'new_password')->passwordInput() ?>
With adding in actionUpdate model->setPassword($this->new_password); and it throw Getting unknown property: common\modules\user\controllers\DefaultController::new_password.
But model->setPassword('123456'); successfully setting pussword 123456.
How can i get new_password field from view, to put it in model->setPassword('there');
Or maybe exist best way to do it?
UPD
I tried do it. Is not work.
public function beforeSave($insert)
{
if (parent::beforeSave($insert)) {
if ($this->new_password) {
$this->setPassword($this->new_password);
}
return true;
} else {
return false;
}
}
UPD2
public function setPassword($password) {
$this->password_hash = Yii::$app->security->generatePasswordHash($password);
}
And password_hash writing in database. I can easy change hash, via generated CRUD, but don't know how to use setPassword() in updateAction.
You can try write updatePassword function like setPassword with another variable
public function updatePassword($new_password) {
$this->password_hash = Yii::$app->security->generatePasswordHash($new_password);
}
declare a variable
public $new_password;
And add it in rules()
public function rules() {
return [
//...
['new_password', 'required'],
['new_password', 'string', 'min' => 6],
];
}
And at actionUpdate in your controller add
$model->updatePassword($model->new_password);
This should help
Here "$this" is your Controller which of course, doesn't have 'new_password' property. You'd better not set new password in controller, but do it in model, for example in beforeSave method:
if ($this->new_password) {
$this->setPassword($this->new_password);
}

setAttribute() function in YII is not working

I am using PHP Yii Framework with MongoDB(yiimongodbsuite). I have created a Model which extends from EMongoDocument.
<?php
class MyModel extends EMongoDocument
{
public $attr1;
public $attr2;
// rules, custom validations and other functions....
public function setAttributes($values, $safeOnly=true)
{
if(!is_array($values))
return;
if($this->hasEmbeddedDocuments())
{
$attributes=array_flip($safeOnly ? $this->getSafeAttributeNames() : $this->attributeNames());
foreach($this->embeddedDocuments() as $fieldName => $className)
if(isset($values[$fieldName]) && isset($attributes[$fieldName]))
{
$this->$fieldName->setAttributes($values[$fieldName], $safeOnly);
unset($values[$fieldName]);
}
}
parent::setAttributes($values, $safeOnly);
}
}
In Controller,
$dataModel = new MyModel();
$dataModel->setAttributes($_POST['MyModel']);
if($dataModel->validate()){
$dataModel->save();
}
the above code is not setting the attribute value.
Please let me know if there is any mistake.
You need to make sure that the 'safe' validation rules is used on each level.
To understand more read this http://www.yiiframework.com/wiki/161/understanding-safe-validation-rules/
Try to determine which valdation errors you have:
if(!$model->validate()) {
die( print_r($model->getErrors()) );
}