How validate parameters in yii2? - yii

How validate parameters in yii2?
I try, but not work validate:
I want validate in BaseData parameters - $key_active = '0', $login = '0'
class MyController extends Controller
{
public function actionMy($key_active = '0', $login = '0')
{
$model = new Mymodel();
if($model->validate()){
return $this->render('yes');
}
return $this->render('no');
}
}
class Mymodel extends Model
{
public $login;
public function rules()
{
return [
[['login'], 'unique', 'targetClass' => '\app\models\Account', 'message'=>'Этот email уже существует.'],
];
}
}
Maybe it's the wrong thing to be validated?

If you want to validate custom data, you need to add custom properties to model and add it rules.
public function actionMy($key_active = '0', $login = '0')
{
$model = new Mymodel();
$model->key_active = $key_active;
$modle->login = $login;
if($model->validate()){
return $this->render('yes');
}
return $this->render('no');
}
then in model
class Mymodel extends Model
{
public $login;
public $key_active;
public function rules()
{
return [
['login', 'unique', 'targetClass' => '\app\models\Account', 'message'=>'Этот email уже существует.'],
['key_active', 'YOUR_VALIDATION_RULES_HERE'],
];
}
}

$model = new Mymodel();
$model->key_active = $key_active;
$model->login = $login;

Related

Silverstripe 4.6 ModelAdmin dynamic $menu_Title

Is it possible to dynamically change the ModelAdmins $menu_Title to
e.g.
Member::currentUser()->Name ?
How ?
Thanks.
Ok. I got it.
<?php
use SilverStripe\Admin\ModelAdmin;
//...
//...
class UserAdmin extends ModelAdmin
{
private static $managed_models = array(
'YourDataObject'
);
private static $url_segment = 'test';
private static $menu_title = 'Test';
private static $menu_icon_class = 'fa fa-pagelines';
public function getEditForm($id = null, $fields = null)
{
$form = parent::getEditForm($id, $fields);
//.......
//.......
return $form;
}
public static function menu_title($class = null, $localise = true){
//return 'YOUR MENU TITLE';
return Member::currentUser()->Name;
}
}

FluentValidation not validating Email Address List(s) correctly?

{Version 8.0.0}
Why would this test be passing?
Test:
[Test]
public void Validation_NullTo_ShouldThrowModelValidationException()
{
var config = new EmailMessage
{
Subject = "My Subject",
Body = "My Body",
To = null
};
EmailMessageValidator validator = new EmailMessageValidator();
ValidationResult results = validator.Validate(config);
if (!results.IsValid)
{
foreach (var failure in results.Errors)
{
Console.WriteLine("Property " + failure.PropertyName + " failed validation. Error was: " + failure.ErrorMessage);
}
}
// results.Errors is Empty and resuts.IsValid is true here. Should be false with at least one Error message.
Assert.True(results.IsValid);
}
If I change the construction of the message like this, validation fails as normal.
var config = new EmailMessage
{
Subject = "My Subject",
Body = "My Body"
};
config.To = new EmailAddressList();
Validators:
public class EmailAddressListAtLeastOneRequiredValidator : AbstractValidator<EmailAddressList>
{
public EmailAddressListAtLeastOneRequiredValidator()
{
RuleFor(model => model)
.NotNull()
.WithMessage(AppMessages.Validation.AtLeastOneShouldBeDefined.ParseIn(nameof(EmailAddressList.Value)));
RuleFor(model => model.Value)
.NotNull()
.WithMessage(AppMessages.Validation.AtLeastOneShouldBeDefined.ParseIn(nameof(EmailAddressList.Value)));
RuleFor(model => model.Value.Count)
.GreaterThan(0)
.WithMessage(AppMessages.Validation.AtLeastOneShouldBeDefined.ParseIn(nameof(EmailAddressList.Value)));
When(model => model.Value?.Count > 0, () =>
{
RuleFor(model => model.Value)
.NotEmpty()
.WithMessage(AppMessages.Validation.AtLeastOneShouldBeDefined.ParseIn(nameof(EmailAddressList.Value)));
});
}
}
public class EmailAddressListValidator : AbstractValidator<EmailAddressList>
{
public EmailAddressListValidator()
{
RuleFor(model => model.Value).SetCollectionValidator(new EmailAddressValidator());
}
}
public class EmailAddressValidator : AbstractValidator<EmailAddress>
{
public EmailAddressValidator()
{
When(model => model.Value != null, () =>
{
RuleFor(model => model.Value)
.EmailAddress()
.WithMessage(AppMessages.Validation.ValueCannotBeNullOrEmpty.ParseIn(nameof(EmailAddress)));
});
}
}
public class EmailMessageValidator : AbstractValidator<EmailMessage>
{
public EmailMessageValidator()
{
RuleFor(model => model.To).SetValidator(new EmailAddressListAtLeastOneRequiredValidator());
When(model => model.Cc?.Value?.Count > 0, () =>
{
RuleFor(model => model.Cc).SetValidator(new EmailAddressListValidator());
});
When(model => model.Bcc?.Value?.Count > 0, () =>
{
RuleFor(model => model.Bcc).SetValidator(new EmailAddressListValidator());
});
RuleFor(model => model.Subject)
.NotEmpty().WithMessage(AppMessages.Validation.ValueCannotBeNullOrEmpty.ParseIn(nameof(EmailMessage.Subject)))
.MaximumLength(100).WithMessage(AppMessages.Validation.ValueLengthCannotBeGreaterThan.ParseIn(nameof(EmailMessage.Subject), 100));
RuleFor(model => model.Body)
.NotEmpty().WithMessage(AppMessages.Validation.ValueCannotBeNullOrEmpty.ParseIn(nameof(EmailMessage.Body)));
}
}
EmailMessage and EmailAddressList Classes:
public class EmailMessage : IEmailMessage
{
public EmailAddressList To { get; set; } = new EmailAddressList();
public EmailAddressList Cc { get; set; } = new EmailAddressList();
public EmailAddressList Bcc { get; set; } = new EmailAddressList();
public string Subject { get; set; }
public string Body { get; set; }
}
public class EmailAddressList : ModelValidation, IEnumerable<EmailAddress>
{
public List<EmailAddress> Value { get; set; } = new List<EmailAddress>();
public EmailAddressList()
: base(new EmailAddressListValidator())
{
}
public EmailAddressList(string emailAddressList)
: base(new EmailAddressListValidator())
{
Value = Split(emailAddressList);
}
public EmailAddressList(IValidator validator)
: base(validator ?? new EmailAddressListValidator())
{
}
public List<EmailAddress> Split(string emailAddressList, char splitChar = ';')
{
return emailAddressList.Contains(splitChar)
? emailAddressList.Split(splitChar).Select(email => new EmailAddress(email)).ToList()
: new List<EmailAddress> { new EmailAddress(emailAddressList) };
}
public string ToString(char splitChar = ';')
{
if (Value == null)
return "";
var value = new StringBuilder();
foreach (var item in Value)
value.Append($"{item.Value};");
return value.ToString().TrimEnd(';');
}
public void Add(string emailAddress, string displayName = "")
{
Value.Add(new EmailAddress(emailAddress, displayName));
}
public void Add(EmailAddress emailAddress)
{
Value.Add(emailAddress);
}
public IEnumerator<EmailAddress> GetEnumerator()
{
return Value.GetEnumerator();
}
[ExcludeFromCodeCoverage]
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
Here is answer from Jeremy Skinner...
This behaviour is normal and correct. Complex child validators set
with SetValidator can only be invoked if the target property is not
null. As the To property is null, the child validator won't be
invoked. What you should be doing is combining the SetValidator with a
NotNull check:
RuleFor(model => model.To) .NotNull().WithMessage("...");
.SetValidator(new EmailAddressListAtLeastOneRequiredValidator());
...and then remove the RuleFor(model => model).NotNull() from the
EmailAddressListAtLeastOneRequiredValidator as this will never be
executed. Overriding PreValidate is not relevant here. Using
PreValidate like this is only relevant when trying to pass a null to
the root validator. When working with child validators, they can never
be invoked with a null instance (which is by design), and the null
should be handled by the parent validator.

Yii2 Login from DB (Setting unknown property: app\models\User::password_hash)

I want the user authentication in Yii to be based on user table in my database. This is my User model:
<?php
namespace app\models;
use Yii;
use yii\base\NotSupportedException;
use yii\db\ActiveRecord;
use yii\helpers\Security;
use yii\web\IdentityInterface;
/**
* This is the model class for table "user".
*
* #property integer $id
* #property string $username
* #property string $password
* #property string $title
*/
class User extends \yii\db\ActiveRecord implements IdentityInterface
{
public static function tableName()
{
return 'user';
}
/**
* #inheritdoc
*/
public function rules()
{
return [
[['username', 'password'], 'required'],
[['username', 'password'], 'string', 'max' => 100]
];
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'UserID',
'username' => 'Username',
'password' => 'Password',
];
}
public static function findIdentity($id) {
return static::findOne($id);
}
public static function findIdentityByAccessToken($token, $type = null) {
return static::findOne(['access_token' => $token]);
}
public static function findByUsername ($username){
return static::findOne(['username' => $username]);
}
public static function findbyPasswordResetToken($token)
{
$expire= \Yii::$app->params['user.passwordResetTokenExpire'];
$parts = explode('_', $token);
$timestamp = (int) end($parts);
if ($timestamp + $expire < time()) {
//token expired
return null;
}
return static::findOne(['password_reset_token' => $token ]);
}
public function getId() {
return $this->getPrimaryKey();
}
public function getAuthKey() {
return $this->auth_key;
}
public function validateAuthKey($authKey) {
return $this->getAuthKey() === $authKey;
}
public function validatePassword($password){
$this->password_hash= Yii::$app->security->generatePasswordHash ($password);
}
public function generateAuthKey()
{
$this->auth_key = Yii::$app->security->generateRandomKey();
}
/**
* Generates new password reset token
*/
public function generatePasswordResetToken()
{
$this->password_reset_token = Yii::$app->security->generateRandomKey() . '_' . time();
}
/**
* Removes password reset token
*/
public function removePasswordResetToken()
{
$this->password_reset_token = null;
}
}
But it is giving me this error when I try to login:
Setting unknown property: app\models\User::password_hash
This is actionLogin in siteController:
public function actionLogin()
{
if (!\Yii::$app->user->isGuest) {
return $this->goHome();
}
$model = new LoginForm();
if ($model->load(Yii::$app->request->post()) && $model->login()) {
return $this->goBack();
} else {
return $this->render('login', [
'model' => $model,
]);
}
}
And this is the code in LoginForm.php:
public function validatePassword($attribute, $params)
{
if (!$this->hasErrors()) {
$user = $this->getUser();
if (!$user || !$user->validatePassword($this->password)) {
$this->addError($attribute, 'Incorrect username or password.');
}
}
}
/**
* Logs in a user using the provided username and password.
* #return boolean whether the user is logged in successfully
*/
public function login()
{
if ($this->validate()) {
return Yii::$app->user->login($this->getUser(), $this->rememberMe ? 3600*24*30 : 0);
} else {
return false;
}
}
I don't know what is wrong, could you please help me fix this?
This is because the column "password_hash" assigned in the function "validatePassword()" doesn't exist in database or is not declared in the User model.
If the password hash is stored in the database in "password" field, then change "validatePassword()" to,
public function validatePassword($password)
{
return $this->password === Yii::$app->security->generatePasswordHash ($password);
}
Here is the solution
1: Declare it in the user controller
* #property string $password_hash
class User extends ActiveRecord implements IdentityInterface
{
public $password;
/**
* #inheritdoc
*/
public static function tableName()
{
return '{{%user}}';
}
public function rules()
{
return [
[['username','email','first_name','last_name','address','password','contact_no','role'], 'safe'],
[['email'], 'unique'],
[['email'], 'email'],
];
}
.
.
....
public function validatePassword($password)
{
return Yii::$app->security->validatePassword($password, $this->password_hash);
}
2: In your LoginForm model rule function add this
['password', 'validatePassword'],
everything else looks okay. Hope this helps you

Creating dynamic attributes and properties in model class

I used code
$sql="SELECT 'Name' FROM XXX";
$names =$connection->createCommand($sql)->query()->readAll();
$myDynamicObject = new DynamicModel($names);
class DynamicModel extends CModel
{
protected $_members = array();
public function __construct($nameFields)
{
foreach ($nameFields as $member) {
$this->_members[$member] = null;
}
parent::__construct();
}
/**
* #return array validation rules for model attributes.
*/
public function rules()
{
$allMembers = implode(', ', array_keys($this->_members));
return array(
array($allMembers, 'required'),
);
}
public function __get($attribute)
{
if (in_array($attribute, array_keys($this->_members))) {
return $this->_members[$attribute];
} else {
return parent::__get($attribute);
}
}
public function __set($attribute, $value)
{
if (in_array($attribute, array_keys($this->_members))) {
return $this->_members[$attribute] = $value;
} else {
return parent::__set($attribute, $value);
}
}
public function getAttributes()
{
return $this->_members;
}
public function setAttributes($attributes)
{
$this->_members = $attributes;
}
}
i print this model in controller but
not nothing coming..server error came..
" More
An unexpected condition was encountered while the server was attempting to fulfill the request.
Error code: 500"
CModel is an abstract class and you need to at least implement the attributeNames() function.
In your case I guess the following should suffice:
public function attributeNames()
{
return array_keys($this->_members);
}

OOP PHP error for non-object when trying to get user info from database [duplicate]

This question already has answers here:
Call to a member function on a non-object [duplicate]
(8 answers)
Closed 10 years ago.
I'm trying to make oop class to get user info but i get this error
Fatal error: Call to a member function prepare() on a non-object in functions.php
user.php - >
include_once 'functions.php';
$user = new User();
echo $user->get_fullname(5);
functions.php ->
include_once 'database.php';
class User
{
public function connect()
{
$dbh = new DB_Class();
}
public function get_fullname($uid)
{
$getName = $dbh->prepare("SELECT EmailAddress FROM users WHERE UserID =:username");
$getName->bindParam(':username', $uid);
$getName->execute();
$rowName = $getName->fetch();
$email = $rowName['emailaddress'];
return $email;
}
}
database.php - >
class DB_Class
{
public function connect() {
try {
$dbh= new PDO("mysql:host=localhost;dbname=root",'users','password', array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"
));
} catch (PDOException $e) {
echo $e->getMessage();
}
$dbh->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_WARNING);
$dbh->setAttribute(PDO::ATTR_CASE,PDO::CASE_LOWER);
}
}
What i'm doing wrong :(
You never actually give access to the PDO instance $dbh to the things youre trying to use it in. It seems like youre using classes simple as groupings of functions but also expecting some magic to happen :-) This is how i would do it with your existingcode:
class DB_Class {
protected $dsn;
protected $user;
protected $password;
protected $connection;
public function __construct($dsn = null, $user = null, $password = null)
{
$this->dsn = $dsn;
$this->user = $user;
$this->password = $password;
}
public function connect()
{
if($this->connection) {
return $this->connection;
}
try {
$this->connection = new PDO($this->dsn,$this->user, $this->password,
array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"
));
$this->connection->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_WARNING);
$this->connection->setAttribute(PDO::ATTR_CASE,PDO::CASE_LOWER);
return $this->connection;
}
catch (PDOException $e) {
return false;
}
}
}
class User {
protected $db;
public function __construct(DB_Class $db = null)
{
$this->db = $db;
}
public function setDb(DB_Class $db)
{
$this->db = $db;
}
public function get_fullname($uid)
{
$stmt = $this->db->connect()->prepare("SELECT EmailAddress FROM users WHERE UserID =:username");
$stmt->execute(array(':username', $uid));
if($row = $getName->fetch()) {
return $row['emailaddress'];
} else {
return null;
}
}
}
The $dbh variable isn't being passed into the get_fullname function. You'd need to do something like:
public function connect()
{
$dbh = new DB_Class();
return $dbh;
}
public function get_fullname($uid)
{
$dbh = $this->connect();
you need to declare $dbh as property of User class and access it via $this identifier:
class User
{
protected $dbh;
public function connect()
{
$this->dbh = new DB_Class();
}
public function get_fullname($uid)
{
$getName =$this->dbh->prepare("SELECT EmailAddress FROM users WHERE UserID =:username");
$getName->bindParam(':username', $uid);
$getName->execute();
$rowName = $getName->fetch();
$email = $rowMail['emailaddress'];
return $email;
}
}
You are never actually assigning your class properties as a property, all you are doing when declaring the variables inside of your methods is putting them into the methods current scope and they are destroyed once the method finishes execution.
To properly set a property within a class you need to declare them using $this->varname and the same goes for accessing them.
You are also using an incorrect name for the classes construction, the constructor must be set to __construct not connect.
As you can see in the updated code the $dbh variable is now a property of the User class and can be called between it's methods.
User Class
class User
{
public function __construct()
{
$this->dbh = new DB_Class();
}
public function get_fullname($uid)
{
$getName = $this->dbh->getConnection()->prepare("SELECT EmailAddress FROM users WHERE UserID =:username");
$getName->bindParam(':username', $uid);
$getName->execute();
$rowName = $getName->fetch();
$email = $rowName['emailaddress'];
return $email;
}
}
Database Class
class DB_Class
{
public function __construct() {
try {
$this->dbh = new PDO("mysql:host=localhost;dbname=root",'users','password', array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"
));
} catch (PDOException $e) {
echo $e->getMessage();
}
$this->dbh->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_WARNING);
$this->dbh->setAttribute(PDO::ATTR_CASE,PDO::CASE_LOWER);
}
public function getConnection() {
return $this->dbh;
}
}
You will benefit greatly by using http://us2.php.net/manual/en/oop5.intro.php as a resource.