Understanding Yii2 "range" validation rule - yii2

I am new to Yii2 Framework and I need to understand the users status. I need to create an app that assign many statuses to the user, comparing to just 2 that Yii2 gave. In Yii2 common\models\Users there are two constants: STATUS_DELETED = 0; and STATUS_ACTIVE = 10;. There is a block of code that limits the range of the value of status to 0-10, which is STATUS_DELETED and STATUS_ACTIVE. If I need to add other status like STATUS_DISABLED = 20 in the rules() part, how do I modify this block? Do I need to remove the STATUS_ACTIVEand replace it with STATUS_DISABLED, or I should just limit the value of STATUS_DISABLED to be within the range of 0-10. How do I make this work? I don't understand this part.
class User extends ActiveRecord implements IdentityInterface
{
const STATUS_DELETED = 0;
const STATUS_ACTIVE = 10;
const STATUS_DISABLED = 20; // I want to add this
/**
* #inheritdoc
*/
public static function tableName()
{
return '{{%user}}';
}
/**
* #inheritdoc
*/
public function behaviors()
{
return [
TimestampBehavior::className(),
];
}
/**
* #inheritdoc
*/
public function rules()
{
return [
['status', 'default', 'value' => self::STATUS_ACTIVE],
['status', 'in', 'range' => [self::STATUS_ACTIVE, self::STATUS_DELETED]],
];
}
}

$range should contain array of valid values, not actual range in the meaning of "between A and B". So this:
['status', 'in', 'range' => [self::STATUS_ACTIVE, self::STATUS_DELETED]],
means that status should be either 0 or 10. For example 5 will not be valid value. And you can add any number of values to range array, like this:
[
'status', 'in',
'range' => [self::STATUS_ACTIVE, self::STATUS_DELETED, self::STATUS_DISABLED]
],

Related

FORM INPUT VALIDATION IN YII2

I'm trying to validate form input in yii2, I want to check user's input against a certain value from the database.
In my model i have this
use backend\models\RealAccount;
class Amount extends Model
{
public $amount;
/**
* {#inheritdoc}
*/
public function rules()
{
return [
[['amount'], 'number'],
['amount', 'checkBalance'],
['amount', 'compare', 'compareValue' => function($model) {
return RealAccount::getAccountBalance();
}, 'operator' => '<=', 'message' => \Yii::t('app','Insufficient balance')
],
];
}
public function checkBalance($attribute)
{
/*check wallet balance is greater or equal to amount*/
$balance = RealAccount::getAccountBalance();
if(!$balance >= $this->amount){
$this->addError($attribute, \Yii::t('app','Insufficient balance');
}
}
}
I tried both checkBlance, and also try compareValue but non of this work as I expected. NOTE i didn't use bot the same time, tired one it failed then i try the other,
Suppose my Balance is 200, if user input 201, i want to return error message. thanks for any help

Yii2 Model Rules Update Checking Rules For Same Record

I.E. If i update address_line1 then its giving error for mobile number allocated.
While update it should not match with it self.
Even if i change mobile number it should check with other user.
public function rules()
{
return [
[['mobile_number','address_line1','address_line2','city','state','country','pincode' ],'required'],
['mobile_number','mobile_number_allocation_validate'],
];
}
public function mobile_number_allocation_validate($attribute){
// add custom validation
$result = User::find()
->where('`mobile_number` = "'.$this->$attribute.'" AND
`status` = "A" ')->all();
if(!empty($result)){
$this->addError($attribute,'Mobile number is allocated to other vehicle');
}
}
Thanks in Advance
Change your condition as :-- Override beforeSave() of User ActiveRecord
/**
* BeforeSave() check if User ActiveRecord is created with same calculator param
* if created then return false with model error
*
*/
public function beforeSave($insert){
$model = self::find()->where('`mobile_number` = "'.$this->$attribute.'" AND
`status` = "A" ')->all();
if($model !== null && $model->id !== $this->id){
$this->addError('mobile_number' , 'Mobile number is allocated to other vehicle');
return false;
}
return parent::beforeSave($insert);
}
You should be able to use the unique validator for this, by simply adding a filter condition like this
public function rules()
{
return [
[['mobile_number','address_line1','address_line2','city','state','country','pincode' ],'required'],
['mobile_number','unique', 'filter' => ['status' => 'A']],
];
}

How to insert same data record to multiple table on Yii2

I'm using yii2-advanced. I've several table :
tb_user:(iduser(PK),username),
tb_profile:(id,iduser(FK)),
tb_status:(id,iduser(FK))
My question is how can i insert iduser(PK) from tb_user to iduser(FK) on tb_profile and tb_status after i push the signup button.
For a while i think i must to do some modification of bevahiours() function on User model and i found some error, or adding trigger syntax on the table ? (i think this is not a good ways).
Is there anyone who can help me, how to solve my problem ?
this is the User model before the modification :
<?php
namespace common\models;
use Yii;
use yii\base\NotSupportedException;
use yii\behaviors\TimestampBehavior;
use yii\db\ActiveRecord;
use yii\web\IdentityInterface;
class User extends ActiveRecord implements IdentityInterface
{
const STATUS_DELETED = 0;
const STATUS_ACTIVE = 10;
/**
* #inheritdoc
*/
public static function tableName()
{
return '{{%user}}';
}
/**
* #inheritdoc
*/
public function behaviors()
{
return [
'timestamp' => [
'class' => TimestampBehavior::className(),
'attributes' => [
ActiveRecord::EVENT_BEFORE_INSERT => 'created_at',
ActiveRecord::EVENT_BEFORE_UPDATE => 'updated_at',
],
'value' => function () {return date('Y-m-d h:m:s');},
],
];
}
/**
* #inheritdoc
*/
public function rules()
{
return [
['status', 'default', 'value' => self::STATUS_ACTIVE],
['status', 'in', 'range' => [self::STATUS_ACTIVE, self::STATUS_DELETED]],
];
}
/**
* #inheritdoc
*/
public static function findIdentity($id)
{
return static::findOne(['id' => $id, 'status' => self::STATUS_ACTIVE]);
}
/**
* #inheritdoc
*/
public function getId()
{
return $this->getPrimaryKey();
}
}
?>
The Controller :
public function actionSignup()
{
$model = new SignupForm();
if ($model->load(Yii::$app->request->post())) {
if ($user = $model->signup()) {
if (Yii::$app->getUser()->login($user)) {
return $this->goHome();
}
}
}
return $this->render('signup', [
'model' => $model,
]);
}
I had similar situation in one of my project where i had 2 tables like user,user_image where user_id was foreign key to add the path.
For those kind of situation you can use either of following approach
1.Insert record in both table on click of signup button. You will have to write update action accordingly.
$user = new User();
$user->name = "John"
$user->email = "John#gmail.com"
//Add if any other fields in table
$user->save(); //save the record
$user_image = new UserImage();
$user_image->user_id = $user->id;
$user_image->image = "image path"
//Add any other images here
$user_image->save();//save the record
2.You can also call create action of UserImage and do the same. If you use this approach than you might also need to use any other unique column to find the id of that user and use it to insert new record,for example in my table email is unique column so i can write following code in UserImage and get the id
$user = User::findOne(['email' => 'john#gmail.com']);//this will return whole row
$user_image->user_id = $user->id;
$user_image->image = "image path"
//Add any other images here
$user_image->save();//save the record
And that way you can use the code as per it suits your need
Thank you

Cannot redeclare class Cake\ORM\Behavior\ in CakePHP 3

I created src/Model/Behavior/ModernTreeBehavior.php:
<?php
namespace Cake\ORM\Behavior;
use Cake\Datasource\EntityInterface;
use Cake\Datasource\Exception\RecordNotFoundException;
use Cake\Event\Event;
use Cake\ORM\Behavior;
use Cake\ORM\Entity;
use Cake\ORM\Query;
use InvalidArgumentException;
use RuntimeException;
class ModernTreeBehavior extends Behavior
{
/**
* Cached copy of the first column in a table's primary key.
*
* #var string
*/
protected $_primaryKey;
/**
* Default config
*
* These are merged with user-provided configuration when the behavior is used.
*
* #var array
*/
protected $_defaultConfig = [
'implementedFinders' => [
'children' => 'findChildren',
'treeList' => 'findTreeList'
],
'implementedMethods' => [
'childCount' => 'childCount',
'getLevel' => 'getLevel'
],
'parent' => 'parent_id',
'path' => 'path',
'scope' => null,
'level' => null
];
public function getLevel($entity)
{
$primaryKey = $this->_getPrimaryKey();
$id = $entity;
if ($entity instanceof EntityInterface) {
$id = $entity->get($primaryKey);
}
$config = $this->config();
$entity = $this->_table->find('all')
->select([$config['path']])
->where([$primaryKey => $id])
->first();
if ($entity === null) {
return false;
}
return substr_count($entity[$config['path']], '-') + 1;
}
/**
* Returns a single string value representing the primary key of the attached table
*
* #return string
*/
protected function _getPrimaryKey()
{
if (!$this->_primaryKey) {
$this->_primaryKey = (array)$this->_table->primaryKey();
$this->_primaryKey = $this->_primaryKey[0];
}
return $this->_primaryKey;
}
}
I used $this->addBehavior('ModernTree'); in CommentTables.php
and I got error Fatal error: Cannot redeclare class Cake\ORM\Behavior\ModernTreeBehavior in .../src/Model/Behavior/ModernTreeBehavior.php on line 0
But if I paste /src/Model/Behavior/ModernTreeBehavior.php into built-in file TreeBehavior.php and load TreeBehavior.php, everything so goods.
Can you tell me the reason?
The namespace declaration of your class is wrong, it should be:
namespace App\Model\Behavior;

Symfony2: How to render datetime-local fields with FormBuilder?

The title says it all: How can i render html5 datetime-local fields from the formbuilder?
With
$builder->add('start', 'datetime', array('widget' => 'single_text'))
i can get a datetime field, but this is not supported by chrome.
Thanks in advance!
This is an old question, but for anybody coming across this post searching for a solution to that issue (like me), here is how I solved it:
Add a custom field type that inherits DateTimeType:
<?php
namespace AppBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\OptionsResolver;
class LocalDateTimeType extends AbstractType
{
const HTML5_FORMAT = "yyyy-MM-dd'T'HH:mm";
/**
* {#inheritdoc}
*/
public function buildView(FormView $view, FormInterface $form, array $options)
{
$view->vars['widget'] = $options['widget'];
if ($options['html5'] && 'single_text' === $options['widget'] && self::HTML5_FORMAT === $options['format']) {
$view->vars['type'] = 'datetime-local';
}
}
/**
* #param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'format' => self::HTML5_FORMAT
]);
}
/**
* {#inheritdoc}
*/
public function getParent()
{
return 'datetime';
}
/**
* #return string
*/
public function getName()
{
return 'local_datetime';
}
}
Register it as a service:
app.form.type.local_datetime:
class: AppBundle\Form\Type\LocalDateTimeType
tags:
- { name: form.type, alias: local_datetime }
Now you may use it in your forms:
(...)
$builder->add('myLocalDateTimeField', 'local_datetime', [
'widget' => 'single_text'
];
(...)
It's important that you set the widget to single_text - and yes, this is of course possible (as of Symfony 2.7).
Using localized dateTimes, you'll probably want to store your datetimes normalized in the database. A nice approach can be found here:
http://jeremycook.ca/2012/06/24/normalising-datetimes-with-doctrine-events/
The widget 'single_text' is not supported by the datetime field type.
The date and time parts have independent widgets. For Example:
<?php
// from date
$builder->add('DateFrom', 'datetime', array(
'input' => 'datetime',
'date_widget' => 'single_text',
'time_widget' => 'single_text',
'empty_value' => '',
'format' => 'yyyy-MM-dd',
'label' => 'From Date',
'required' => false,
'mapped' => false
));
Definition of the widget options for the date type.
Definition of the widget options for the time type.