我有一个模型的网格视图,显示一个属性gender
和一个lang_code
来自 1:n 关系的字段language
。
当我过滤“女性”时,它会显示 310 位女性(总共 600 个条目中)。如果我随后清除过滤器,则会显示 0 个条目(而不是全部 600 个)。
当我lang_code
从视图中删除时,过滤器会在清除后正确重置。
这就是我在 modelSearch.php 中查询 1:n 关系的方式:
public $languages;
public function rules()
{
return [
[[ ...,'languages',...], 'safe'],
];
}
public function search($params)
{
$query = Sprecher::find();
$query = $query->distinct()->joinWith(['languages', ...]);
$dataProvider->sort->attributes['languages'] = [
'asc' => ['language.lang_code' => SORT_ASC],
'desc' => ['language.lang_code' => SORT_DESC],
];
...
$query->andFilterWhere(['in', 'language.lang_code', $this->languages])
...
}
我究竟做错了什么?
编辑:
完整的模型搜索:
<?php
namespace app\models;
use Yii;
use yii\base\Model;
use yii\data\ActiveDataProvider;
use app\models\Sprecher;
/**
* SprecherSearch represents the model behind the search form of `app\models\Sprecher`.
*/
class SprecherSearch extends Sprecher
{
public $languages;
public $dialekte;
public $einsatzbereiche;
public $nationalitaeten;
/**
* @inheritdoc
*/
public function rules()
{
return [
[['id', 'hat_erfahrung_synchron', 'ist_schauspieler', 'ist_ahv_pflichtig', 'braucht_neue_samples'], 'integer'],
[[ 'einsatzbereiche','dialekte','languages','nationalitaeten','vorname', 'nachname', 'gender', 'stimmalter', 'stimmlage', 'stimmcharakter', 'mitglied_verein', 'bemerkungen', 'web', 'studio', 'skype', 'geburtsdatum', 'ahv_nummer'], '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 = Sprecher::find();
// add conditions that should always apply here
$query = $query->distinct()->joinWith(['languages', 'dialekte', 'einsatzbereiche', 'nationalitaeten']);
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
$dataProvider->sort->attributes['languages'] = [
// The tables are the ones our relation are configured to
// in my case they are prefixed with "tbl_"
'asc' => ['language.lang_code' => SORT_ASC],
'desc' => ['language.lang_code' => SORT_DESC],
];
$dataProvider->sort->attributes['dialekte'] = [
// The tables are the ones our relation are configured to
// in my case they are prefixed with "tbl_"
'asc' => ['dialekt.lang_code' => SORT_ASC],
'desc' => ['dialekt.lang_code' => SORT_DESC],
];
$dataProvider->sort->attributes['einsatzbereiche'] = [
// The tables are the ones our relation are configured to
// in my case they are prefixed with "tbl_"
'asc' => ['einsatzbereich.bereich' => SORT_ASC],
'desc' => ['einsatzbereich.bereich' => SORT_DESC],
];
$dataProvider->sort->attributes['nationalitaeten'] = [
// The tables are the ones our relation are configured to
// in my case they are prefixed with "tbl_"
'asc' => ['nationalitaet.code' => SORT_ASC],
'desc' => ['nationalitaet.code' => SORT_DESC],
];
$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,
'hat_erfahrung_synchron' => $this->hat_erfahrung_synchron,
'ist_schauspieler' => $this->ist_schauspieler,
'geburtsdatum' => $this->geburtsdatum,
'ist_ahv_pflichtig' => $this->ist_ahv_pflichtig,
'braucht_neue_samples' => $this->braucht_neue_samples
]);
$query->andFilterWhere(['in', 'gender', $this->gender]);
$query->andFilterWhere(['in', 'stimmalter', $this->stimmalter]);
$query->andFilterWhere(['in', 'stimmlage', $this->stimmlage]);
$query->andFilterWhere(['in', 'stimmcharakter', $this->stimmcharakter]);
$query->andFilterWhere(['like', 'vorname', $this->vorname])
->andFilterWhere(['like', 'nachname', $this->nachname])
->andFilterWhere(['like', 'mitglied_verein', $this->mitglied_verein])
->andFilterWhere(['like', 'bemerkungen', $this->bemerkungen])
->andFilterWhere(['like', 'web', $this->web])
->andFilterWhere(['like', 'studio', $this->studio])
->andFilterWhere(['like', 'skype', $this->skype])
->andFilterWhere(['like', 'ahv_nummer', $this->ahv_nummer])
->andFilterWhere(['in', 'language.lang_code', $this->languages])
->andFilterWhere(['in', 'dialekt.lang_code', $this->dialekte])
->andFilterWhere(['in', 'nationalitaet.code', $this->nationalitaeten])
->andFilterWhere(['in', 'einsatzbereich.bereich', $this->einsatzbereiche]);
return $dataProvider;
}
}
完整型号:
<?php
namespace app\models;
use Yii;
/**
* This is the model class for table "sprecher".
*
* @property int $id
* @property string $vorname
* @property string $nachname
* @property string $gender
* @property string $nationalitaet
* @property string $stimmalter
* @property string $stimmlage
* @property string $stimmcharakter
* @property int $hat_erfahrung_synchron
* @property int $ist_schauspieler
* @property string $mitglied_verein
* @property string $bemerkungen
* @property string $web
* @property string $studio
* @property string $skype
* @property string $geburtsdatum
* @property string $ahv_nummer
* @property int $ist_ahv_pflichtig
* @property string $sprecher_id
* @property string $korrespondenz_lang_code
* @property string $tel
* @property string $tel2
* @property string $tel3
* @property string $email
* @property string $strasse
* @property string $plz_org
* @property string $firma
* @property string $bank
* @property int $ist_vps_mitglied
* @property int $braucht_neue_samples
*
* @property Sample[] $samples
* @property Dialekt[] $dialekte
* @property language[] $languages
* @property Einsatzbereich[] $einsatzbereiche
* @property Nationalitaet[] $nationalitaeten
*/
class Sprecher extends \yii\db\ActiveRecord
{
public $gender_search;
/**
* @var UploadedFile[]
*/
public $imageFiles;
public $selected = false;
private function getSelected() {
return $this->selected;
}
private static $auswahl_liste_id;
public static function getAuswahl_liste_id()
{
return SPRECHER::$auswahl_liste_id;
}
public static function setAuswahl_liste_id($id)
{
Sprecher::$auswahl_liste_id = $id;
}
/**
* @inheritdoc
*/
public static function tableName()
{
return 'sprecher';
}
/**
* @inheritdoc
*/
public function rules()
{
return [
[['vorname', 'nachname', 'hat_erfahrung_synchron', 'ist_schauspieler', 'braucht_neue_samples'], 'required'],
[['hat_erfahrung_synchron', 'ist_schauspieler', 'ist_vps_mitglied', 'ist_ahv_pflichtig', 'braucht_neue_samples'], 'integer'],
[['geburtsdatum'], 'safe'],
[['vorname', 'nachname', 'studio', 'skype'], 'string', 'max' => 64],
[['gender'], 'string', 'max' => 12],
[['stimmalter'], 'string', 'max' => 7],
[['stimmlage', 'stimmcharakter', 'mitglied_verein', 'ahv_nummer'], 'string', 'max' => 32],
[['bemerkungen', 'web'], 'string', 'max' => 255],
[['sprecher_id'], 'string', 'max' => 4],
[['korrespondenz_lang_code', 'tel', 'email', 'strasse', 'plz_org', 'firma', 'bank', 'tel2', 'tel3'], 'string', 'max' => 128],
];
}
/**
* @inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'System ID',
'vorname' => 'Vorname',
'nachname' => 'Nachname',
'gender' => 'Gender',
'stimmalter' => 'Stimmalter',
'stimmlage' => 'Stimmlage',
'stimmcharakter' => 'Stimmcharakter',
'hat_erfahrung_synchron' => 'hat Synchron-Erfahrung',
'ist_schauspieler' => 'Ist Schauspieler',
'mitglied_verein' => 'Mitglied Verein',
'bemerkungen' => 'Bemerkungen',
'web' => 'Web',
'studio' => 'Studio',
'skype' => 'Skype',
'geburtsdatum' => 'Geburtsdatum',
'ahv_nummer' => 'Ahv Nummer',
'ist_ahv_pflichtig' => 'Ist Ahv Pflichtig',
'sprecher_id' => 'Sprecher ID',
'korrespondenz_lang_code' => 'Korrespondenz lang_code',
'tel' => 'Mobile 1',
'tel2' => 'Mobile 2',
'tel3' => 'Fixnet',
'email' => 'Email',
'strasse' => 'Strasse',
'plz_org' => 'Plz Ort',
'firma' => 'Firma',
'bank' => 'Bank',
'ist_vps_mitglied' => 'Ist Vps Mitglied',
'braucht_neue_samples' => 'Braucht neue Samples'
];
}
/**
* @return \yii\db\ActiveQuery
*/
public function getSamples()
{
return $this->hasMany(Sample::className(), ['sprecher_id' => 'id']);
}
/**
* @return \yii\db\ActiveQuery
*/
public function getAusgewaehlteSprechers()
{
return $this->hasMany(AusgewaehlteSprecher::className(), ['sprecher_id' => 'id']);
}
/**
* @return \yii\db\ActiveQuery
*/
public function getAuswahls()
{
return $this->hasMany(Auswahl::className(), ['id' => 'auswahl_id'])->viaTable('ausgewaehlte_sprecher', ['sprecher_id' => 'id']);
}
public function upload()
{
if ($this->validate()) {
foreach ($this->imageFiles as $file) {
$file->saveAs('uploads/' . $file->baseName . '.' . $file->extension);
$sample = new Sample();
$sample->sprecher_id = $this->id;
$sample->url = 'uploads/' . $file->baseName . '.' . $file->extension;
$sample->save();
}
return true;
} else {
return false;
}
}
private $_ganzer_name = null;
public function getGanzer_name() {
return $this->vorname . " " . $this->nachname;
}
/**
* @return \yii\db\ActiveQuery
*/
public function getlanguages()
{
return $this->hasMany(language::className(), ['sprecher_id' => 'id']);
}
public function getlang_coden()
{
return $this->hasMany( language::className(), [ 'id' => 'categoryID' ] )
->via('PeopleCategoriesAssn');
}
public function getAllTel() {
return
( empty($this->tel) == false ?'<span title="mobile 1" class="pre">'.$this->tel.'</span>' . "<br/>" : '').
( empty($this->tel2) == false ?'<span title="mobile 2" class="pre">'.$this->tel2.'</span>' . "<br/>" : '').
( empty($this->tel3) == false ?'<span title="fixnet" class="pre">'.$this->tel3.'</span>' . "<br/>" : '');
}
public function getlanguages_txt() {
$languages = $this->languages;
$languages_array = array();
foreach ($languages as $language) {
$languages_array[] = $language->lang_code;
}
return implode(",", $languages_array);
}
/**
* @return \yii\db\ActiveQuery
*/
public function getDialekte()
{
return $this->hasMany(Dialekt::className(), ['sprecher_id' => 'id']);
}
public function getDialekte_txt() {
$languages = $this->dialekte;
$languages_array = array();
foreach ($languages as $language) {
$languages_array[] = $language->lang_code;
}
return implode(",", $languages_array);
}
/**
* @return \yii\db\ActiveQuery
*/
public function getEinsatzbereiche()
{
return $this->hasMany(Einsatzbereich::className(), ['sprecher_id' => 'id']);
}
public function getEinsatzbereiche_txt()
{
$languages = $this->einsatzbereiche;
$languages_array = array();
foreach ($languages as $language) {
$languages_array[] = $language->bereich;
}
return implode("-", $languages_array);
}
public function getNationalitaeten()
{
return $this->hasMany(Nationalitaet::className(), ['sprecher_id' => 'id']);
}
public function getNationalitaeten_txt()
{
$languages = $this->nationalitaeten;
$languages_array = array();
foreach ($languages as $language) {
$languages_array[] = $language->code;
}
return implode("-", $languages_array);
}
/**
* @inheritdoc
* @return SprecherQuery the active query used by this AR class.
*/
public static function find()
{
return new SprecherQuery(get_called_class());
}
}
使用 GridView 查看:
<?php
use yii\helpers\Html;
use yii\widgets\Pjax;
use kartik\grid\GridView;
use kartik\widgets\Select2;
use yii\helpers\Url;
use yii\helpers\ArrayHelper;
use kartik\widgets\ActiveForm;
use app\models\Sprecher;
/* @var $this yii\web\View */
/* @var $searchModel app\models\SprecherSearch */
/* @var $dataProvider yii\data\ActiveDataProvider */
$this->title = 'Sprecher';
$this->params['breadcrumbs'][] = $this->title;
$this->registerJsFile(
'@web/js/main.js',
['depends' => [\yii\web\JqueryAsset::className()]]
);
?>
<p>
<!-- <?= Html::a('Create Sprecher', ['create'], ['class' => 'btn btn-success']) ?>-->
</p>
<?php $listen = \app\models\Auswahl::find()->all(); ?>
<div class="auswahl-form">
<!-- <?php $form = ActiveForm::begin(); ?>
<?= Html::DropDownList("auswahl", 'titel', ArrayHelper::map($listen, 'id', 'titel'),array('prompt'=>'Liste auswählen:', 'options'=>array((isset($auswahl->id) ? $auswahl->id: 0) => array("selected"=>"selected")))) ?>
<div class="form-group">
<?= Html::submitButton('Save', ['class' => 'btn btn-success']) ?>
</div>
<?php ActiveForm::end(); ?>-->
</div>
<?php
?>
<div class="sprecher-index">
<h1><?= Html::encode($this->title) ?></h1>
<?php
$data = [
'Mann' => 'Mann',
'Frau' => 'Frau',
'Junge' => 'Junge',
'Mädchen' => 'Mädchen',
];
$lang_coden = [];
$query = new yii\db\Query();
$sprach_codes = $query->select(['lang_code'])
->from('languages')
->distinct()
->all();
foreach ($sprach_codes as $sprach_code) {
$lang_coden[$sprach_code["lang_code"]] = $sprach_code["lang_code"];
}
$dialekt_codes = $query->select(['lang_code'])
->from('dialekt')
->distinct()
->all();
$dialekte = [];
foreach ($dialekt_codes as $dialekt_code) {
$dialekte[$dialekt_code["lang_code"]] = $dialekt_code["lang_code"];
}
$einsatzbereich_codes = $query->select(['bereich'])
->from('einsatzbereich')
->distinct()
->all();
$einsatzbereiche = [];
foreach ($einsatzbereich_codes as $einsatzbereich_code) {
$einsatzbereiche[$einsatzbereich_code["bereich"]] = $einsatzbereich_code["bereich"];
}
$nation_codes = $query->select(['code'])
->from('nationalitaet')
->distinct()
->all();
$nationen = [];
foreach ($nation_codes as $nation_code) {
$nationen[$nation_code["code"]] = $nation_code["code"];
}
// Generate a bootstrap responsive striped table with row highlighted on hover
echo GridView::widget([
'dataProvider'=> $dataProvider,
'filterModel' => $searchModel,
'pjax'=>true,
'toolbar'=> [
['content'=>
Html::a('<i class="glyphicon glyphicon-plus"></i>', ['create'], ['data-pjax'=>0,'title'=>'Sprecher erfassen', 'class'=>'btn btn-default', 'title'=>'Reset Grid']).
Html::a('<i class="glyphicon glyphicon-repeat"></i>', ['index'], ['data-pjax'=>0, 'class'=>'btn btn-default', 'title'=>'Reset Grid'])
],
'{export}',
'{toggleData}',
],
'panel'=>[
'type'=>GridView::TYPE_PRIMARY,
'heading' => $this->title,
],
'toggleDataOptions' =>
[
'all' => [
'icon' => 'resize-full',
'label' => 'Alle',
'class' => 'btn btn-default',
'title' => 'Zeige alle Datensätze'
],
'page' => [
'icon' => 'resize-small',
'label' => 'Seiten',
'class' => 'btn btn-default',
'title' => 'Zeige erste Datenseite'
],
],
'columns' => [
[
'class' => '\kartik\grid\CheckboxColumn'
],
'vorname',
'nachname',
[
'attribute' => 'gender',
'filter' => $data,
'filterType' => '\kartik\widgets\Select2',
'filterWidgetOptions' => [
'data' => $data,
'hideSearch'=>true,
'pluginOptions' => [
'allowClear' => true
],
'options' => ['placeholder' => 'Wähle ...', 'multiple' => true, 'hideSearch'=>true,'allowClear' => true,],
]
],
[
'attribute' => 'nationalitaeten',
'label' => 'Nat.',
'filter' => $lang_coden,
'filterType' => '\kartik\widgets\Select2',
'filterWidgetOptions' => [
'data' => $nationen,
'hideSearch'=>true,
'pluginOptions' => [
'allowClear' => true
],
'options' => ['placeholder' => 'Wähle ...', 'multiple' => true, 'hideSearch'=>true,'allowClear' => true,],
],
'value' => 'nationalitaeten_txt'
],
[
'attribute' => 'dialekte',
'filter' => $dialekte,
'filterType' => '\kartik\widgets\Select2',
'filterWidgetOptions' => [
'data' => $dialekte,
'hideSearch'=>true,
'pluginOptions' => [
'allowClear' => true
],
'options' => ['placeholder' => 'Wähle ...', 'multiple' => true, 'hideSearch'=>true,'allowClear' => true,],
],
'value' => 'dialekte_txt'
]
,
[
'attribute' => 'einsatzbereiche',
'label' => 'Bereich',
'filter' => $einsatzbereiche,
'filterType' => '\kartik\widgets\Select2',
'filterWidgetOptions' => [
'data' => $einsatzbereiche,
'hideSearch'=>true,
'pluginOptions' => [
'allowClear' => true
],
'options' => ['placeholder' => 'Wähle ...', 'multiple' => true, 'hideSearch'=>true,'allowClear' => true,],
],
'value' => 'einsatzbereiche_txt'
]
,
[
'attribute' => 'stimmalter',
'filter' => array("0-20"=>"0-20","20-40"=>"20-40","40-60"=>"40-60","60-80"=>"60-80"),
'filterType' => '\kartik\widgets\Select2',
'filterWidgetOptions' => [
'data' => array("0-20"=>"0-20","20-40"=>"20-40","40-60"=>"40-60","60-80"=>"60-80"),
'hideSearch'=>true,
'pluginOptions' => [
'allowClear' => true
],
'options' => ['placeholder' => 'Wähle ...', 'multiple' => true, 'hideSearch'=>true,'allowClear' => true,],
]
],
[
'attribute' => 'stimmlage',
'filter' => array("hoch"=>"hoch","mittel"=>"mittel","tief"=>"tief"),
'filterType' => '\kartik\widgets\Select2',
'filterWidgetOptions' => [
'data' => array("hoch"=>"hoch","mittel"=>"mittel","tief"=>"tief"),
'hideSearch'=>true,
'pluginOptions' => [
'allowClear' => true
],
'options' => ['placeholder' => 'Wähle ...', 'multiple' => true, 'hideSearch'=>true,'allowClear' => true,],
]
],
[
'attribute' => 'stimmcharakter',
'label' => 'Charakter',
'filter' => array("frisch"=>"frisch","hell"=>"hell","neutral"=>"neutral","rauchig"=>"rauchig","seriös"=>"seriös","sonor"=>"sonor"),
'filterType' => '\kartik\widgets\Select2',
'filterWidgetOptions' => [
'data' => array("frisch"=>"frisch","hell"=>"hell","neutral"=>"neutral","rauchig"=>"rauchig","seriös"=>"seriös","sonor"=>"sonor"),
'hideSearch'=>true,
'pluginOptions' => [
'allowClear' => true
],
'options' => ['placeholder' => 'Wähle ...', 'multiple' => true, 'hideSearch'=>true,'allowClear' => true,],
]
],
[
'class' => '\kartik\grid\BooleanColumn',
'attribute' => 'ist_schauspieler',
'label' => 'Actor',
'trueLabel' => 'Yes',
'falseLabel' => 'No'
],
[
'class' => '\kartik\grid\BooleanColumn',
'attribute' => 'hat_erfahrung_synchron',
'label' => 'Sync',
'trueLabel' => 'Yes',
'falseLabel' => 'No',
],
'bemerkungen',
[
'attribute' => 'Samples',
'format' => 'raw',
'value' => function ($model) {
$samples = $model->samples;
return Yii::$app->controller->renderPartial('_samples', [ 'samples' => $samples]);
},
],
[
'attribute' => 'allTel',
'label' => 'Tel',
'format' => 'html',
'value' => 'allTel'
],
[
'class' => '\kartik\grid\BooleanColumn',
'attribute' => 'braucht_neue_samples',
'label' => 'ToDo',
'trueLabel' => 'Yes',
'falseLabel' => 'No',
],
[
'class' => 'yii\grid\ActionColumn',
'buttons' => []
]
],
'responsive'=>true,
'hover'=>true,
'resizableColumns'=>true,
'resizeStorageKey'=>Yii::$app->user->id . '-' . date("m"),
]);
?>
</div>
<script type="text/javascript">
/* $( document ).ready(function() {
var files = [document.getElementById("dragout")],
fileDetails = [];
// Some forward thinking, utilise the custom data attribute to extend attributes available.
if(typeof files[0].dataset === "undefined") {
// Grab it the old way
fileDetails[0] = files[0].getAttribute("data-downloadurl");
} else {
fileDetails[0] = files[0].dataset.downloadurl;
}
files[0].addEventListener("dragstart",function(evt){
evt.dataTransfer.setData("DownloadURL",fileDetails[0]);
},false);
});
*/
</script>