While I am testing yii2 multiple select2 tutorial, I faced the error "Class 'common\models\LinkAllBehavior' not found".
Here is my model code,
public $tag_ids;
public static function tableName()
{
return 'post';
}
public function rules()
{
return [
[['title', 'body','tag_ids'], 'required'],
[['body'], 'string'],
[['title'], 'string', 'max' => 255],
];
}
public function attributeLabels()
{return [
'id' => 'ID',
'title' => 'Title',
'body' => 'Body',
];}
public function behaviors()
{
return [
LinkAllBehavior::className(),
];
}
public function afterSave($insert, $changedAttributes)
{
$tags = [];
foreach ($this->tag_ids as $tag_name) {
$tag = Tag::getTagByName($tag_name);
if ($tag) {
$tags[] = $tag;
}
}
$this->linkAll('tags', $tags);
parent::afterSave($insert, $changedAttributes);
}
public function getPostToTags()
{
return $this->hasMany(PostToTag::className(), ['post_id' => 'id']);
}
public function getTags()
{
return $this->hasMany(Tag::className(), ['id' => 'tag_id'])->viaTable('post_to_tag', ['post_id' => 'id']);
}
}
So, I would like to know what is LinkAllBehavior and how does it work?
Thanks
LinkAllBehavior::className()
above line is causing this, if you are using yii2-linkall
try adding
use cornernote\linkall\LinkAllBehavior;
on top of your model code along with other use statements
I get an error while using getAttributes method : "Call to a member function getAttributes() on a non-object".
Now, In my Controller:
$notifications = Notifications::return_new()->getAttributes();
var_dump($notifications);
In model
public static function return_new(){
return Notifications::find()->where(['is_seen' => 0])->all();
}
Now, the Yii docs say that getAttribute() takes an array as a parameter, so I've tried
$notifications = Notifications::return_new()->getAttributes('text');
but it still persists with the same error. Any help?
Here is the model
<?php
namespace frontend\models;
use Yii;
*/
class Notifications extends \yii\db\ActiveRecord
{
public static function tableName()
{
return 'notifications';
}
public function rules()
{
return [
[['created_on', 'user_id', 'text'], 'required'],
[['user_id'], 'integer'],
[['created_on'], 'safe'],
[['text'], 'string', 'max' => 255]
];
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'created_on' => 'Created On',
'user_id' => 'User ID',
'text' => 'Text',
];
}
public static function count_new()
{
$new = Notifications::find()->where(['is_seen' => 0])->all();
return count($new);
}
public static function return_new(){
return Notifications::find()->where(['is_seen' => 0])->all();
}
public function return_all(){
return Notifications::find()->all();
}
public static function checkst(){
return Notifications::find()->where(['id' => 3])->one();
}
public function return_by_date () {
// write something here.
}
}
If you use all() you obtain a collection of models and then you should refere to
Notifications::return_new()[0]->getAttributes();
otherwise you can
public static function return_new(){
return Notifications::find()->where(['is_seen' => 0])->one();
}
and in this case you can use
$notifications = Notifications::return_new()->getAttributes();
I have a table in my DB called 'member' where I intend to store username, password and all other related info of a user and I want to use those username/password for login instead yii2's default User.php model. I have been trying for almost a day and modified the Member.php model but can't make it work. Every time I use my custom username/password from db, it says username or password is incorrect.
Can anyone please help me out? Thanks in advance. :)
FYI, I have no such field in member table such as authKey or accessToken. I have tried all the related stackoverflow posts but in vein.
Member.php Model
namespace app\models;
use Yii;
use yii\web\IdentityInterface;
class Member extends \yii\db\ActiveRecord implements IdentityInterface
{
public static function tableName()
{
return 'member';
}
public function rules()
{
return [
[['username', 'password', 'first_name', 'last_name', 'role'], 'required'],
[['created_by_date', 'last_modified_by_date'], 'safe'],
[['username', 'password', 'role', 'created_by_id', 'last_modified_by_id'], 'string', 'max' => 50],
[['first_name', 'last_name', 'middle_name', 'phone', 'mobile'], 'string', 'max' => 100],
[['email'], 'string', 'max' => 250],
[['address_line1', 'address_line2', 'address_line3'], 'string', 'max' => 512]
];
}
public function attributeLabels()
{
return [
'id' => 'ID',
'username' => 'Username',
'password' => 'Password',
'first_name' => 'First Name',
'last_name' => 'Last Name',
'middle_name' => 'Middle Name',
'email' => 'Email',
'phone' => 'Phone',
'mobile' => 'Mobile',
'address_line1' => 'Address Line1',
'address_line2' => 'Address Line2',
'address_line3' => 'Address Line3',
'role' => 'Role',
'created_by_id' => 'Created By ID',
'created_by_date' => 'Created By Date',
'last_modified_by_id' => 'Last Modified By ID',
'last_modified_by_date' => 'Last Modified By Date',
];
}
public static function find()
{
return new MemberQuery(get_called_class());
}
public static function findIdentity($id)
{
$dbUser = self::find()
->where([
"id" => $id
])
->one();
if (!count($dbUser)) {
return null;
}
return new static($dbUser);
}
public static function findIdentityByAccessToken($token, $userType = null)
{
$dbUser = self::find()
->where(["accessToken" => $token])
->one();
if (!count($dbUser)) {
return null;
}
return new static($dbUser);
}
public static function findByUsername($username)
{
$dbUser = self::find()
->where(["username" => $username])
->one();
if (!count($dbUser)) {
return null;
}
return $dbUser;
}
public function getId()
{
return $this->id;
}
public function getAuthKey()
{
return $this->authKey;
}
public function validateAuthKey($authKey)
{
return $this->authKey === $authKey;
}
/**
* Validates password
*
* #param string $password password to validate
* #return boolean if password provided is valid for current user
*/
public function validatePassword($password)
{
return $this->password === $password;
}
}
config/web.php
'user' => [
'identityClass' => 'app\models\Member',
'enableAutoLogin' => true,
],
I didnt change the User.php model. Here it is:
namespace app\models;
class User extends \yii\base\Object implements \yii\web\IdentityInterface
{
private static $users = [
'100' => [
'id' => '100',
'username' => 'admin',
'password' => 'admin',
'authKey' => 'test100key',
'accessToken' => '100-token',
],
'101' => [
'id' => '101',
'username' => 'demo',
'password' => 'demo',
'authKey' => 'test101key',
'accessToken' => '101-token',
],
];
/**
* #inheritdoc
*/
public static function findIdentity($id)
{
return isset(self::$users[$id]) ? new static(self::$users[$id]) : null;
}
/**
* #inheritdoc
*/
public static function findIdentityByAccessToken($token, $type = null)
{
foreach (self::$users as $user) {
if ($user['accessToken'] === $token) {
return new static($user);
}
}
return null;
}
/**
* Finds user by username
*
* #param string $username
* #return static|null
*/
public static function findByUsername($username)
{
foreach (self::$users as $user) {
if (strcasecmp($user['username'], $username) === 0) {
return new static($user);
}
}
return null;
}
/**
* #inheritdoc
*/
public function getId()
{
return $this->id;
}
/**
* #inheritdoc
*/
public function getAuthKey()
{
return $this->authKey;
}
/**
* #inheritdoc
*/
public function validateAuthKey($authKey)
{
return $this->authKey === $authKey;
}
/**
* Validates password
*
* #param string $password password to validate
* #return boolean if password provided is valid for current user
*/
public function validatePassword($password)
{
return $this->password === $password;
}
}
You should make sure you change the getUser() method on models/LoginForm.php to use your Member model class, otherwise it will keep validating against the default User model.
public function getUser() {
if ($this->_user === false) {
$this->_user = Member::findByUsername($this->username);
}
return $this->_user;
}
Also, here is an example of my own User model class
namespace app\models;
use Yii;
class User extends \yii\db\ActiveRecord implements \yii\web\IdentityInterface {
const SCENARIO_LOGIN = 'login';
const SCENARIO_CREATE = 'create';
public static function tableName() {
return 'user';
}
public function scenarios() {
$scenarios = parent::scenarios();
$scenarios[self::SCENARIO_LOGIN] = ['username', 'password'];
$scenarios[self::SCENARIO_CREATE] = ['username', 'password', 'authKey'];
return $scenarios;
}
public function rules() {
return [
[['username', 'email'], 'string', 'max' => 45],
[['email'], 'email'],
[['password'], 'string', 'max' => 60],
[['authKey'], 'string', 'max' => 32],
[['username', 'password', 'email'], 'required', 'on' => self::SCENARIO_CREATE],
[['authKey'], 'default', 'on' => self::SCENARIO_CREATE, 'value' => Yii::$app->getSecurity()->generateRandomString()],
[['password'], 'filter', 'on' => self::SCENARIO_CREATE, 'filter' => function($value) {
return Yii::$app->getSecurity()->generatePasswordHash($value);
}],
[['username', 'password'], 'required', 'on' => self::SCENARIO_LOGIN],
[['username'], 'unique'],
[['email'], 'unique'],
[['authKey'], 'unique'],
];
}
public function attributeLabels() {
return [
'id' => 'Id',
'username' => 'Username',
'password' => 'Password',
'email' => 'Email',
'authKey' => 'authKey',
];
}
public static function findIdentity($id) {
return self::findOne($id);
}
public static function findIdentityByAccessToken($token, $type = null) {
throw new NotSupportedException('"findIdentityByAccessToken" is not implemented.');
}
public static function findByUsername($username) {
return static::findOne(['username' => $username]);
}
public function getId() {
return $this->getPrimaryKey();
}
public function getAuthKey() {
return $this->authKey;
}
public function validateAuthKey($authKey) {
return $this->authKey === $authKey;
}
public function validatePassword($password) {
return Yii::$app->getSecurity()->validatePassword($password, $this->password);
}
}
Make sure the methods from IdentityInterface you implement but don't want to use throw an exception, just like i do on the findIdentityByAccessToken method.
You should extend User class with your Member class and set in main config:
[...]
'modules' => [
'user' => [
'class' => 'member class
'modelMap' => [
'User' => 'app\models\member',
More info: yii 2 : override user model
On adding a new record, insert only ID, other fields empty is added.
public function actionSignup()
{
$model = new User();
if(Yii::$app->request->post()) {
$model->id = 122;
$model->username = 'user123';
$model->password = 'pass123';
...
$model->save(false);
}
return $this->render('signup',['model' => $model]);
}
var_dump shows that all necessary data are brought in $model...
User model:
<?php
namespace app\models;
use yii\captcha\Captcha;
use yii\db\ActiveRecord;
class User extends ActiveRecord implements \yii\web\IdentityInterface
{
public $id;
public $username;
public $password;
public $user_fio;
public $user_email;
public $user_group;
public $verifyCode;
private static $users;
public function actions()
{
return [
'captcha' => [
'class' => 'yii\captcha\CaptchaAction',
'fixedVerifyCode' => YII_ENV_TEST ? 'index' : null,
],
];
}
public function rules()
{
return [
[['username', 'user_fio', 'user_email', 'password', 'user_group'], 'required'],
[['username', 'user_fio', 'password'], 'string', 'max' => 70],
[['user_email'], 'string', 'max' => 150],
["verifyCode", "captcha", 'captchaAction' => 'site/captcha'],
];
}
public static function tableName()
{
return '{{users}}';
}
public function attributesLabels()
{
return [
'username' => 'username',
'password' => 'password',
'user_fio' => 'fiouser',
'user_mail' => 'email',
'user_group' => 'group',
'verifyCode' => 'code with image'
];
}
public static function findIdentity($id)
{
$user = Users::find()->where(['id' => $id])->one();
if(!count($user)) return null;
else
return new static($user);
}
public static function findIdentityByAccessToken($token, $type = null)
{
$user = Users::find()->where(['auth_key' => $token])->one();
if(!count($user)) return null;
else
return new static($user);
}
public static function findByUsername($username)
{
$user = Users::find()->where(['username' => $username])->one();
if(!count($user)) return null;
else
return new static ($user);
}
public function getId()
{
return $this->id;
}
public function getAuthKey()
{
return $this->authKey;
}
public function validateAuthKey($authKey)
{
return $this->authKey === $authKey;
}
public function validatePassword($password)
{
return $this->password === $password;
}
}
screenshots table Users:
[Table with emptys fields] http://i.stack.imgur.com/EowUl.jpg
[Table structure] http://i.stack.imgur.com/lpdZM.jpg
I changed nothing, only I added action of registration of the new user
You have declared database fields as public class fields ($id, $username, etc.), so this fields are assigned instead of internal ActiveRecord fields. Try to delete or comment out class public fields.
i want to build a update profile page, and i have 2 mysql table 1. account 2. info, so i want to insert or update the user info table.
this is what i have so far, but its return an error when saving the data "Call to undefined method stdClass::save()"
controller:
public function actionUpdate_profile() {
$model = new UserProfileForm();
$user = Userinfo::model()->findByPk(Yii::app()->user->id);
$model->name = $user->_name;
$model->myurl = $user->myurl;
if (isset($_POST['UserProfileForm'])) {
$model->attributes = $_POST['UserProfileForm'];
if ($model->validate()) {
$model->attributes = $_POST['UserProfileForm'];
$user->name = $model->name;
$user->myurl = $model->myurl;
$user->save();
});
});
$this->render('update_profile', array(
'model' => $model,
'user' => $user,
));
}
model:
class Userinfo extends CActiveRecord {
public static function model($className = __CLASS__) {
return parent::model($className);
}
public function tableName() {
return 'user_info';
}
public function rules() {
return array(
array('email, name, myurl', 'length', 'max' => 255),
);
}
public function attributeLabels() {
return array(
'user_id' => Yii::t('yii', 'Id User'),
'name' => Yii::t('yii', 'First Name'),
'myurl' => Yii::t('yii', 'Last Name'),
);
}
class UserProfileForm extends CFormModel {
public $name;
public $myurl;
public function rules() {
return array(
array('name, myurl', 'required'),
);
}
public function attributeLabels() {
return array(
'name' => Yii::t('yii', 'First Name'),
'myurl' => Yii::t('yii', 'Last Name'),
);
}
}
I know this not best practice but it is concise -
if($user = Userinfo::model()->findByPk(Yii::app()->user->id)) {
//then work with $user here
}