Foreign Key Relations In Yii2 (Activerecord)

Hi.

I am trying to learn Yii2 but stuck on understanding how related tables should be implemented in Yii2.

Examples from Yii1.1 do not help because AtctiveRecord had been redesigned completely.

Please help me with examples on following:

  1. Given two related tables eg. tbl_writer(id,name) and tbl_book(id,writer_id,title). Table tbl_book has foreign key writer_id.

  2. how to pass to GridView fields of tbl_book: writers_name, title ?

  3. how to pass to GridView fields of tbl_writer: name, list_of_books_titles ?

  4. how to make the form of tbl_book to choose writer_id from dropDown list of writers ?

Looking forward for replies.

Take a look here, it explains how to use relations in Yii 2:

https://github.com/yiisoft/yii2/blob/master/docs/guide/active-record.md#querying-relational-data

You can get relational data in your Gridview by using a dot. So if your relation is called ‘book’, you can get the value of writers_name in your Gridview by: ‘book.writers_name’.

A dropdownlist with content from a model can be done like this:


$models = Writer::find()->asArray()->all();

$map = ArrayHelper::map($models, 'id', 'name'); // (where 'id' becomes the value and 'name' the name of the value which will be displayed)

<?= $form->field($model, 'writer_id')->dropDownList($map) ?>

Where should we type this code?


$models = Writer::find()->asArray()->all();

$map = ArrayHelper::map($models, 'id', 'name'); // (where 'id' becomes the value and 'name' the name of the value which will be displayed)



Thanks

View (for one-off use) or Model (for multiple reuse).




// In view

$models = Writer::find()->asArray()->all();

$data = ArrayHelper::map($models, 'id', 'name');

echo $form->field($model, 'field')->dropDownList($data);



Alternatively:

In model




class ModelClass extends yii\db\ActiveRecord {

    public function getDataList() { // could be a static func as well

        $models = Writer::find()->asArray()->all();

        return ArrayHelper::map($models, 'id', 'name');

    }

}



In view




echo $form->field($model, 'field')->dropDownList($model->dataList);



I’ve got the following error:

Getting unknown property: app\models\Book::Writer_id

Just a note: I’ve added

use app\models\Writer;

use yii\helpers\ArrayHelper;

Can you post the code for the Book model (and where you are using it)?

I’m not using book or writer models. I’m using employee and organization models instead.

Many thanks for your help.

Employee.php




<?php


namespace app\models;


use app\models\Organization;

use yii\helpers\ArrayHelper;


/**

 * This is the model class for table "employee".

 *

 * @property string $Id

 * @property string $CommonName

 * @property string $FirstName

 * @property string $MiddleName

 * @property string $LastName

 * @property string $Organization_Id

 */


class Employee extends \yii\db\ActiveRecord

{

	/**

	 * @inheritdoc

	 */

	public static function tableName()

	{

		return 'employee';

	}


	/**

	 * @inheritdoc

	 */

	public function rules()

	{

		return [

			[['CommonName', 'FirstName', 'MiddleName', 'LastName', 'Organization_Id'], 'required'],

			[['Organization_Id'], 'integer'],

			[['CommonName', 'FirstName', 'MiddleName', 'LastName'], 'string', 'max' => 255]

		];

	}


	/**

	 * @inheritdoc

	 */

	public function attributeLabels()

	{

		return [

			'Id' => 'ID',

			'CommonName' => 'Common Name',

			'FirstName' => 'First Name',

			'MiddleName' => 'Middle Name',

			'LastName' => 'Last Name',

			'Organization_Id' => 'Organization ID',

		];

	}

	

	/** Own Code Begin ***************************************************/

	

	public function getOrganization() {

		return $this->hasOne(Organization::className(), ['Id' => 'Organization_Id']);

	}

	

	public function getOrganizationName() {

		return $this->Organization->Name;

	}

	

	public function getOrganizationList() { 

                $models = Organization::find()->asArray()->all();

                return ArrayHelper::map($models, 'Id', 'Name');

        }


	/** Own Code End   ***************************************************/

	

}




_form.php (Employee)




<?php


use yii\helpers\Html;

use yii\widgets\ActiveForm;


/**

 * @var yii\web\View $this

 * @var app\models\Employee $model

 * @var yii\widgets\ActiveForm $form

 */

 

?>


<div class="employee-form">


	<?php $form = ActiveForm::begin(); ?>


		<?= $form->field($model, 'CommonName')->textInput(['maxlength' => 255]) ?>


		<?= $form->field($model, 'FirstName')->textInput(['maxlength' => 255]) ?>


		<?= $form->field($model, 'MiddleName')->textInput(['maxlength' => 255]) ?>


		<?= $form->field($model, 'LastName')->textInput(['maxlength' => 255]) ?>

		

		<?= $form->field($model, 'Organization_id')->dropDownList($model->organizationList) ?>

	

		<div class="form-group">

			<?= Html::submitButton($model->isNewRecord ? 'Create' : 'Update', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>

		</div>


	<?php ActiveForm::end(); ?>


</div>




Error:

"Getting unknown property: app\models\Employee::Organization_id"

in …\basic\vendor\yiisoft\yii2\yii\base\Component.php at line 66




            }

        }

        if (method_exists($this, 'set' . $name)) {

            throw new InvalidCallException('Getting write-only property: ' . get_class($this) . '::' . $name);

        } else {

            throw new UnknownPropertyException('Getting unknown property: ' . get_class($this) . '::' . $name);

        }

    }

 

    /**

     * Sets the value of a component property.



NOTE THE CASE in your attribute naming. Change all instances of "Organization_id" to "Organization_Id".

In your view file: THIS IS WRONG.




 <?= $form->field($model, 'Organization_id')->dropDownList($model->organizationList)



CHANGE TO




 <?= $form->field($model, 'Organization_Id')->dropDownList($model->organizationList)



Its recommended to use lower case characters for all your table fields in your database to avoid such errors.

You are the best. Sorry to bother you with this kind of errors. I should have seen it.

Many thanks.

Sir please help:

i am using yii2 advanced. And i want to search foreign key from search model class.

i am getting error. my code is


public function getDataList() {	 // could be a static func as well

        $models = Admin::find()->asArray()->all();

        return ArrayHelper::map($models, 'id', 'username');

    }

MY Error is

Fatal Error – yii\base\ErrorException

Class ‘app\models\ArrayHelper’ not found


use yii\helpers\ArrayHelper;

I haven’t tried it yet, but I know in yii 1.1 gii automatically builds relations, here we have to write relations by ourselves?

No, Gii in Yii2 has this feature too. There is checkbox called "Generate Relations" which is checked by default. Gii will generate relations based on foreign key constraints it detects in the database.

Hello Sir,

How can I use this in different view. Like I have declared function to bind state in State model and want to use it any view where I have a field for State.

Kindly help me.

Thanks

The grid view page

the corresponding territory_type_id equivalent value is not retrieve

I want to show the

var_dump($model->territory);

if (isset ( $model->territory ) && ! empty ( $model->territory->territory_name))

return $model->territory->territory_name;

Unknown Property – yii\base\UnknownPropertyException

Getting unknown property: livefactory\models\Census::territory

have u code for "territory" relation? like

in CITY MODEL




public function getState()

    {

        return $this->hasOne(State::className(), ['stateId' => 'stateId']);

    }

In CITY INDEX GRID


 'state.stateName',

// this display state Name depends on stateId of city table.

regards,

webin

I have a business model. This model need to the territory details in dropdown. The values are inserted perfectly.

But the index page all the values are shown in grid view except territory_name.

using the following

if (isset ( $model->territory ) && ! empty ( $model->territory->territory_name))

return $model->territory->territory_name;

kindly share your relation method for territory of business model

and i assume that territory is relation function name then why u use like isset($model->territory)

Those are all business module files.

but the file names are comes like customer the variables are business.

if (isset ( $model->territory ) && ! empty ( $model->territory->territory_name))

checking the table is in or not

[color="#FF0000"]My model[/color]

class Customer extends \yii\db\ActiveRecord

{

/**


 * @inheritdoc


 */


public static function tableName()


{


    return 'tbl_business';


}





/**


 * @inheritdoc


 */


public function rules()


{


    return [


        [['business_name', 'business_cond_type_id', 'email', 'mobile'], 'required'],


        [['territory_type_id', 'business_cond_type_id', 'num', 'added_at', 'updated_at', 'inserted_by', 'updated_by'], 'integer'],


        [['business_name', 'latitude', 'longitude', 'street', 'between_street', 'and_street', 'colony', 'inserted_ip', 'updated_ip', 'email', 'first_name', 'last_name', 'phone', 'mobile', 'fax'], 'string', 'max' =&gt; 255]


    ];


}





/**


 * @inheritdoc


 */


public function attributeLabels()


{


    return [


        'id' =&gt; Yii::t('app', 'ID'),


        'business_name' =&gt; Yii::t('app', 'Business Name'),


		'territory_type_id' =&gt; Yii::t('app', 'Territory Type'),


        'business_cond_type_id' =&gt; Yii::t('app', 'Business Type'),


		'latitude' =&gt; Yii::t('app', 'Latitude'),


		'longitude' =&gt; Yii::t('app', 'Longitude'),


		'num' =&gt; Yii::t('app', 'Minutes'),


		'street' =&gt; Yii::t('app', 'Street'),


		'between_street' =&gt; Yii::t('app', 'Between Street'),


		'and_street' =&gt; Yii::t('app', 'And Street'),


        'email' =&gt; Yii::t('app', 'Email'),


        'first_name' =&gt; Yii::t('app', 'First Name'),


        'last_name' =&gt; Yii::t('app', 'Last Name'),


        'phone' =&gt; Yii::t('app', 'Phone'),


        'mobile' =&gt; Yii::t('app', 'Mobile'),


        'fax' =&gt; Yii::t('app', 'Fax'),


        'contact_id' =&gt; Yii::t('app', 'Contact'),


        'added_at' =&gt; Yii::t('app', 'Added At'),


        'updated_at' =&gt; Yii::t('app', 'Updated At'),


		'inserted_ip' =&gt; Yii::t('app', 'inserted_ip'),


		'inserted_by' =&gt; Yii::t('app', 'inserted_by'),


		'updated_ip' =&gt; Yii::t('app', 'updated_ip'),


		'updated_by' =&gt; Yii::t('app', 'updated_by'),


    ];


}


public function getCustomerType()





{





	return &#036;this-&gt;hasOne(CustomerType::className(), ['id' =&gt; 'business_cond_type_id']);





}

[color="#FF0000"]Searchmodel:[/color]

class Customer extends CustomerModel

{

public function rules()


{


    return [


        [['id', 'business_cond_type_id', 'territory_type_id', 'added_at', 'updated_at'], 'integer'],


        [['business_name', 'email', 'first_name', 'last_name', 'phone', 'mobile', 'fax'], 'safe'],


    ];


}





public function scenarios()


{


    // bypass scenarios() implementation in the parent class


    return Model::scenarios();


}





public function search(&#036;params)


{


    &#036;query = CustomerModel::find();





    &#036;dataProvider = new ActiveDataProvider([


        'query' =&gt; &#036;query,


    ]);





    if (&#33;(&#036;this-&gt;load(&#036;params) &amp;&amp; &#036;this-&gt;validate())) {


        return &#036;dataProvider;


    }





    &#036;query-&gt;andFilterWhere([


        'id' =&gt; &#036;this-&gt;id,


        'business_cond_type_id' =&gt; &#036;this-&gt;business_cond_type_id,


		'territory_type_id' =&gt; &#036;this-&gt;territory_type_id,


        //'contact_id' =&gt; &#036;this-&gt;contact_id,


        'added_at' =&gt; &#036;this-&gt;added_at,


        'updated_at' =&gt; &#036;this-&gt;updated_at,


    ]);





    &#036;query-&gt;andFilterWhere(['like', 'business_name', &#036;this-&gt;business_name])


        -&gt;andFilterWhere(['like', 'email', &#036;this-&gt;email])


        -&gt;andFilterWhere(['like', 'first_name', &#036;this-&gt;first_name])


        -&gt;andFilterWhere(['like', 'last_name', &#036;this-&gt;last_name])


        -&gt;andFilterWhere(['like', 'phone', &#036;this-&gt;phone])


        -&gt;andFilterWhere(['like', 'mobile', &#036;this-&gt;mobile])


        -&gt;andFilterWhere(['like', 'fax', &#036;this-&gt;fax]);





    return &#036;dataProvider;


}


public function searchProject(&#036;params,&#036;customer_id)





{





    &#036;query = ProjectModel::find()-&gt;where(&quot;customer_id=&#036;customer_id&quot;);











    &#036;dataProvider = new ActiveDataProvider([





        'query' =&gt; &#036;query,





    ]);











    











    return &#036;dataProvider;





}


public function searchAddresses(&#036;params, &#036;entity_id)





{





	&#036;sql =&quot;select tbl_city.city,tbl_country.country,tbl_state.state,tbl_address.*,tbl_customer_addresses.* from tbl_city,tbl_country,tbl_state,tbl_address,tbl_customer_addresses where tbl_city.id=tbl_address.city_id and tbl_state.id=tbl_address.state_id and tbl_country.id=tbl_address.country_id  and tbl_address.entity_id=&#036;entity_id and tbl_address.is_primary='1' and tbl_address.entity_type='customer'&quot;;





		&#036;connection = &#092;Yii::&#036;app-&gt;db;





		&#036;command=&#036;connection-&gt;createCommand(&#036;sql);





		&#036;dataReader=&#036;command-&gt;queryAll();





	





	return &#036;dataReader;





}





public function searchCustomer(){





	&#036;sql =&quot;select 			





				tbl_city.city,





				tbl_country.country,





				tbl_state.state,





				tbl_address.*,





				tbl_business.*,





				tbl_business_condition_type.type, 


				


				tbl_territory.territory_name





			from 


				tbl_business





				 


				LEFT JOIN tbl_business_condition_type


				ON tbl_business.business_cond_type_id=tbl_business_condition_type.id


				


				LEFT JOIN tbl_territory


				ON tbl_business.territory_type_id=tbl_territory.territory_type_id


				


				LEFT JOIN tbl_address


				ON tbl_address.entity_id=tbl_business.id and tbl_address.is_primary='1'


				


				LEFT JOIN tbl_country


				ON tbl_country.id=tbl_address.country_id


				


				LEFT JOIN tbl_state


				ON tbl_state.id=tbl_address.state_id


				


				LEFT JOIN tbl_city


				ON tbl_city.id=tbl_address.city_id


				&quot;;





				//echo &#036;sql;





		&#036;connection = &#092;Yii::&#036;app-&gt;db;





		&#036;command=&#036;connection-&gt;createCommand(&#036;sql);





		&#036;dataReader=&#036;command-&gt;queryAll();





	





	return &#036;dataReader;





}

[color="#FF0000"]My View:[/color]

Pjax::begin ();

                    echo GridView::widget ( [ 





                            'dataProvider' =&gt; &#036;dataProvider,





                            'filterModel' =&gt; &#036;searchModel,





                            'columns' =&gt; [ 





                                    ['class' =&gt; '&#092;kartik&#092;grid&#092;CheckboxColumn'],





                                    ['class' =&gt; 'yii&#092;grid&#092;SerialColumn'],





                                    





                                    // 'id',





                                    [ 





                                            'attribute' =&gt; 'business_name',





                                            'width' =&gt; '200px',





                                            'format' =&gt; 'raw',





                                            'value' =&gt; function (&#036;model, &#036;key, &#036;index, &#036;widget)





                                            {





                                                return '&lt;a href=&quot;index.php?r=customer/customer/customer-view&amp;id=' . &#036;model-&gt;id . '&quot;&gt;' . &#036;model-&gt;business_name . '&lt;/a&gt;';





                                            } 





                                    ],





                                    [ 





                                            'attribute' =&gt; 'business_cond_type_id',





                                           // 'label' =&gt; 'Type',





                                            'filterType' =&gt; GridView::FILTER_SELECT2,





                                            'format' =&gt; 'raw',





                                            'width' =&gt; '100px',





                                            'filter' =&gt; ArrayHelper::map ( CustomerType::find ()-&gt;orderBy ( 'sort_order' )-&gt;asArray ()-&gt;all (), 'id', 'label' ),





                                            'filterWidgetOptions' =&gt; [ 





                                                    'options' =&gt; [ 





                                                            'placeholder' =&gt; 'All...' 





                                                    ],





                                                    'pluginOptions' =&gt; [ 





                                                            'allowClear' =&gt; true 





                                                    ] 





                                            ],





                                            'value' =&gt; function (&#036;model, &#036;key, &#036;index, &#036;widget)





                                            {





                                                // var_dump(&#036;model-&gt;user);





                                                // var_dump(&#036;model-&gt;customerType);





                                                if (isset ( &#036;model-&gt;customerType ) &amp;&amp; &#33; empty ( &#036;model-&gt;customerType-&gt;label ))





                                                    return &#036;model-&gt;customerType-&gt;label;





                                            } 





                                    ],


									


									// [ 





                                            // 'attribute' =&gt; 'territory_type_id',





                                           // 'label' =&gt; 'Type',





                                            // 'filterType' =&gt; GridView::FILTER_SELECT2,





                                            // 'format' =&gt; 'raw',





                                            // 'width' =&gt; '100px',





                                            // 'filter' =&gt; ArrayHelper::map ( Territory::find ()-&gt;orderBy ( 'territory_name' )-&gt;asArray ()-&gt;all (), 'territory_type_id', 'territory_name' ),





                                            // 'filterWidgetOptions' =&gt; [ 





                                                    // 'options' =&gt; [ 





                                                            // 'placeholder' =&gt; 'All...' 





                                                    // ],





                                                    // 'pluginOptions' =&gt; [ 





                                                            // 'allowClear' =&gt; true 





                                                    // ] 





                                            // ],





                                            // 'value' =&gt; function (&#036;model, &#036;key, &#036;index, &#036;widget)





                                            // {





                                                // var_dump(&#036;model-&gt;user);





                                                // var_dump(&#036;model-&gt;customerType);





                                                // if (isset ( &#036;model-&gt;Territory ) &amp;&amp; &#33; empty ( &#036;model-&gt;Territory-&gt;territory_name ))





                                                    // return &#036;model-&gt;Territory-&gt;territory_name;





                                            // } 





                                    // ],





                                    'latitude',





                                    'longitude',





                                    'email:email',





                                    





                                    // 'phone',





                                    'mobile',





                                    





                                    // 'fax',





                                    // 'address_id',





                                    // 'created_at',





                                    // 'updated_at',





                                    





                                    [ 





                                            'class' =&gt; 'yii&#092;grid&#092;ActionColumn',





                                            'template' =&gt; '{update} {delete}',





                                            'buttons' =&gt; [ 





                                                    'update' =&gt; function (&#036;url, &#036;model)





                                                    {





                                                        return '&lt;a href=&quot;?r=customer/customer/customer-view&amp;id=' . &#036;model-&gt;id . '&quot;&gt;&lt;span class=&quot;glyphicon glyphicon-eye-open&quot;&gt;&lt;/span&gt;&lt;/a&gt;';





                                                    } ,


													'delete' =&gt; function(&#036;url,&#036;model){


														&#036;view =&#036;_GET['view']?'&amp;view='.&#036;_GET['view']:'';


													return '&lt;form action=&quot;index.php?r=customer/customer/delete&amp;id='.&#036;model-&gt;id.&#036;view.'&quot; method=&quot;post&quot; name=&quot;cust'.&#036;model-&gt;id.'&quot; style=&quot;display:inline&quot;&gt;





&lt;input type=&quot;hidden&quot; name=&quot;_csrf&quot; value=&quot;&quot;&gt;


    &lt;button type=&quot;submit&quot; onClick=&quot;return confirm(&#092;''.Yii::t ('app','Are you Sure&#33;').'&#092;')&quot;  class=&quot;btn btn-link&quot; style=&quot;color:#337ab7;display:inline;padding:0&quot;&gt;&lt;span class=&quot;glyphicon glyphicon-trash&quot;&gt;&lt;/span&gt;&lt;/button&gt;


&lt;/form&gt;	';





													}





                                            ]





                                             





                                    ] 





                            ],





                            'responsive' =&gt; true,





                            





                            'hover' =&gt; true,





                            'condensed' =&gt; true,





                            'floatHeader' =&gt; false,





                            





                            'panel' =&gt; [ 





                                    'heading' =&gt; '&lt;h3 class=&quot;panel-title&quot;&gt;&lt;i class=&quot;glyphicon glyphicon-th-list&quot;&gt;&lt;/i&gt; '.Yii::t ( 'app', 'Business' ).' &lt;/h3&gt;',





                                    'type' =&gt; 'info',





                                    'before' =&gt; Html::a ( '&lt;i class=&quot;glyphicon glyphicon-plus&quot;&gt;&lt;/i&gt; '.Yii::t ( 'app', 'Add' ), [ 





                                            'create' 





                                    ], [ 





                                            'class' =&gt; 'btn btn-success' 





                                    ] ).' &lt;a href=&quot;javascript:void(0)&quot; onClick=&quot;all_del()&quot; class=&quot;btn btn-danger&quot;&gt;&lt;i class=&quot;glyphicon glyphicon-trash&quot;&gt;&lt;/i&gt; '.Yii::t ( 'app', 'Delete Selected' ).'&lt;/a&gt;',





                                    'after' =&gt; Html::a ( '&lt;i class=&quot;glyphicon glyphicon-repeat&quot;&gt;&lt;/i&gt; '.Yii::t ( 'app', 'Reset List' ), [ 





                                            'index' 





                                    ], [ 





                                            'class' =&gt; 'btn btn-info' 





                                    ] ),





                                    'showFooter' =&gt; false 





                            ] 





                    ] );





                    Pjax::end ();