@User456

Как вывести связь one-to-many и mamy-to-many в генераторе кода gii в операциях CRUD фреймворка yii?

Доброго времени суток! Обыскал множество сайтов, но так и не нашел как выводить связи one-to-many и many-to-many. Нашел только как их реализовывать при миграции, чтоб в базе таблицы были связаны первичными и внешними ключами, но выводить вместо внешнего ключа - его значение, так и не нашел. И еще предо мной стоит задача - реализовать это не лепя громоздкие конструкции из htlm и php кода в виде foreach и echo для каждой страницы, а все средствами фреймворка (есть подозрение, что, наверное, нужно добавить несколько сточек кода в модели, или в контроллере). Собственно сама задача. Есть 3 таблицы. product(id, name, id_category, id_country, s_description, description, price). country(id, country). category(id, category). Таблица product имеет внешние ключи к таблицам country (id_country => id) и на таблицу category (id_country => id).
Миграции:
Таблица category
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
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
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');
    }

Модели:
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']);
    }

Контроллеры:
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,
        ]);
    }
...

Повторюсь, в итоге, требуется получить, при выводе данных таблицы product, не ключ id_category и id_country, а их значении из таблиц. И, если не трудно, расскажите еще пожалуйста, как это все будет реализовываться для связи many-to-many. Заранее, всем тем кто откликнется, спасибо за помощь!
  • Вопрос задан
  • 70 просмотров
Решения вопроса 1
slo_nik
@slo_nik Куратор тега Yii
Добрый день.
Вот это лишнее во всех миграциях
$this->alterColumn('category','id',$this->smallInteger(8).'NOT NULL AUTO_INCREMENT');

Если в GridView хотите вывести не id, а имя категории, например, то в value указываете это через связь
// for hasOne()
'value' => function($model){
       return $model->country->name ?? null;
}

Если у Вас связь идёт через hasMany(), то Вы получите несколько значений, вывести их все можно через implode()
// for hasMany()
'value' => function($model){
        return implode(',', ArrayHelper::map($model->country, 'id', 'name'));
}

Можно выводить без анонимной функции, сразу указывать название связи и имя атрибута
'value' => 'country.name'
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы