yii2 function issue called with null value - php

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. :)

Related

Show Related Data in View Yii 2

I'm new in Yii 2, and I'm creating an inventory system for the library of my school, but I had a problem.
First, I have a relation like this:
I want to show all the adqs (a unique number for each book - that way we don't need to capture the book again for every copy) of a book in his view, but only the adqs related to the book id obviously at the bottom.
My View:
<?php
use yii\helpers\Html;
use yii\widgets\DetailView;
use yii\helpers\Url;
use yii\grid\GridView;
/* #var $this yii\web\View */
/* #var $model app\models\Libros */
/* #var $searchModel app\models\LibrosSearch */
/* #var $dataProvider yii\data\ActiveDataProvider */
$this->title = $model->lib_titulo;
$this->params['breadcrumbs'][] = ['label' => 'Libros', 'url' => ['index']];
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="libros-view">
<h1><?= Html::encode($this->title) ?></h1>
<p>
<?= Html::a('Modificar', ['update', 'id' => $model->lib_id], ['class' => 'btn btn-primary']) ?>
<?= Html::a('Borrar', ['delete', 'id' => $model->lib_id], [
'class' => 'btn btn-danger',
'data' => [
'confirm' => 'Are you sure you want to delete this item?',
'method' => 'post',
],
]) ?>
</p>
<div class="row" align="center">
<?php
if ($model->lib_image_web_filename!='') {
echo '<br /><p><img width="500" src="'.Url::to('#web/', true). '/uploads/libros/'.$model->lib_image_web_filename.'"></p>';
}
?>
</div>
<div class="row" style="
text-align: center;
font: normal normal bold 15px/1 'lato';
color: rgba(7,7,7,1);
text-align: center;
">
<?= DetailView::widget([
'model' => $model,
'attributes' => [
'lib_id',
'lib_titulo',
'lib_autor',
//'lib_edicion',
'editorialNombre',
'ubicacionNombre',
'lib_isbn',
'lib_clasificacion',
'lib_seccion',
//'lib_image_src_filename',
//'lib_image_web_filename',
],
]) ?>
</div>
</div>
My Controller (LibrosController):
<?php
namespace backend\controllers;
use Yii;
use app\models\Libros;
use app\models\LibrosSearch;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
use yii\web\UploadedFile;
/**
* LibrosController implements the CRUD actions for Libros model.
*/
class LibrosController extends Controller
{
/**
* #inheritdoc
*/
public function behaviors()
{
return [
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'delete' => ['POST'],
],
],
];
}
/**
* Lists all Libros models.
* #return mixed
*/
public function actionIndex()
{
$searchModel = new LibrosSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
/**
* Displays a single Libros model.
* #param integer $id
* #return mixed
* #throws NotFoundHttpException if the model cannot be found
*/
public function actionCreate()
{
$model = new Libros();
if ($model->load(Yii::$app->request->post())) {
$image = UploadedFile::getInstance($model, 'image');
if (!is_null($image)) {
$model->lib_image_src_filename = $image->name;
$ext = end((explode(".", $image->name)));
// generate a unique file name to prevent duplicate filenames
$model->lib_image_web_filename = Yii::$app->security->generateRandomString().".{$ext}";
// the path to save file, you can set an uploadPath
// in Yii::$app->params (as used in example below)
Yii::$app->params['uploadPath'] = Yii::$app->basePath . '/web/uploads/libros/';
$path = Yii::$app->params['uploadPath'] . $model->lib_image_web_filename;
$image->saveAs($path);
}
if ($model->save()) {
return $this->redirect(['view', 'id' => $model->lib_id]);
} else {
var_dump ($model->getErrors()); die();
}
}
return $this->render('create', [
'model' => $model,
]);
}
/**
* Updates an existing Libros 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())) {
$image = UploadedFile::getInstance($model, 'image');
if (!is_null($image)) {
$model->lib_image_src_filename = $image->name;
$ext = explode(".", $image->name);
$ext_final = end($ext);
// generate a unique file name to prevent duplicate filenames
$model->lib_image_web_filename = Yii::$app->security->generateRandomString().".{$ext_final}";
// the path to save file, you can set an uploadPath
// in Yii::$app->params (as used in example below)
Yii::$app->params['uploadPath'] = Yii::$app->basePath . '/web/uploads/libros/';
$path = Yii::$app->params['uploadPath'] . $model->lib_image_web_filename;
$image->saveAs($path);
}
if ($model->save()) {
return $this->redirect(['view', 'id' => $model->lib_id]);
} else {
var_dump ($model->getErrors()); die();
}
}
return $this->render('create', [
'model' => $model,
]);
}
/**
* Deletes an existing Libros 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 Libros model based on its primary key value.
* If the model is not found, a 404 HTTP exception will be thrown.
* #param integer $id
* #return Libros the loaded model
* #throws NotFoundHttpException if the model cannot be found
*/
protected function findModel($id)
{
if (($model = Libros::findOne($id)) !== null) {
return $model;
}
throw new NotFoundHttpException('The requested page does not exist.');
}
}
My Model (Libros.php):
<?php
namespace app\models;
use Yii;
/**
* This is the model class for table "libros".
*
* #property int $lib_id
* #property string $lib_titulo
* #property string $lib_autor
* #property string $lib_edicion
* #property int $lib_ubi
* #property int $lib_editorial_id
* #property string $lib_isbn
* #property string $lib_clasificacion
* #property string $lib_seccion
* #property string $lib_image_src_filename
* #property string $lib_image_web_filename
*
* #property Adq[] $adqs
* #property Editorial $libEditorial
* #property Ubicacion $libUbi
* #property LibrosCarreras[] $librosCarreras
* #property Carreras[] $licCarreras
*/
class Libros extends \yii\db\ActiveRecord
{
const PERMISSIONS_PRIVATE = 10;
const PERMISSIONS_PUBLIC = 20;
public $image;
/**
* #inheritdoc
*/
public static function tableName()
{
return 'libros';
}
/**
* #inheritdoc
*/
public function rules()
{
return [
[['lib_titulo', 'lib_autor', 'lib_ubi', 'lib_isbn', 'lib_clasificacion', 'lib_seccion', 'lib_image_src_filename', 'lib_image_web_filename'], 'required'],
[['lib_ubi', 'lib_editorial_id'], 'integer'],
[['lib_titulo'], 'string', 'max' => 120],
[['lib_autor', 'lib_clasificacion'], 'string', 'max' => 64],
//[['lib_edicion'], 'string', 'max' => 3],
[['lib_isbn'], 'string', 'max' => 32],
[['lib_seccion'], 'string', 'max' => 2],
[['lib_editorial_id'], 'exist', 'skipOnError' => true, 'targetClass' => Editorial::className(), 'targetAttribute' => ['lib_editorial_id' => 'edi_id']],
[['lib_ubi'], 'exist', 'skipOnError' => true, 'targetClass' => Ubicacion::className(), 'targetAttribute' => ['lib_ubi' => 'ubil_id']],
[['lib_image_src_filename', 'lib_image_web_filename'], 'string', 'max' => 100],
[['image'], 'safe'],
[['image'], 'file', 'extensions'=>'jpg, gif, png'],
[['image'], 'file', 'maxSize'=>'1000000'],
[['lib_image_src_filename', 'lib_image_web_filename'], 'string', 'max' => 255], ];
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'lib_id' => 'ID',
'lib_titulo' => 'Titulo',
'lib_autor' => 'Autor',
//'lib_edicion' => 'Edicion',
'lib_editorial_id' => 'Editorial',
'lib_isbn' => 'ISBN',
'lib_clasificacion' => 'Clasificacion',
'lib_ubi' => 'Ubicacion',
'lib_seccion' => 'Seccion',
'image' => 'Captura',
'lib_image_src_filename' => Yii::t('app', 'Nombre de Archivo'),
'lib_image_web_filename' => Yii::t('app', 'Nombre del Directorio'),
'editorialNombre' => 'Editorial',
'ubicacionNombre' => 'Ubicacion',
];
}
/**
* #return \yii\db\ActiveQuery
*/
public function getAdqs()
{
return $this->hasMany(Adq::className(), ['adq_libro_id' => 'lib_id']);
}
/**
* #return \yii\db\ActiveQuery
*/
/**
* #return \yii\db\ActiveQuery
*/
public function getLibrosCarreras()
{
return $this->hasMany(LibrosCarreras::className(), ['lic_libros_id' => 'lib_id']);
}
/**
* #return \yii\db\ActiveQuery
*/
public function getEditorial0()
{
return $this->hasOne(Editorial::className(), ['edi_id' => 'lib_editorial_id']);
}
public function getEditorialNombre()
{
return $this->editorial0->edi_nombre;
}
public function getLibUbi()
{
return $this->hasOne(Ubicacion::className(), ['ubil_id' => 'lib_ubi']);
}
public function getUbicacionNombre()
{
return $this->libUbi->ubil_nombre; }
}
My Search Model (LibrosSearch.php):
<?php
namespace app\models;
use Yii;
use yii\base\Model;
use yii\data\ActiveDataProvider;
use app\models\Libros;
/**
* LibrosSearch represents the model behind the search form of `app\models\Libros`.
*/
class LibrosSearch extends Libros
{
public $editorialNombre;
public $ubicacionNombre;
/**
* #inheritdoc
*/
public function rules()
{
return [
[['lib_id', 'lib_ubi', 'lib_editorial_id'], 'integer'],
[['lib_titulo', 'lib_autor', 'lib_isbn', 'lib_clasificacion', 'lib_seccion', 'lib_image_src_filename', 'lib_image_web_filename'], 'safe'],
[['editorialNombre'],'safe'],
[['ubicacionNombre'],'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 = Libros::find();
// add conditions that should always apply here
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
$dataProvider->setSort([
'attributes'=>[
'editorialNombre'=>[
'asc'=>['editorial.edi_nombre'=>SORT_ASC],
'desc'=>['editorial.edi_nombre'=>SORT_DESC],
'label'=>'Editorial Nombre'
]
]
]);
$dataProvider->setSort([
'attributes'=>[
'ubicacionNombre'=>[
'asc'=>['ubicacion.ubil_nombre'=>SORT_ASC],
'desc'=>['ubicacion.ubil_nombre'=>SORT_DESC],
'label'=>'Ubicacion Nombre'
]
]
]);
$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([
'lib_id' => $this->lib_id,
'lib_ubi' => $this->lib_ubi,
'lib_editorial_id' => $this->lib_editorial_id,
]);
$query->andFilterWhere(['like', 'lib_titulo', $this->lib_titulo])
->andFilterWhere(['like', 'lib_autor', $this->lib_autor])
//->andFilterWhere(['like', 'lib_edicion', $this->lib_edicion])
->andFilterWhere(['like', 'lib_isbn', $this->lib_isbn])
->andFilterWhere(['like', 'lib_clasificacion', $this->lib_clasificacion])
->andFilterWhere(['like', 'lib_seccion', $this->lib_seccion])
->andFilterWhere(['like', 'lib_image_src_filename', $this->lib_image_src_filename])
->andFilterWhere(['like', 'lib_image_web_filename', $this->lib_image_web_filename]);
$query->joinWith(['editorial0'=>function($q)//creamos un nuevo filtro
{
$q->where('editorial.edi_nombre LIKE "%' . $this->editorialNombre . '%"');
}]);
$query->joinWith(['libUbi'=>function($q)//creamos un nuevo filtro
{
$q->where('ubicacion.ubil_nombre LIKE "%' . $this->ubicacionNombre . '%"');
}]);
return $dataProvider;
}
}
How can I accomplish this task?
[
'attribute' => 'adq_libro_id',
'value' => implode(', ', \yii\helpers\ArrayHelper::map($model->Adqs, 'id',
function ( $model )
{
return $model['adq'];
}
)),
'format' => 'raw'
],
try like this. Check the right name of attributes
In your model Libros.php you have this function.
public function getAdqs()
{
return $this->hasMany(Adq::className(), ['adq_libro_id' => 'lib_id']);
}
This means you can access the relations of Libros like:
// where $model is an instance of Libros
$model->adqs->property_name
Or as a function
$model->getAdqs();

issue with Yii 2 framework

I was trying to make a blog with YII2, my framework is confusing to call data from database.
For example when I call "username" from "user" table,
<?= DetailView::widget([
'model' => $model,
'attributes' => [
'user.fullname', --->> Yii2 is thinking that this is a category and not a user table
'title',
'description',
'content:html',
'count_view',
'status',
'created_at',
],
]) ?>
I am getting this error: -->> unknown property: app\models\Category::fullname
please could you help me to solve this issue, where I did make a mistake?
and here is my post model contains:
<?php
namespace app\models;
use Yii;
/**
* This is the model class for table "post".
*
* #property integer $id
* #property integer $user_id
* #property string $title
* #property string $description
* #property string $content
* #property integer $count_view
* #property string $status
* #property string $created_at
*
* #property User $user
* #property TagAssign[] $tagAssigns
*/
class Post extends \yii\db\ActiveRecord
{
/**
* #inheritdoc
*/
public static function tableName()
{
return 'post';
}
/**
* #inheritdoc
*/
public function rules()
{
return [
[['user_id', 'count_view','category_id'], 'integer'],
[['content', 'status'], 'string'],
[['created_at'], 'safe'],
[['count_view'], 'default','value'=>0],
[['user_id'], 'default','value'=>Yii::$app->user->id],
[['title', 'description'], 'string', 'max' => 255],
[['user_id'], 'exist', 'skipOnError' => true, 'targetClass' => User::className(), 'targetAttribute' => ['user_id' => 'id']],
];
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'user_id' => 'User ID',
'title' => 'Title',
'description' => 'Description',
'content' => 'Content',
'category' => 'Category',
'count_view' => 'Count View',
'status' => 'Status',
'created_at' => 'Created At',
];
}
/**
* #return \yii\db\ActiveQuery
*/
public function getUser()
{
return $this->hasOne(Category::className(), ['id' => 'user_id']);
}
public function getCategory()
{
return $this->hasOne(User::className(), ['id' => 'category_id']);
}
/**
* #return \yii\db\ActiveQuery
*/
public function getTagAssigns()
{
return $this->hasMany(TagAssign::className(), ['post_id' => 'id']);
}
}
and here user Model:
<?php
namespace app\models;
use Yii;
use yii\web\IdentityInterface;
/**
* This is the model class for table "user".
*
* #property integer $id
* #property string $username
* #property string $password
* #property string $fullname
* #property string $status
* #property string $role
* #property string $created_At
*
* #property Post[] $posts
*/
class User extends \yii\db\ActiveRecord implements IdentityInterface
{
/**
* #inheritdoc
*/
public static function tableName()
{
return 'user';
}
public $current_password;
public $new_password;
public $confirm_password;
public $authKey;
/**
* #inheritdoc
*/
public function rules()
{
return [
[['status', 'role'], 'string'],
[['created_At'], 'safe'],
[['username', 'password', 'fullname'], 'string', 'max' => 45],
];
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'username' => 'username',
'password' => 'password',
'fullname' => 'fullname',
'status' => 'Status',
'role' => 'Role',
'created_At' => 'Created At',
];
}
/**
* #return \yii\db\ActiveQuery
*/
public function getPosts()
{
return $this->hasMany(Post::className(), ['user_id' => 'id']);
}
public static function findIdentity($id)
{
return static::findOne($id);
}
public static function findIdentityByAccessToken($token,$type=null)
{
return static::findOne(['access_token'=>$token]);
}
public function getId()
{
return $this->id;
}
public function getAuthKey()
{
return $this->authKey;
}
public function validateAuthKey($authKey)
{
return $this->authKey == $authKey;
}
public static function findByUsername($username)
{
return static::findOne(['username'=>$username]);
}
public function validatePassword($password)
{
if(Yii::$app->security->validatePassword($password,$this->password))
{
return true;
} else {
return false;
}
}
}
Change to this in Post model.
public function getUser()
{
return $this->hasOne(User::className(), ['id' => 'category_id']);
}
public function getCategory()
{
return $this->hasOne(Category::className(), ['id' => 'user_id']);
}

How to add behaviour to a junction table?

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)

Yii2:Trying to get property of non-object

public function actionCreate()
{
$model = new Bookings();
$temp = new RoomTypes();
if ($model->load(Yii::$app->request->post()))
{
$roomtype = $model->room_type;
$totalremain = RoomTypes::find('total_remain')->where(['room_type' => $model->room_type])->one();
if ($roomtype->$totalremain > 0)
{
$imageName = $model->first_name;
$mobile = $model->primary_mobile;
$model->file = UploadedFile::getInstance($model, 'file');
$model->file->saveAs('uploads/id_images/' . $imageName . '_' . $mobile . '.' . $model->file->extension);
//save the path in the db column
$model->id_image = 'uploads/id_images/' . $imageName . '_' . $mobile . '.' . $model->file->extension;
$model->save();
return $this->redirect(['view', 'id' => $model->id]);
}
else
{
echo "This room Types are full ";
}
}
else {
return $this->render('create', [
'model' => $model,
'temp' => $temp,
]);
}
}
I need to check total_remain from Roomtypes model is > 0 from room_types in Bookings model, before submitting the form if user submit the form it should get flash meassage saying "this room are full"
Getting this error, how to solve this
getting error at if ($roomtype->$totalremain > 0)
Room types model
<?php
namespace backend\models;
use Yii;
/**
* This is the model class for table "room_types".
*
* #property integer $id
* #property integer $room_id
* #property string $room_type
* #property integer $total_count
* #property string $description
* #property integer $extra_beds
* #property string $images
* #property string $status
* #property integer $rate
* #property integer $adults_count
* #property integer $child_count
* #property integer $total_people
*/
class RoomTypes extends \yii\db\ActiveRecord
{
/**
* #inheritdoc
*/
public $imageFiles;
public static function tableName()
{
return 'room_types';
}
/**
* #inheritdoc
*/
public function rules()
{
return [
[['room_id','total_booked','total_remain','total_count', 'extra_beds', 'rate', 'adults_count', 'child_count'], 'integer'],
[['status'], 'string'],
[['imageFiles'], 'file', 'skipOnEmpty' => false, 'extensions' => 'png, jpg', 'maxFiles' => 4,'skipOnEmpty' => true, 'on' => 'update-photo-upload'],
[['room_type'], 'string', 'max' => 40],
[['description'], 'string', 'max' => 300],
[['images'], 'string', 'max' => 500]
];
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'room_id' => 'Room Number',
'room_type' => 'Room Type',
'total_count' => 'Total Count',
'description' => 'Description',
'extra_beds' => 'Extra Beds',
//'images' => 'Images',
'status' => 'Status',
'rate' => 'Rate',
'adults_count' => 'Adults Count',
'child_count' => 'Child Count',
'total_remain' =>'Remaing Rooms',
'total_booked' => 'Total Rooms Booked',
];
}
}
The code if ($roomtype->$totalremain > 0) is causing the problem.Change it like if ($totalremain->total_remain > 0)

Yii2 rest api join query with ActiveDataProvider

I have a custom action in ActiveController and need to fetch some data by joining two tables.
I have written following query .
$query = Item::find()->joinWith(['subcategory'])->select(['item.*', 'sub_category.name'])->where(['item.active' => 1])->addOrderBy(['item.id' => SORT_DESC]);
$pageSize = (isset($_GET["limit"]) ? $_GET["limit"] : 1) * 10;
$page = isset($_GET["page"]) ? $_GET["page"] : 1;
$dataProvider = new ActiveDataProvider(['query' => $query, 'pagination' => ['pageSize' => $pageSize, "page" => $page]]);
$formatter = new ResponseFormatter();
return $formatter->formatResponse("", $dataProvider->getTotalCount(), $dataProvider->getModels());
but it is throwing an exception
"message": "Setting unknown property: common\\models\\Item::name",
Here is the item Model with all the fields and relation.
<?php
namespace common\models;
use Yii;
use yii\behaviors\TimestampBehavior;
use yii\db\BaseActiveRecord;
use yii\db\Expression;
/**
* This is the model class for table "item".
*
* #property integer $id
* #property integer $subcategory_id
* #property string $title
* #property resource $description
* #property integer $created_by
* #property integer $updated_by
* #property string $created_at
* #property string $updated_at
* #property string $image
* #property integer $active
*
* #property SubCategory $subcategory
*/
class Item extends \yii\db\ActiveRecord
{
public $imageFile;
/**
* #inheritdoc
*/
public static function tableName()
{
return 'item';
}
/**
* #inheritdoc
*/
public function rules()
{
return [
[['created_by', 'updated_by'], 'required'],
[['subcategory_id', 'created_by', 'updated_by', 'active'], 'integer'],
[['description'], 'string'],
[['created_at', 'updated_at'], 'safe'],
[['title', 'image'], 'string', 'max' => 999],
[['title'], 'unique'],
[['imageFile'], 'file', 'skipOnEmpty' => true, 'extensions' => 'png, jpg'],
];
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'subcategory_id' => 'Subcategory ID',
'title' => 'Title',
'description' => 'Description',
'created_by' => 'Created By',
'updated_by' => 'Updated By',
'created_at' => 'Created At',
'updated_at' => 'Updated At',
'image' => 'Image',
'active' => 'Active',
'imageFile' => 'Image',
];
}
/**
* #return \yii\db\ActiveQuery
*/
public function getSubcategory()
{
return $this->hasOne(SubCategory::className(), ['id' => 'subcategory_id']);
}
/**
* #return \yii\db\ActiveQuery
*/
public function getCreatedBy()
{
return $this->hasOne(User::className(), ['id' => 'created_by']);
}
/**
* #return \yii\db\ActiveQuery
*/
public function getUpdatedBy()
{
return $this->hasOne(User::className(), ['id' => 'updated_by']);
}
public function behaviors()
{
return [
'timestamp' => [
'class' => TimestampBehavior::className(),
'attributes' => [
BaseActiveRecord::EVENT_BEFORE_INSERT => ['created_at', 'updated_at'],
BaseActiveRecord::EVENT_BEFORE_UPDATE => 'updated_at',
],
'value' => new Expression('NOW()'),
],
];
}
}
The joinWith makes a query using the joins requested, but result data are mapped in source model (in this case Item).
Since you have select(['item.*', 'sub_category.name']) , the framework will try to fill 'name' field of Item model, that does not exist and this generates the error.
According with documentation (http://www.yiiframework.com/doc-2.0/guide-rest-resources.html#overriding-extra-fields) you should have db relation subcategory populated from db, by default, but I don't see subcategory relation in your model.
So you have only to create subcategory relation in your model, such as:
public function getSubcategory() { return $this->hasOne(Subcategory::className(), ['id' => 'subcategory_id']); }
So you should solve your problem.
Other solution to have custom fields from more models could be:
1) Create a sql View (and from that create the Model) with fields that you want and pass it to ActiveDataProvide
2) Override extraFields method of the model (http://www.yiiframework.com/doc-2.0/yii-base-arrayabletrait.html#extraFields%28%29-detail)
Again, I suggest you to read this good article:
http://www.yiiframework.com/wiki/834/relational-query-eager-loading-in-yii-2-0/

Categories