U
U
User4562019-06-08 21:10:12
Yii
User456, 2019-06-08 21:10:12

How to display one-to-many and mamy-to-many relationship in gii code generator in yii framework CRUD operations?

Good day! I searched a lot of sites, but did not find how to display one-to-many and many-to-many relationships. I only found how to implement them during migration, so that the tables in the database are linked by primary and foreign keys, but I did not find its value instead of the foreign key. And I also have a task - to implement this without sculpting cumbersome constructions from htlm and php code in the form of foreach and echo for each page, but all using the framework (there is a suspicion that, probably, you need to add a few lines of code in the model, or in the controller ). Actually the task itself. There are 3 tables. product(id, name, id_category, id_country, s_description, description, price). country(id, country). category(id, category). The product table has foreign keys to the country (id_country => id) and category (id_country => id) tables.
Migrations:
category table

public function safeUp()
    {
          $this->createTable('category', [
            'id' => $this->primaryKey(),
            'category' => $this->string(),
        ]);
    $this->alterColumn('category','id',$this->smallInteger(8).'NOT NULL AUTO_INCREMENT');	
    }
    public function safeDown()
    {
        $this->dropTable('category');
    }

country table
public function safeUp()
    {
        $this->createTable('country', [
            'id' => $this->primaryKey(),
      'country' => $this->string(),
        ]);
    $this->alterColumn('country','id',$this->smallInteger(8).'NOT NULL AUTO_INCREMENT');
    }
    public function safeDown()
    {
        $this->dropTable('country');
    }

product table
public function safeUp()
    {
        $this->createTable('product', [
            'id' => $this->primaryKey(),
            'name' => $this->string(),
            'id_category' => $this->smallInteger(8),
            'id_country' => $this->smallInteger(8),
            's_description' => $this->string(),
            'description' => $this->string(),
            'price' => $this->integer(),
        ]);
    $this->alterColumn('product','id',$this->smallInteger(8).'NOT NULL AUTO_INCREMENT');
    
    $this->addForeignKey(
      'product_to_category',
      'product',
      'id_category',
      'category',
      'id',
      'CASCADE'
    );
    
    $this->addForeignKey(
      'product_to_country',
      'product',
      'id_country',
      'country',
      'id',
      'CASCADE'
    );
    }
    public function safeDown()
    {
        $this->dropTable('product');
    }

Models:
Category:
...
public function getProducts()
    {
        return $this->hasMany(Product::className(), ['id_category' => 'id']);
    }

Country:
...
public function getProducts()
    {
        return $this->hasMany(Product::className(), ['id_country' => 'id']);
    }

product:
...
    /**
     * @return \yii\db\ActiveQuery
     */
    public function getCategory()
    {
        return $this->hasOne(Category::className(), ['id' => 'id_category']);
    }

    /**
     * @return \yii\db\ActiveQuery
     */
    public function getCountry()
    {
        return $this->hasOne(Country::className(), ['id' => 'id_country']);
    }

Controllers:
CategoryController:
...
public function actionIndex()
    {
        $searchModel = new CategorySearch();
        $dataProvider = $searchModel->search(Yii::$app->request->queryParams);

        return $this->render('index', [
            'searchModel' => $searchModel,
            'dataProvider' => $dataProvider,
        ]);
    }
...

CountryController
...
public function actionIndex()
    {
        $searchModel = new CountrySearch();
        $dataProvider = $searchModel->search(Yii::$app->request->queryParams);

        return $this->render('index', [
            'searchModel' => $searchModel,
            'dataProvider' => $dataProvider,
        ]);
    }
...

ProductController
...
public function actionIndex()
    {
        $searchModel = new ProductSearch();
        $dataProvider = $searchModel->search(Yii::$app->request->queryParams);

        return $this->render('index', [
            'searchModel' => $searchModel,
            'dataProvider' => $dataProvider,
        ]);
    }
...

I repeat, in the end, when displaying data from the product table, it is required to get not the key id_category and id_country, but their value from the tables. And, if it's not difficult, please tell us more about how all this will be implemented for many-to-many communication. In advance, to all those who respond, thanks for the help!

Answer the question

In order to leave comments, you need to log in

1 answer(s)
D
Dmitry, 2019-06-08
@User456

Good afternoon.
This is redundant in all migrations
If in the GridView you want to display not the id, but the name of the category, for example, then in the value you specify this through the link

// for hasOne()
'value' => function($model){
       return $model->country->name ?? null;
}

If your connection goes through hasMany(), then you will get several values, you can display them all through implode()
// for hasMany()
'value' => function($model){
        return implode(',', ArrayHelper::map($model->country, 'id', 'name'));
}

Can be displayed without an anonymous function, immediately indicate the name of the relationship and the name of the attribute
'value' => 'country.name'

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question