How to return value based on id?

Hello,

I am still trying to grasps the concept of Yii2,

I have created 2 models and their CRUDS called categories and posts respectively.

I am ok to pass in the Posts _form the categories via a drop down menu and save the whole form into the CRUD.

Where I am confused in this concept is that in MYSQL, I created a relation between the Categories and the posts as:

Categories has many posts.

But, the CRUD created in GII expect to have an ID of the categories in the _form of the posts…

How to get the categories name instead while still having the validation accepting the input?

Right now in my form I have this:




<?php


use yii\helpers\Html;

use yii\widgets\ActiveForm;

use yii\helpers\ArrayHelper;

use frontend\models\categories;

use yii\models\user;

use yii\web\IdentityInterface;




/* @var $this yii\web\View */

/* @var $model frontend\models\Posts */

/* @var $form yii\widgets\ActiveForm */

?>


<div class="posts-form">


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


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


    <?= $form->field($model, 'posts')->textarea(['rows' => 6]) ?>


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







    

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

    ArrayHelper::map(Categories::find()->all(),'id','id'),

    ['prompt'=>'Select a category']) ?>

   

    

    <?= $form->field($model, 'user_id')->textInput(['value' => \Yii::$app->user->identity->id]) ?>

   

  


    <div class="form-group">

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

    </div>


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


</div>




But i do not want the ID to be output, but instead the name of the categories so instead I added this:




<?= $form->field($model, 'categories')->dropDownList(ArrayHelper::map(Categories::find()->all(),'id','id'),

    ['prompt'=>'Select a category']) ?>




This correctly shows the category names but won;t let me submit the form.

So I then added in the Posts model this:




    public function rules()

    {

        return [

            [['title', 'posts', 'categories_id', 'user_id'], 'required'],

            [['posts'], 'string'],

            [['created_at', 'updated_at'], 'safe'],

            [['categories_id', 'user_id'], 'integer'],

            [['title'], 'string', 'max' => 160],

            [['keywords'], 'string', 'max' => 45],

            [['categories'], 'string', 'max' => 64],<------------

        ];

    }






I can submit the form now but right after submission I get this error:




Invalid Call – yii\base\InvalidCallException


Setting read-only property: frontend\models\Posts::categories

1. in C:\xampp\htdocs\forum\vendor\yiisoft\yii2\base\Component.php at line 195

186187188189190191192193194195196197198199200201202203204            foreach ($this->_behaviors as $behavior) {

                if ($behavior->canSetProperty($name)) {

                    $behavior->$name = $value;

 

                    return;

                }

            }

        }

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

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

        } else {

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

        }

    }

 

    /**

     * Checks if a property value is null.

     * This method will check in the following order and act accordingly




I am not getting this, could you please help me?

Thank you,

Ben

Ok So I moved forward a bit, in the _form file I added:




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

    ArrayHelper::map(Categories::find()->all(),'id','name'),

    ['prompt'=>'Select a category']) ?>



I did not know that you could record in the database the id but show the category name ‘id’, ‘name’

Now my next problem is in the next page(index), It shows the categorie id, how to output the category name instead please?




    <?= GridView::widget([

        'dataProvider' => $dataProvider,

        'filterModel' => $searchModel,

        'columns' => [

            ['class' => 'yii\grid\SerialColumn'],


            'id',

            'title',

            'posts:ntext',

            'keywords',

            'created_at:datetime',

            'updated_at:datetime',

            'categories_id',

            // 'user_id',


            ['class' => 'yii\grid\ActionColumn'],

        ],

    ]); ?>



Thank you,

Ben

Ok Cracked it, this is how to do it:




    <?= GridView::widget([

        'dataProvider' => $dataProvider,

        'filterModel' => $searchModel,

        'columns' => [

            ['class' => 'yii\grid\SerialColumn'],


            'id',

            'title',

            'posts:ntext',

            'keywords',

            'created_at:datetime',

            'updated_at:datetime',

           [

            'attribute' => 'categories_id',

            'label' => 'Categories',

            'value' => 'categories.name',

           ],

            // 'categories_id',

            // 'user_id',


            ['class' => 'yii\grid\ActionColumn'],

        ],

    ]); ?>



Funnily enough, when I add the exact same code in the "view" file which comes after the "create" action, it does not show the categorie name but instead this:




ID	8

Title	This is the post 4

Posts	this is a post

Keywords	keyword1

Created At	Apr 27, 2015 12:07:17 AM

Updated At	Apr 27, 2015 12:07:17 AM

Categories	categories.name<----------------------------

User ID	1



Any idea why please?

Thank you,

Ben

What are you using to in the view.php?

DetailView Wiget?

Try for example:




    <?= DetailView::widget([

        'model' => $model,

        'attributes' => [


            [

                'attribute' => 'categories_id',

                'value'     => Html::encode($model->categories->name),

            ],

        ],

    ]) ?>



Thank you so much, I was using a <?= GridView::widget, I have just added your code to it, and it works great!

Thank you!

Ben

Where I am confused is to why do we have to encode the output in the Detail view widget but not the Grid view?

I did this in the gridview and it worked:




   <?= GridView::widget([

        'dataProvider' => $dataProvider,

        'filterModel' => $searchModel,

        'columns' => [

            ['class' => 'yii\grid\SerialColumn'],


            'id',

            'title',

            'posts:ntext',

            'keywords',

            'created_at:datetime',

            'updated_at:datetime',

           [

            'attribute' => 'categories_id',

            'label' => 'Categories',

            'value' => 'categories.name',

           ],

            // 'categories_id',

            // 'user_id',


            ['class' => 'yii\grid\ActionColumn'],

        ],

    ]); ?>