Related
I have two tables. One for Users, one for Equipments.
I managed to make the search for username from other table, but now i want to create an equipment or to update an equipment directly to username, not by user_for_id. Is there any posibilty to do that ? Which would be the steps ? Thank you very much for any guidance.
First table : user_id - primary key, username, password ;
Second table: user_equip_id - primary key, phone_model, phone_model_series, phone_date_acq, nb_sg_model, nb_sg,_date_acq, display_model, display_series, display_date_acq, user_for_id - foreign key to user_id from table1
Controller:
<?php
namespace app\controllers;
use Yii;
use app\models\Equipment;
use app\models\EquipmentSearch;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
use yii\filters\AccessControl;
/**
* EquipmentController implements the CRUD actions for Equipment model.
*/
class EquipmentController extends Controller
{
/**
* {#inheritdoc}
*/
public function behaviors()
{
return [
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'delete' => ['POST'],
],
],
'access' => [
'class' => AccessControl::className(),
'rules' => [
[
'allow' => true,
'roles' => ['#'],
],
],
],
];
}
/**
* Lists all Equipment models.
* #return mixed
*/
public function actionIndex()
{
$searchModel = new EquipmentSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
/**
* Displays a single Equipment model.
* #param integer $id
* #return mixed
* #throws NotFoundHttpException if the model cannot be found
*/
public function actionView($id)
{
return $this->render('view', [
'model' => $this->findModel($id),
]);
}
/**
* Creates a new Equipment model.
* If creation is successful, the browser will be redirected to the 'view' page.
* #return mixed
*/
public function actionCreate()
{
$model = new Equipment();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->user_equip_id]);
}
return $this->render('create', [
'model' => $model,
]);
}
/**
* Updates an existing Equipment model.
* If update is successful, the browser will be redirected to the 'view' page.
* #param integer $id
* #return mixed
* #throws NotFoundHttpException if the model cannot be found
*/
public function actionUpdate($id)
{
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->user_equip_id]);
}
return $this->render('update', [
'model' => $model,
]);
}
/**
* Deletes an existing Equipment model.
* If deletion is successful, the browser will be redirected to the 'index' page.
* #param integer $id
* #return mixed
* #throws NotFoundHttpException if the model cannot be found
*/
public function actionDelete($id)
{
$this->findModel($id)->delete();
return $this->redirect(['index']);
}
/**
* Finds the Equipment model based on its primary key value.
* If the model is not found, a 404 HTTP exception will be thrown.
* #param integer $id
* #return Equipment the loaded model
* #throws NotFoundHttpException if the model cannot be found
*/
protected function findModel($id)
{
if (($model = Equipment::findOne($id)) !== null) {
return $model;
}
throw new NotFoundHttpException('The requested page does not exist.');
}
}
Model :
<?php
namespace app\models;
use Yii;
/**
* This is the model class for table "equipment".
*
* #property int $user_equip_id
* #property string|null $phone_model
* #property string $phone_series
* #property string $phone_date_acq
* #property string $nb_sg_model
* #property string $nb_sg_series
* #property string $nb_sg_date_acq
* #property string $display_model
* #property string $display_series
* #property string $display_date_acq
* #property int $user_for_id
*
* #property User $userFor
*/
class Equipment extends \yii\db\ActiveRecord
{
/**
* {#inheritdoc}
*/
public static function tableName()
{
return 'equipment';
}
/**
* {#inheritdoc}
*/
public function rules()
{
return [
[['phone_series', 'phone_date_acq', 'nb_sg_model', 'nb_sg_series', 'nb_sg_date_acq', 'display_model', 'display_series', 'display_date_acq', 'user_for_id'], 'required'],
[['phone_date_acq', 'nb_sg_date_acq', 'display_date_acq'], 'safe'],
[['user_for_id'], 'integer'],
[['userFor'], 'safe'],
[['phone_model', 'phone_series', 'nb_sg_model', 'nb_sg_series', 'display_model', 'display_series'], 'string', 'max' => 50],
[['user_for_id'], 'exist', 'skipOnError' => true, 'targetClass' => User::className(), 'targetAttribute' => ['user_for_id' => 'user_id']],
[['userFor'], 'string', 'max' => 50],
//[['username'], 'exist', 'skipOnError' => true, 'targetClass' => User::className(), 'targetAttribute' => ['username' => 'username']],
];
}
/**
* {#inheritdoc}
*/
public function attributeLabels()
{
return [
'user_equip_id' => 'User Equip ID',
'phone_model' => 'Phone Model',
'phone_series' => 'Phone Series',
'phone_date_acq' => 'Phone Date',
'nb_sg_model' => 'NB/GS Model',
'nb_sg_series' => 'NB/GS Series',
'nb_sg_date_acq' => 'NB/GS Date',
'display_model' => 'Display Model',
'display_series' => 'Display Series',
'display_date_acq' => 'Display Date',
'user_for_id' => 'User For ID',
'userFor.username' => 'Username',
];
}
/**
* Gets query for [[UserFor]].
*
* #return \yii\db\ActiveQuery|yii\db\ActiveQuery
*/
public function getUserFor()
{
return $this->hasOne(User::className(), ['user_id' => 'user_for_id']);
}
//public function getUsername()
//{
// print_r($equipment->userFor->username);die;
// }
/**
* {#inheritdoc}
* #return EquipmentQuery the active query used by this AR class.
*/
public static function find()
{
return new EquipmentQuery(get_called_class());
}
}
Model Search:
<?php
namespace app\models;
use yii\base\Model;
use yii\data\ActiveDataProvider;
use app\models\Equipment;
/**
* EquipmentSearch represents the model behind the search form of `app\models\Equipment`.
*/
class EquipmentSearch extends Equipment
{
public $userFor;
/**
* {#inheritdoc}
*/
public function rules()
{
return [
[['user_equip_id', 'user_for_id'], 'integer'],
[['phone_model', 'phone_series', 'phone_date_acq', 'nb_sg_model', 'nb_sg_series', 'nb_sg_date_acq', 'display_model', 'display_series', 'display_date_acq'], 'safe'],
[['userFor'], 'safe'],
#[['username'], 'safe'],
];
}
/**
* {#inheritdoc}
*/
public function scenarios()
{
// bypass scenarios() implementation in the parent class
return Model::scenarios();
}
/**
* Creates data provider instance with search query applied
*
* #param array $params
*
* #return ActiveDataProvider
*/
public function search($params)
{
$query = Equipment::find();
$query->joinWith(['userFor']);
// add conditions that should always apply here
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
$dataProvider->sort->attributes['username'] = [
'asc' => ['user.username' => SORT_ASC],
'desc' => ['user.username' => SORT_DESC],
];
$this->load($params);
if (!$this->validate()) {
// uncomment the following line if you do not want to return any records when validation fails
// $query->where('0=1');
return $dataProvider;
}
// grid filtering conditions
$query->andFilterWhere([
'user_equip_id' => $this->user_equip_id,
'phone_date_acq' => $this->phone_date_acq,
'nb_sg_date_acq' => $this->nb_sg_date_acq,
'display_date_acq' => $this->display_date_acq,
'user_for_id' => $this->user_for_id,
]);
$query->andFilterWhere(['like', 'phone_model', $this->phone_model])
->andFilterWhere(['like', 'phone_series', $this->phone_series])
->andFilterWhere(['like', 'nb_sg_model', $this->nb_sg_model])
->andFilterWhere(['like', 'nb_sg_series', $this->nb_sg_series])
->andFilterWhere(['like', 'display_model', $this->display_model])
->andFilterWhere(['like', 'display_series', $this->display_series])
->andFilterWhere(['like', 'user.username', $this->userFor]);
return $dataProvider;
}
}
Thank you in advance for any guidance or help.
I have users table containing : PK - id, username, password.
i have three tables ( laptop, display, phone) - id - FK, series, model
I have userequipmentmapping table containing : id - PK , user_id - FK( id from users table), laptop_id - FK (id from laptop table), phone_id - FK (id from phone table), display_id(id from dislpay table), start_date, end_date.
I want to search by user in my gridview from UserEquipmentMapping, but don't know where should i implement the search model, considering the username is passed from the users table by foreign key.
If you have any suggestions are appreciated. Thank You in advance !
Controller :
<?php
namespace app\controllers;
use Yii;
use app\models\UserEquipmentMapping;
use app\models\UserequipmentmappingSearch;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
use app\models\User;
use app\models\Laptop;
use app\models\Phone;
use app\models\Display;
/**
* UserequipmentmappingController implements the CRUD actions for UserEquipmentMapping model.
*/
class UserequipmentmappingController extends Controller
{
/**
* {#inheritdoc}
*/
public function behaviors()
{
return [
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'delete' => ['POST'],
],
],
];
}
/**
* Lists all UserEquipmentMapping models.
* #return mixed
*/
public function actionIndex()
{
$usermodel = new UserEquipmentMapping();
$userquery = $usermodel->getUsers();
$displaymodel = new UserEquipmentMapping();
$displayquery = $displaymodel->getDisplays();
$phonemodel = new UserEquipmentMapping();
$phonequery = $phonemodel->getPhones();
$laptopmodel = new UserEquipmentMapping();
$laptopquery = $laptopmodel->getLaptops();
#foreach($query as $q)
# print_r($q);
#
# die;
$searchModel = new UserequipmentmappingSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
'userquery' => $userquery,
'displayquery' => $displayquery,
'laptopquery'=> $laptopquery,
'phonequery'=> $phonequery,
]);
}
/**
* Displays a single UserEquipmentMapping model.
* #param integer $id
* #return mixed
* #throws NotFoundHttpException if the model cannot be found
*/
public function actionView($id)
{
return $this->render('view', [
'model' => $this->findModel($id),
]);
}
/**
* Creates a new UserEquipmentMapping model.
* If creation is successful, the browser will be redirected to the 'view' page.
* #return mixed
*/
public function actionCreate()
{
$model = new UserEquipmentMapping();
$usermodel = User::find()->all();
$laptopmodel = Laptop::find()->all();
$phonemodel = Phone::find()->all();
$displaymodel = Display::find()->all();
#print_r(Yii::$app->request->post()); die;
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
}
return $this->render('create', [
'model' => $model,
'usermodel' => $usermodel,
'laptopmodel' => $laptopmodel,
'phonemodel' => $phonemodel,
'displaymodel' => $displaymodel,
]);
}
/**
* Updates an existing UserEquipmentMapping model.
* If update is successful, the browser will be redirected to the 'view' page.
* #param integer $id
* #return mixed
* #throws NotFoundHttpException if the model cannot be found
*/
public function actionUpdate($id)
{
$model = $this->findModel($id);
$usermodel = User::find()->all();
$laptopmodel = Laptop::find()->all();
$phonemodel = Phone::find()->all();
$displaymodel = Display::find()->all();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
}
return $this->render('update', [
'model' => $model,
'usermodel' => $usermodel,
'laptopmodel' => $laptopmodel,
'phonemodel' => $phonemodel,
'displaymodel' => $displaymodel,
]);
}
/**
* Deletes an existing UserEquipmentMapping model.
* If deletion is successful, the browser will be redirected to the 'index' page.
* #param integer $id
* #return mixed
* #throws NotFoundHttpException if the model cannot be found
*/
public function actionDelete($id)
{
$this->findModel($id)->delete();
return $this->redirect(['index']);
}
/**
* Finds the UserEquipmentMapping model based on its primary key value.
* If the model is not found, a 404 HTTP exception will be thrown.
* #param integer $id
* #return UserEquipmentMapping the loaded model
* #throws NotFoundHttpException if the model cannot be found
*/
protected function findModel($id)
{
if (($model = UserEquipmentMapping::findOne($id)) !== null) {
return $model;
}
throw new NotFoundHttpException('The requested page does not exist.');
}
}
Model :
<?php
namespace app\models;
use Yii;
use app\models\User;
use app\models\UserQuery;
use yii\db\ActiveQuery;
/**
* This is the model class for table "user_equipment_mapping".
*
* #property int $id
* #property int $user_id
* #property int|null $laptop_id
* #property int|null $phone_id
* #property int|null $display_id
* #property string|null $start_date
* #property string|null $stop_date
*
* #property Display $display
* #property Laptop $laptop
* #property Phone $phone
* #property User $user
*/
class UserEquipmentMapping extends \yii\db\ActiveRecord
{
/**
* {#inheritdoc}
*/
public static function tableName()
{
return 'user_equipment_mapping';
}
/**
* {#inheritdoc}
*/
public function rules()
{
return [
[['user_id'], 'required'],
[['user_id', 'laptop_id', 'phone_id', 'display_id'], 'integer'],
[['start_date', 'stop_date'], 'safe'],
[['display_id'], 'exist', 'skipOnError' => true, 'targetClass' => Display::className(), 'targetAttribute' => ['display_id' => 'id']],
[['laptop_id'], 'exist', 'skipOnError' => true, 'targetClass' => Laptop::className(), 'targetAttribute' => ['laptop_id' => 'id']],
[['phone_id'], 'exist', 'skipOnError' => true, 'targetClass' => Phone::className(), 'targetAttribute' => ['phone_id' => 'id']],
[['user_id'], 'exist', 'skipOnError' => true, 'targetClass' => User::className(), 'targetAttribute' => ['user_id' => 'id']],
];
}
/**
* {#inheritdoc}
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'user_id' => 'User ID',
'laptop_id' => 'Laptop ID',
'phone_id' => 'Phone ID',
'display_id' => 'Display ID',
'start_date' => 'Start Date',
'stop_date' => 'Stop Date',
];
}
/**
* Gets query for [[Display]].
*
* #return \yii\db\ActiveQuery|DisplayQuery
*/
public function getDisplay()
{
return $this->hasOne(Display::className(), ['id' => 'display_id']);
}
/**
* Gets query for [[Laptop]].
*
* #return \yii\db\ActiveQuery|LaptopQuery
*/
public function getLaptop()
{
return $this->hasOne(Laptop::className(), ['id' => 'laptop_id']);
}
/**
* Gets query for [[Phone]].
*
* #return \yii\db\ActiveQuery|PhoneQuery
*/
public function getPhone()
{
return $this->hasOne(Phone::className(), ['id' => 'phone_id']);
}
/**
* Gets query for [[User]].
*
* #return \yii\db\ActiveQuery|UserQuery
*/
public function getUser()
{
return $this->hasOne(User::className(), ['id' => 'user_id']);
}
public function getUsers()
{
return $this->hasMany(User::className(),['user_id', 'id']);
}
public function getLaptops()
{
return $this->hasMany(Laptop::className(),['laptop_id', 'id']);
}
public function getDisplays()
{
return $this->hasMany(Display::className(),['dislpay_id', 'id']);
}
public function getPhones()
{
return $this->hasMany(Phone::className(),['phone_id', 'id']);
}
/**
* {#inheritdoc}
* #return UserEquipmentMappingQuery the active query used by this AR class.
*/
public static function find()
{
return new UserEquipmentMappingQuery(get_called_class());
}
}
ModelSearch :
<?php
namespace app\models;
use yii\base\Model;
use yii\data\ActiveDataProvider;
use app\models\UserEquipmentMapping;
/**
* UserequipmentmappingSearch represents the model behind the search form of `app\models\UserEquipmentMapping`.
*/
class UserequipmentmappingSearch extends UserEquipmentMapping
{
/**
* {#inheritdoc}
*/
public function rules()
{
return [
[['id', 'user_id', 'laptop_id', 'phone_id', 'display_id'], 'integer'],
[['start_date', 'stop_date'], 'safe'],
];
}
/**
* {#inheritdoc}
*/
public function scenarios()
{
// bypass scenarios() implementation in the parent class
return Model::scenarios();
}
/**
* Creates data provider instance with search query applied
*
* #param array $params
*
* #return ActiveDataProvider
*/
public function search($params)
{
$query = UserEquipmentMapping::find();
// add conditions that should always apply here
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
$this->load($params);
if (!$this->validate()) {
// uncomment the following line if you do not want to return any records when validation fails
// $query->where('0=1');
return $dataProvider;
}
// grid filtering conditions
$query->andFilterWhere([
'id' => $this->id,
'user_id' => $this->user_id,
'laptop_id' => $this->laptop_id,
'phone_id' => $this->phone_id,
'display_id' => $this->display_id,
'start_date' => $this->start_date,
'stop_date' => $this->stop_date,
]);
return $dataProvider;
}
}
Index :
<?php
use yii\helpers\Html;
use yii\grid\GridView;
/* #var $this yii\web\View */
/* #var $searchModel app\models\UserequipmentmappingSearch */
/* #var $dataProvider yii\data\ActiveDataProvider */
$this->title = 'User Equipment Mappings';
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="user-equipment-mapping-index">
<h1><?= Html::encode($this->title) ?></h1>
<p>
<?= Html::a('Create User Equipment Mapping', ['create'], ['class' => 'btn btn-success']) ?>
</p>
<?php // echo $this->render('_search', ['model' => $searchModel]); ?>
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'formatter' => [
'class' => 'yii\i18n\Formatter',
'nullDisplay' => '-',],
'columns' => [
['class' => 'yii\grid\SerialColumn'],
#'id',
'user.username',
#'laptop.laptop_model',
'laptop.laptop_series',
#'laptop_id',
#'phone.phone_model',
'phone.phone_series',
#'phone_id',
#'display.display_model',
'display.display_series',
#'display_id',
'start_date',
'stop_date',
['class' => 'yii\grid\ActionColumn'],
],
]); ?>
</div>
Uncomment in your index view _search view. There are all fields from UserequipmentmappingSearch model. You can replace input fields with select fields for user, laptop and etc. Search model will do the other thing, all is in search function that fills your dataprovider
I have 2 tables with strategy and risk_colors .
I generated Model and CRUD with GII and modified it just a little to get risk_value column in my GridView widget.
Here is my Strategy.php
<?php
namespace backend\models;
use Yii;
use yii\db\ActiveRecord;
use yii\helpers\Url;
use yii\helpers\Html;
use yii\helpers\ArrayHelper;
use yii\db\Expression;
/**
* This is the model class for table "strategy".
*
* #property int $id
* #property string $strategy_title
* #property string $strategy_description
* #property string $strategy_current_money
* #property int $risk_colors_id
*
* #property SelectedStrategies[] $selectedStrategies
* #property RiskColors $riskColors
*/
class Strategy extends \yii\db\ActiveRecord
{
/**
* {#inheritdoc}
*/
public static function tableName()
{
return 'strategy';
}
/**
* {#inheritdoc}
*/
public function rules()
{
return [
[['strategy_title', 'strategy_description', 'strategy_current_money', 'risk_colors_id'], 'required'],
[['strategy_current_money', 'risk_colors_id'], 'integer'],
[['strategy_title'], 'string', 'max' => 255],
[['strategy_description'], 'string', 'max' => 2055],
[['risk_colors_id'], 'exist', 'skipOnError' => true, 'targetClass' => RiskColors::className(), 'targetAttribute' => ['risk_colors_id' => 'id']],
];
}
/**
* {#inheritdoc}
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'strategy_title' => 'Strategy Title',
'strategy_description' => 'Strategy Description',
'strategy_current_money' => 'Strategy Current Money',
'risk_colors_id' => 'Risk Color ID',
'riskValue' => Yii::t('app', 'Risk'),
'colorNumber' => 'Color Number',
];
}
/**
* #return \yii\db\ActiveQuery
*/
public function getSelectedStrategies()
{
return $this->hasMany(SelectedStrategies::className(), ['strategy_id' => 'id']);
}
/**
* #return \yii\db\ActiveQuery
*/
public function getRiskColors()
{
return $this->hasOne(RiskColors::className(), ['id' => 'risk_colors_id']);
}
/**
* #return risk value
*/
public function getRiskValue()
{
return $this->riskColors->risk_value;
}
/**
* #return Get risk value list for dropdown
*/
public function getRiskValueList()
{
$droptions = RiskColors::find()->asArray()->all();
return ArrayHelper::map($droptions, 'id', 'risk_value');
}
/**
* #return Get risk value list for dropdown
*/
public function getColorNumberList()
{
$droptions = RiskColors::find()->asArray()->all();
return ArrayHelper::map($droptions, 'id', 'color_number');
}
}
here is my index.php.
After all i got risk_value column in my GridView, but it looks like i cant sort my table by this field. Here is .
Here is my Search Model
So my question is what should i do to make this field sortable?
In your StrategySearch.php
public function search($params)
{
$query = Strategy::find()->joinWith(['riskColors']);
// add conditions that should always apply here
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
$dataProvider->sort->attributes['risk_colors_id'] = [
'asc' => ['risk_colors.risk_value' => SORT_ASC],
'desc' => ['risk_colors.risk_value' => SORT_DESC],
];
$this->load($params);
if (!$this->validate()) {
// uncomment the following line if you do not want to return any records when validation fails
// $query->where('0=1');
return $dataProvider;
}
// grid filtering conditions
$query->andFilterWhere([
'id' => $this->id,
'strategy_current_money' => $this->strategy_current_money,
// 'risk_colors_id' => $this->risk_colors_id,
'risk_colors.risk_value' => $this->risk_colors_id
]);
$query->andFilterWhere(['like', 'strategy_title', $this->strategy_title])
->andFilterWhere(['like', 'strategy_description', $this->strategy_description]);
return $dataProvider;
}
Refere GridView Sorting
i'm trying to copy some values from a table that contain a column that relates to another table to copy too.
the problem is that if i call the function createNew() of the model Email.php
<?php
namespace app\models;
use Yii;
/**
* This is the model class for table "email".
*
* #property integer $id
* #property integer $provider_id
* #property integer $sender_id
* #property string $recipient
* #property string $name
* #property string $cc
* #property string $ccn
* #property string $subject
* #property string $body
* #property integer $type
* #property string $created
*
* #property Emailaccount $sender
* #property Provider $provider
*/
class Email extends \yii\db\ActiveRecord
{
/**
* #inheritdoc
*/
public static function tableName()
{
return 'email';
}
/**
* #inheritdoc
*/
public function rules()
{
return [
[['provider_id', 'sender_id', 'name', 'subject', 'body', 'type'], 'required'],
[['provider_id', 'sender_id', 'type'], 'integer'],
[['body'], 'string'],
[['created'], 'safe'],
[['recipient'], 'string', 'max' => 200],
[['name', 'cc', 'ccn', 'subject'], 'string', 'max' => 100],
[['sender_id'], 'exist', 'skipOnError' => true, 'targetClass' => Emailaccount::className(), 'targetAttribute' => ['sender_id' => 'id']],
[['provider_id'], 'exist', 'skipOnError' => true, 'targetClass' => Provider::className(), 'targetAttribute' => ['provider_id' => 'id']],
];
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'provider_id' => 'Provider ID',
'sender_id' => 'Sender ID',
'recipient' => 'Recipient',
'name' => 'Name',
'cc' => 'Cc',
'ccn' => 'Ccn',
'subject' => 'Subject',
'body' => 'Body',
'type' => 'Type',
'created' => 'Created',
];
}
/**
* #return \yii\db\ActiveQuery
*/
public function getSender()
{
return $this->hasOne(Emailaccount::className(), ['id' => 'sender_id']);
}
/**
* #return \yii\db\ActiveQuery
*/
public function getProvider()
{
return $this->hasOne(Provider::className(), ['id' => 'provider_id']);
}
public function createNew ($id,$new_id){
$model = Email::findOne(['id'=>$id]);
$model->id = null;
$model->provider_id = $new_id;
$model->isNewRecord = true;
$model->save();
return $model->id;
}
}
from the model Service.php
namespace app\models;
use Yii;
use app\models\Email;
use app\models\Question;
/**
* This is the model class for table "service".
*
* #property integer $id
* #property integer $provider_id
* #property string $token
* #property string $name
* #property string $description
* #property integer $parent_id
* #property string $reference
* #property integer $reference_id
* #property integer $depth
* #property integer $isleaf
* #property string $color
* #property string $icon
* #property integer $type
* #property string $type_label
* #property integer $totem_reference_id
*
* #property Service $parent
* #property Service[] $services
*/
class Service extends \yii\db\ActiveRecord
{
/**
* #inheritdoc
*/
public static function tableName()
{
return 'service';
}
/**
* #inheritdoc
*/
public function rules()
{
return [
[['provider_id', 'token', 'name'], 'required'],
[['provider_id', 'parent_id', 'reference_id', 'depth', 'isleaf', 'type', 'totem_reference_id'], 'integer'],
[['reference', 'color'], 'string'],
[['token', 'type_label'], 'string', 'max' => 45],
[['name', 'description'], 'string', 'max' => 255],
[['icon'], 'string', 'max' => 30],
[['token'], 'unique'],
[['parent_id'], 'exist', 'skipOnError' => true, 'targetClass' => Service::className(), 'targetAttribute' => ['parent_id' => 'id']],
];
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'provider_id' => 'Provider ID',
'token' => 'Token',
'name' => 'Name',
'description' => 'Description',
'parent_id' => 'Parent ID',
'reference' => 'Reference',
'reference_id' => 'Reference ID',
'depth' => 'Depth',
'isleaf' => 'Isleaf',
'color' => 'Color',
'icon' => 'Icon',
'type' => 'Type',
'type_label' => 'Type Label',
'totem_reference_id' => 'Totem Reference ID',
];
}
/**
* #return \yii\db\ActiveQuery
*/
public function getParent()
{
return $this->hasOne(Service::className(), ['id' => 'parent_id']);
}
/**
* #return \yii\db\ActiveQuery
*/
public function getServices()
{
return $this->hasMany(Service::className(), ['parent_id' => 'id']);
}
public function mostraService($id,$new_id){
$service = Service::find()
->where(['provider_id'=>$id])
->all();
foreach ($service as $s) {
if ($s->parent_id==NULL) {
$o_id= $s->id; //ID ORIGINALE
$s->id= null;
$s->token= Yii::$app->getSecurity()->generateRandomString(45);
$s->isNewRecord = true;
$s->provider_id = $new_id; //ID_NUOVO
$s->save();
$p_id=$s->id;
$copy = $this->recursiveCopy($o_id,$new_id,$p_id);
} else {
//do something
}
}
}
public function recursiveCopy ($id_s,$id_pr,$id_p){
$children = Service::find()
->where(['parent_id'=>$id_s])
->all();
foreach ($children as $c) {
if ($c->reference == null){
$o_id=$c->id;
$c->id= null;
$c->token= Yii::$app->getSecurity()->generateRandomString(45);
$c->isNewRecord = true;
$c->parent_id = $id_p;
$c->provider_id = $id_pr;
$c->save();
$c_id=$c->id;
$copy = $this->recursiveCopy($o_id,$id_pr,$c_id);
}else {
if ($c->reference =='email') {
$email = new Email();
$e_id=$email->createNew($c->reference_id, $id_pr);
$c->id= null;
$c->token = Yii::$app->getSecurity()->generateRandomString(45);
$c->reference_id = $e_id;
$c->provider_id = $id_pr;
$c->parent_id = $id_p;
$c->isNewRecord = true;
$c->save();
} else if ($c->reference =='question'){
$question = new Question();
$q_id = $question->createNew($c->reference_id, $id_pr);
} else {
$c->id= null;
$c->token = Yii::$app->getSecurity()->generateRandomString(45);
$c->reference_id = $id_p;
$c->provider_id = $id_pr;
$c->parent_id = $id_p;
$c->isNewRecord = true;
$c->save();
}
}
}
}
}
it work perfectly but if i call in the same way in the Question.php
namespace app\models;
use Yii;
use app\models\Email;
/**
* This is the model class for table "question".
*
* #property integer $id
*#property integer $provider_id
* #property string $title
* #property string $description
* #property string $children
* #property integer $parent_id
* #property string $reference
* #property integer $reference_id
* #property integer $depth
* #property integer $type
*
* #property Provider $provider
* #property Question $parent
* #property Question[] $questions
*/
class Question extends \yii\db\ActiveRecord
{
/**
* #inheritdoc
*/
public static function tableName()
{
return 'question';
}
/**
* #inheritdoc
*/
public function rules()
{
return [
[['provider_id', 'title'], 'required'],
[['provider_id', 'parent_id', 'reference_id', 'depth', 'type'], 'integer'],
[['reference'], 'string'],
[['title'], 'string', 'max' => 150],
[['description'], 'string', 'max' => 1000],
[['children'], 'string', 'max' => 300],
[['provider_id'], 'exist', 'skipOnError' => true, 'targetClass' => Provider::className(), 'targetAttribute' => ['provider_id' => 'id']],
[['parent_id'], 'exist', 'skipOnError' => true, 'targetClass' => Question::className(), 'targetAttribute' => ['parent_id' => 'id']],
];
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'provider_id' => 'Provider ID',
'title' => 'Title',
'description' => 'Description',
'children' => 'Children',
'parent_id' => 'Parent ID',
'reference' => 'Reference',
'reference_id' => 'Reference ID',
'depth' => 'Depth',
'type' => 'Type',
];
}
/**
* #return \yii\db\ActiveQuery
*/
public function getProvider()
{
return $this->hasOne(Provider::className(), ['id' => 'provider_id']);
}
/**
* #return \yii\db\ActiveQuery
*/
public function getParent()
{
return $this->hasOne(Question::className(), ['id' => 'parent_id']);
}
/**
* #return \yii\db\ActiveQuery
*/
public function getQuestions()
{
return $this->hasMany(Question::className(), ['parent_id' => 'id']);
}
public function createNew ($id,$new_id){
$model = Question::findOne(['id'=>$id]);
$model->id= null;
$model->provider_id = $new_id;
$model->isNewRecord = true;
$model->save();
$child= explode(",", $model->children);
$sons= '';
foreach ($child as $c) {
$model_c = Question::findOne(['id'=>$c]);
$email = new Email();
$e_id=$email->createNew($model_c->reference_id,$new_id);
$model_c->id= null;
$model_c->provider_id = $new_id;
$model_c->parent_id = $model->id;
$model_c->isNewRecord = true;
$model_c->save();
$sons=$sons.$model_c->id.',';
}
$model->children =$sons;
}
}
it pass a null value and of course throw an exception.
exception 1 exception 2
i tried to echo the value before pass it to the function and it print the right value. i really don't understand, someone can help me?
The problem is you are not checking if Model::findOne() has actually returned a valid result model. It could be false / null if the record with $id doesn't exist.
The second error you are getting usually happens in following case:
$object = null;
$object->prop = 'a value';
aka whey you try to set a value of an object property which doesn't exist.
And your first error message is saying that above case is true.
app\models\Email::createNew(null, 51) <-- notice the null here
So when you are finding a model always check before using it. You can do following:
foreach ($child as $c) {
$model_c = Question::findOne(['id'=>$c]);
if( $model_c ) { // check the model is valid
$email = new Email();
$e_id=$email->createNew($model_c->reference_id,$new_id);
$model_c->id= null;
$model_c->provider_id = $new_id;
$model_c->parent_id = $model->id;
$model_c->isNewRecord = true;
$model_c->save();
$sons=$sons.$model_c->id.',';
}
}
Just showed you one, do the rest. :)
I have user, role tables and a junction table role_user for many to many relationship between these tables.
Timestamp and Blameable behaviours works fine for user and role tables but i want to add these behaviours to my junction table too.
My models are;
User.php
namespace backend\models;
use yii\behaviors\BlameableBehavior;
use yii\behaviors\TimestampBehavior;
use yii\db\ActiveQuery;
use yii\db\ActiveRecord;
use yii\helpers\ArrayHelper;
/**
* This is the model class for table "user".
*
* #property integer $id
* #property string $username
* #property string $auth_key
* #property string $password_hash
* #property string $password_reset_token
* #property string $email
* #property integer $status
* #property integer $created_at
* #property integer $updated_at
* #property string $name
* #property string $surname
* #property integer $role_id
*/
class User extends ActiveRecord {
const STATUS_DELETED = 0;
const STATUS_ACTIVE = 10;
public static function getStates() {
return ArrayHelper::map([
['id' => User::STATUS_ACTIVE, 'name' => 'Active'],
['id' => User::STATUS_DELETED, 'name' => 'Deleted'],
], 'id', 'name');
}
/**
* #inheritdoc
*/
public function behaviors() {
return [
TimestampBehavior::className(),
BlameableBehavior::className()
];
}
/**
* #inheritdoc
*/
public static function tableName() {
return 'user';
}
/**
* #inheritdoc
*/
public function rules() {
return [
[['username', 'auth_key', 'password_hash', 'email'], 'required'],
[['status', 'created_at', 'updated_at', 'created_by', 'updated_by'], 'integer'],
[['username', 'password_hash', 'password_reset_token', 'email', 'name', 'surname'], 'string', 'max' => 255],
[['auth_key'], 'string', 'max' => 32],
[['email'], 'unique'],
[['password_reset_token'], 'unique'],
[['username'], 'unique']
];
}
/**
* #inheritdoc
*/
public function attributeLabels() {
return [
'id' => 'ID',
'username' => 'Username',
'auth_key' => 'Auth Key',
'password_hash' => 'Password Hash',
'password_reset_token' => 'Password Reset Token',
'email' => 'Email',
'status' => 'Status',
'created_at' => 'Created At',
'updated_at' => 'Updated At',
'created_by' => 'Created By',
'updated_by' => 'Updated By',
'name' => 'Name',
'surname' => 'Surname',
'roles' => 'Roles',
];
}
/**
* #return ActiveQuery
*/
public function getRoles() {
return $this->hasMany(Role::className(), ['id' => 'role_id'])
->viaTable(RoleUser::tableName(), ['user_id' => 'id']);
}
}
Role.php
namespace backend\models;
use yii\behaviors\BlameableBehavior;
use yii\behaviors\TimestampBehavior;
use yii\db\ActiveQuery;
use yii\db\ActiveRecord;
use yii\helpers\ArrayHelper;
/**
* This is the model class for table "role".
*
* #property integer $id
* #property string $name
* #property integer $status
* #property string $created_at
* #property string $updated_at
*
* #property User[] $users
*/
class Role extends ActiveRecord {
const STATUS_DELETED = 0;
const STATUS_ACTIVE = 10;
public static function getStates() {
return ArrayHelper::map([
['id' => Role::STATUS_ACTIVE, 'name' => 'Active'],
['id' => Role::STATUS_DELETED, 'name' => 'Deleted'],
], 'id', 'name');
}
/**
* #inheritdoc
*/
public function behaviors() {
return [
TimestampBehavior::className(),
BlameableBehavior::className()
];
}
/**
* #inheritdoc
*/
public static function tableName() {
return 'role';
}
/**
* #inheritdoc
*/
public function rules() {
return [
[['status', 'created_at', 'updated_at', 'created_by', 'updated_by'], 'integer'],
[['name'], 'string', 'max' => 255]
];
}
/**
* #inheritdoc
*/
public function attributeLabels() {
return [
'id' => 'ID',
'name' => 'Name',
'status' => 'Status',
'created_at' => 'Created At',
'updated_at' => 'Updated At',
'created_by' => 'Created By',
'updated_by' => 'Updated By',
];
}
/**
* #return ActiveQuery
*/
public function getUsers() {
return $this->hasMany(User::className(), ['role_id' => 'id']);
}
}
RoleUser.php
<?php
namespace backend\models;
use yii\behaviors\BlameableBehavior;
use yii\behaviors\TimestampBehavior;
use yii\db\ActiveQuery;
use yii\db\ActiveRecord;
/**
* This is the model class for table "role_user".
*
* #property integer $id
* #property integer $user_id
* #property integer $role_id
*
* #property Role $role
* #property User $user
*/
class RoleUser extends ActiveRecord {
/**
* #inheritdoc
*/
public function behaviors() {
return [
TimestampBehavior::className(),
BlameableBehavior::className()
];
}
/**
* #inheritdoc
*/
public static function tableName() {
return 'role_user';
}
/**
* #inheritdoc
*/
public function rules() {
return [
[['user_id', 'role_id'], 'required'],
[['user_id', 'role_id', 'status', 'created_at', 'updated_at', 'created_by', 'updated_by'], 'integer'],
];
}
/**
* #inheritdoc
*/
public function attributeLabels() {
return [
'id' => 'ID',
'user_id' => 'User ID',
'role_id' => 'Role ID',
'created_at' => 'Created At',
'updated_at' => 'Updated At',
'created_by' => 'Created By',
'updated_by' => 'Updated By',
];
}
/**
* #return ActiveQuery
*/
public function getRole() {
return $this->hasOne(Role::className(), ['id' => 'role_id']);
}
/**
* #return ActiveQuery
*/
public function getUser() {
return $this->hasOne(User::className(), ['id' => 'user_id']);
}
}
While i am linking a role to user iam using link method of ActiveRecord:
$user->link('roles', Role::findOne($role_id));
Is there a better way to link these models with these behaviours or should i do the linking via creating an instance from RoleUser model?
Thanks in advance.
If you want Yii to work with your RoleUser class inside link method then you should define relation using via not viaTable.
Declare additional relation:
User.php
public function getRoleLinks()
{
return $this->hasMany(UserRole::className(), ['user_id' => 'id']);
}
And modify your user->role relation:
public function getRoles() {
return $this->hasMany(Role::className(), ['id' => 'role_id'])
->via('roleLinks');
}
If you are using viaTable then yii will directly insert new record into user_role without instantiating of UserRole class.
p.s. and vice versa if you want to call $role->link('users', $user)