WeSee
WeSee

Reputation: 3762

Yii2: display associative array

What is the easiest way to display an associative array in a table style?

The array is defined as

$data = [ 'name' => 'bert', 'age' => 42 ];

Input validation is not required. The output should look like a GridView (one key/value per line), but a GridView requires a model.

So I could use DynamicModel, ArrayDataProvider or other Yii2 stuff.

I tried a lot but there should be an easy way to get this done.

Upvotes: 2

Views: 3220

Answers (2)

robsch
robsch

Reputation: 9718

If you know the content of the array

You can do it this way and use the features of DetailView, esp. formating. I enhanced your data a little bit. Just copy the code into a view file to get a quick impression.

$myArray = [
   'name'             => 'bert',
   'age'              => 42,
   'My email address' => '[email protected]', //no problems with spaces in the key
   'html'             => '<div style="font-size: 2em">asdf</div>',
];

echo \yii\widgets\DetailView::widget([
    'model'      => $myArray,
    'attributes' => [
        'name',
        'age',
        'My email address:email',
        'html',
        'html:html',
        'html:html:Html with different label',
        [
            'label'     => 'Html self defined',
            'attribute' => 'html', // key in model
            'format'    => 'raw'
        ]
    ]
])

Attributes refers to keys of the model.

Look here how you can use attributes.

If the array is dynamic

i.e. you don't know the content and get different kind of data, you can use the DetailView default formatting (what means format is 'text'). In its simplest way it is:

echo \yii\widgets\DetailView::widget([
    'model'      => $myArray,
    'attributes' => array_keys($myArray),
]);

If you want to control the format more or less, use may want to use this, using format 'raw':

echo \yii\widgets\DetailView::widget([
    'model'      => $myArray,
    'attributes' => array_map(function ($key) {
        return "$key:raw"; 
        // or build some logic for the right format 
        // e.g. use '$key:email' if key contains 'email'
    }, array_keys($myArray)),
]);

Regarding the requirement in your answer of localizing the labels as well, you could do it this way (with default 'text' format):

echo \yii\widgets\DetailView::widget([
    'model'      => $myArray,
    'attributes' => array_map(function ($key) {
        return $key . ':text:' . Yii::t('app', 'label-' . $key);
    }, array_keys($myArray)),
]);

However, note some further logic could be needed if the 'label-' . $key does not exist. Otherwise label-somekey would be shown in the DetailView.

Upvotes: 2

WeSee
WeSee

Reputation: 3762

Found a solution that even works with attribute labels being translated, but is it "the easiest"?

In controller file:

class MyDynModel extends \yii\base\DynamicModel {
    public function generateAttributeLabel($name) {
        return Yii::t('app','label-'.$name);
    }
}

class MyController extends Controller {
    public function actionShow() {
        $data = [ 'name' => 'bert', 'age' => 42 ];
        $dataModel = new MyDynModel($data);
        return $this->render('myview', ['dataModel'=>$dataModel]);
    }
}

In view file "my/myview.php":

echo \yii\widgets\DetailView::widget(['model'=>$dataModel]);

In translation file "messages/en/app.php":

return [
    'label-name' => 'Name',
    'label-age' => 'Age (in Years)',
];

Upvotes: 0

Related Questions