2016-05-07 11 views
0

Я пытаюсь отобразить данные в GridView, используя таблицу Junction через отношение many-to-many. Создавая отношение «один ко многим», он работает нормально.Yii2 Junction table gridview display issue

Я уже пробовал некоторые из размещенных вопросов по этой проблеме, но не мог найти, что я делаю неправильно. Пожалуйста, ознакомьтесь со следующим кодом.

интерфейс \ модели \ Users.php

namespace frontend\models; 

use Yii; 

class Users extends \yii\db\ActiveRecord 
{ 
    # @inheritdoc 
    public static function tableName() 
    { 
     return 'users'; 
    } 

    # @inheritdoc 
    public function rules() 
    { 
     return [ 
      [['phone'], 'integer'], 
      [['username', 'address'], 'string', 'max' => 255], 
     ]; 
    } 

    # @inheritdoc 
    public function attributeLabels() 
    { 
     return [ 
      'id' => 'ID', 
      'username' => 'Username', 
      'address' => 'Address', 
      'phone' => 'Phone', 
     ]; 
    } 

    public function getUserCourses() 
    { 
     // one-to-many 
     return $this->hasMany(UserCourses::className(), ['users_id' => 'id']); 
    } 
} 

интерфейс \ модели \ UsersSearch.php

namespace frontend\models; 

use Yii; 
use yii\base\Model; 
use yii\data\ActiveDataProvider; 
use frontend\models\Users; 

class UsersSearch extends Users 
{ 
    # @inheritdoc 
    public function rules() 
    { 
     return [ 
      [['id', 'phone'], 'integer'], 
      [['username', 'address'], '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 = Users::find()->with('courses')->with('userCourses'); 

     // add conditions that should always apply here 
     $dataProvider = new ActiveDataProvider([ 
      'query' => $query, 
     ]); 

     $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([ 
      'id' => $this->id, 
      'phone' => $this->phone, 
     ]); 

     $query->andFilterWhere(['like', 'username', $this->username]) 
      ->andFilterWhere(['like', 'address', $this->address]); 

     return $dataProvider; 
    } 
} 

интерфейс \ модели \ Courses.php

namespace frontend\models; 

use Yii; 

class Courses extends \yii\db\ActiveRecord 
{ 
    # @inheritdoc 
    public static function tableName() 
    { 
     return 'courses'; 
    } 

    # @inheritdoc 
    public function rules() 
    { 
     return [ 
      [['course'], 'string', 'max' => 255], 
     ]; 
    } 

    # @inheritdoc 
    public function attributeLabels() 
    { 
     return [ 
      'id' => 'ID', 
      'course' => 'Course', 
     ]; 
    } 

    public function getUserCourses() 
    { 
     // one-to-many 
     return $this->hasMany(UserCourses::className(), ['courses_id' => 'id']); 
    } 

    public function getUsers() 
    { 
     // many-to-many: uses userGroups relation above which uses an ActiveRecord class 
     return $this->hasMany(Users::className(), ['id' => 'users_id']) 
      ->via('userCourses'); 
    } 
} 

интерфейс \ модели \ CoursesSearch.php

namespace frontend\models; 

use Yii; 
use yii\base\Model; 
use yii\data\ActiveDataProvider; 
use frontend\models\Courses; 

/** 
* CoursesSearch represents the model behind the search form about `frontend\models\Courses`. 
*/ 
class CoursesSearch extends Courses 
{ 
    /** 
    * @inheritdoc 
    */ 
    public function rules() 
    { 
     return [ 
      [['id'], 'integer'], 
      [['course'], '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 = Courses::find(); 

     // add conditions that should always apply here 

     $dataProvider = new ActiveDataProvider([ 
      'query' => $query, 
     ]); 

     $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([ 
      'id' => $this->id, 
     ]); 

     $query->andFilterWhere(['like', 'course', $this->course]); 

     return $dataProvider; 
    } 
} 

интерфейс \ модели \ UserCourses.php

namespace frontend\models; 

use Yii; 

class UserCourses extends \yii\db\ActiveRecord 
{ 
    # @inheritdoc 
    public static function tableName() 
    { 
     return 'user_cources'; 
    } 

    # @inheritdoc 
    public function rules() 
    { 
     return [ 
      [['users_id', 'courses_id'], 'integer'], 
      [['courses_id'], 'exist', 'skipOnError' => true, 'targetClass' => Courses::className(), 'targetAttribute' => ['courses_id' => 'id']], 
      [['users_id'], 'exist', 'skipOnError' => true, 'targetClass' => Users::className(), 'targetAttribute' => ['users_id' => 'id']], 
     ]; 
    } 

    # @inheritdoc 
    public function attributeLabels() 
    { 
     return [ 
      'id' => 'ID', 
      'users_id' => 'Users ID', 
      'courses_id' => 'Courses ID', 
     ]; 
    } 

    # @return \yii\db\ActiveQuery 
    public function getCourses() 
    { 
     return $this->hasOne(Courses::className(), ['id' => 'courses_id']); //->inverseOf('userCources'); 
    } 

    # @return \yii\db\ActiveQuery 
    public function getUsers() 
    { 
     return $this->hasOne(Users::tableName(), ['id' => 'users_id']); //->inverseOf('userCources'); 
    } 
} 

интерфейс \ Views \ курсы \ index.php

GridView::widget([ 
    'dataProvider' => $dataProvider, 
    // 'filterModel' => $searchModel, 
    'columns' => [ 
     ['class' => 'yii\grid\SerialColumn'], 

     [ 
      "attribute" => "users.username", 
      "value" => "username" 
     ], 
     'course', 

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

интерфейс \ c ontrollers \ CoursesController.php

namespace frontend\controllers; 

use Yii; 
use frontend\models\Courses; 
use frontend\models\CoursesSearch; 
use yii\web\Controller; 
use yii\web\NotFoundHttpException; 
use yii\filters\VerbFilter; 

/** 
* CoursesController implements the CRUD actions for Courses model. 
*/ 
class CoursesController extends Controller 
{ 
    /** 
    * @inheritdoc 
    */ 
    public function behaviors() 
    { 
     return [ 
      'verbs' => [ 
       'class' => VerbFilter::className(), 
       'actions' => [ 
        'delete' => ['POST'], 
       ], 
      ], 
     ]; 
    } 

    /** 
    * Lists all Courses models. 
    * @return mixed 
    */ 
    public function actionIndex() 
    { 
     $searchModel = new CoursesSearch(); 
     $dataProvider = $searchModel->search(Yii::$app->request->queryParams); 

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

    /** 
    * Displays a single Courses model. 
    * @param integer $id 
    * @return mixed 
    */ 
    public function actionView($id) 
    { 
     return $this->render('view', [ 
      'model' => $this->findModel($id), 
     ]); 
    } 

    /** 
    * Creates a new Courses model. 
    * If creation is successful, the browser will be redirected to the 'view' page. 
    * @return mixed 
    */ 
    public function actionCreate() 
    { 
     $model = new Courses(); 

     if ($model->load(Yii::$app->request->post()) && $model->save()) { 
      return $this->redirect(['view', 'id' => $model->id]); 
     } else { 
      return $this->render('create', [ 
       'model' => $model, 
      ]); 
     } 
    } 

    /** 
    * Updates an existing Courses model. 
    * If update is successful, the browser will be redirected to the 'view' page. 
    * @param integer $id 
    * @return mixed 
    */ 
    public function actionUpdate($id) 
    { 
     $model = $this->findModel($id); 

     if ($model->load(Yii::$app->request->post()) && $model->save()) { 
      return $this->redirect(['view', 'id' => $model->id]); 
     } else { 
      return $this->render('update', [ 
       'model' => $model, 
      ]); 
     } 
    } 

    /** 
    * Deletes an existing Courses model. 
    * If deletion is successful, the browser will be redirected to the 'index' page. 
    * @param integer $id 
    * @return mixed 
    */ 
    public function actionDelete($id) 
    { 
     $this->findModel($id)->delete(); 

     return $this->redirect(['index']); 
    } 

    /** 
    * Finds the Courses model based on its primary key value. 
    * If the model is not found, a 404 HTTP exception will be thrown. 
    * @param integer $id 
    * @return Courses the loaded model 
    * @throws NotFoundHttpException if the model cannot be found 
    */ 
    protected function findModel($id) 
    { 
     if (($model = Courses::findOne($id)) !== null) { 
      return $model; 
     } else { 
      throw new NotFoundHttpException('The requested page does not exist.'); 
     } 
    } 
} 

Database

CREATE TABLE IF NOT EXISTS `courses` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `course` varchar(255) DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    KEY `cource` (`course`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=9 ; 

INSERT INTO `courses` (`id`, `course`) VALUES 
(8, 'ASP'), 
(1, 'C'), 
(2, 'C++'), 
(6, 'Java'), 
(3, 'MySql'), 
(4, 'Networking'), 
(7, 'PHP'), 
(5, 'System Administrator'); 

CREATE TABLE IF NOT EXISTS `users` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `username` varchar(255) DEFAULT NULL, 
    `address` varchar(255) DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    KEY `username` (`username`), 
    KEY `address` (`address`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ; 

INSERT INTO `users` (`id`, `username`, `address`) VALUES 
(1, 'Parminder', 'ABC-125'), 
(2, 'Manpreet', 'WZ-128'), 
(3, 'Kanwaljeet', 'NA-123'); 

CREATE TABLE IF NOT EXISTS `user_cources` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `users_id` int(11) DEFAULT NULL, 
    `courses_id` int(11) DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    KEY `users_id` (`users_id`), 
    KEY `courses_id` (`courses_id`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=9 ; 

INSERT INTO `user_cources` (`id`, `users_id`, `courses_id`) VALUES 
(1, 1, 1), 
(2, 1, 2), 
(3, 1, 3), 
(4, 1, 6), 
(5, 1, 7), 
(6, 1, 8), 
(7, 2, 4), 
(8, 2, 5); 

ALTER TABLE `user_cources` 
    ADD CONSTRAINT `FK_uc_courses` FOREIGN KEY (`courses_id`) REFERENCES `courses` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, 
    ADD CONSTRAINT `FK_uc_users` FOREIGN KEY (`users_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE; 
+0

Не могли бы вы выслать код CourseController, определяющий ActiveDataProvider для курсов/index.php – MacGyer

+0

Кстати: у вас есть опечатка в имени вашей таблицы: user_cources должны быть user_courses (здесь нет ошибки, потому что ваша таблица имеет соответствующую имя) – MacGyer

+0

Спасибо MacGyer, я исправлю опечатку в коде. Также я добавил CoursesController, пожалуйста, проверьте. – Pummi

ответ

0

просто чтобы убедиться, попробуйте следующее в интерфейс \ контроллерах \ CoursesController:

public function actionIndex() 
{ 
    $query = frontend\models\Courses::find()->with('users'); 
    $dataProvider = new yii\data\ActiveDataProvider(); 
    $dataProvider->query = $query; 

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

И в вашем интерфейсе \ Виды \ курсы \ index.php:

GridView::widget([ 
    'dataProvider' => $dataProvider, 
    'columns' => [ 
     ['class' => 'yii\grid\SerialColumn'], 

     [ 
      'attribute' => 'users', 
      'value' => 'username', 
     ], 
     'course', 

     ['class' => 'yii\grid\ActionColumn'], 
    ], 
]); 
+0

Спасибо MacGrey, я попробовал ваше решение, но, к сожалению, он все еще не работает. Я создаю репозиторий, чтобы исправить эту проблему. Я тоже буду здесь. – Pummi

+0

Вот репозиторий https: //[email protected]/pammysayshello/yii2-junction-table-issue.git. Пожалуйста, скажите мне, что я делаю неправильно. – Pummi

+0

Эй, ребята, я исправил проблему и обновил репозиторий. Надеюсь, этот пример может помочь кому-то. – Pummi