Я пытаюсь отобразить данные в 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;
Не могли бы вы выслать код CourseController, определяющий ActiveDataProvider для курсов/index.php – MacGyer
Кстати: у вас есть опечатка в имени вашей таблицы: user_cources должны быть user_courses (здесь нет ошибки, потому что ваша таблица имеет соответствующую имя) – MacGyer
Спасибо MacGyer, я исправлю опечатку в коде. Также я добавил CoursesController, пожалуйста, проверьте. – Pummi