问题
I have table Lang:
id | lang_name
Table2: Messages:
id | message_code
Table3: Dictionary
id | message_id | lang_id | translation
I want to bring to the gridview with languages. Format:
message_code | en_translation | ..._translation |..._translation
As the number of languages is not known, i pass value of columns in array to gridview.
There is one problem: I need to pass the value of the language id to relation model. I do not know how.
$searchModel = new langmessages_search();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
$columns=array();
$columns[]=array('label'=>'message_code','attribute'=>'message_code');
$languages=Lang::find()->all();
foreach($languages as $language){
$columns[]=array('label'=>$language->name,'attribute'=>'text');
//'attribute'=>'text' ---> need to dynamically create the attribute or pass lang_id
}
I hope you can help.
回答1:
public function actionSearch($name, $email)
{
$model = DynamicModel::validateData(compact('name', 'email'), [
[['name', 'email'], 'string', 'max' => 128],
['email', 'email'],
]);
if ($model->hasErrors()) {
// validation fails
} else {
// validation succeeds
}
}
The above example shows how to validate $name and $email with the help of DynamicModel. The validateData() method creates an instance of DynamicModel, defines the attributes using the given data (name and email in this example), and then calls yii\base\Model::validate().
You can check the validation result by hasErrors(), like you do with a normal model. You may also access the dynamic attributes defined through the model instance, e.g., $model->name and $model->email.
Alternatively, you may use the following more "classic" syntax to perform ad-hoc data validation:
$model = new DynamicModel(compact('name', 'email'));
$model->addRule(['name', 'email'], 'string', ['max' => 128])
->addRule('email', 'email')
->validate();
http://www.yiiframework.com/doc-2.0/yii-base-dynamicmodel.html
回答2:
Your search model could look like this:
class LangMessagesSearch extends Model
{
public $id;
public $messageCode;
private $languages = [];
public function __get($name)
{
if (isset($this->languages[$name])) {
return $this->languages[$name];
}
return null;
}
public function __set($name, $value)
{
return $this->languages[$name] = $value;
}
public function getLanguageAttributes()
{
$languagesList = Lang::find()->all();
$attributes = [];
foreach ($languagesList as $lang) {
$attributes[] = [
'attribute' => $lang,
'format' => 'raw',
'headerOptions' => [
'title' => $lang,
],
'content' => function($model, $key, $index) use ($lang) {
// you can do here something with $lang if you need so
$content = $model->{$lang};
return $content;
}
];
}
return $attributes;
}
public function search($params)
{
// assume that getRecords() implemented here
$records = $this->getRecords($params);
$allModels = [];
foreach ($records as $k => $v) {
$model = new self;
$model->id = $records->id;
$model->messageCode = $records->messageCode;
$allModels[] = $model;
}
return $this->wrapIntoDataProvider($allModels);
}
private function wrapIntoDataProvider($data)
{
$provider = new \app\components\ArrayDataProvider(
[
'allModels' => $data,
'pagination' => [
'pageSize' => 30,
],
]
);
return $provider;
}
}
Finally display grid in the view:
// take just first model in the list
$_model = $dataProvider->allModels[0];
$attributes = array_merge(
[['class' => 'yii\grid\SerialColumn']],
[
'id',
'messageCode'
],
$_model->getLanguageAttributes()
);
echo \yii\grid\GridView::widget([
'dataProvider' => $dataProvider,
'columns' => $attributes
]);
来源:https://stackoverflow.com/questions/27442314/yii2-dynamic-model-attributes